[
  {
    "path": ".gitignore",
    "content": "*.pyc\nbuild/*\ndist/*\nMANIFEST.in\nmocodo.egg-info/*\nparams.json\nREADME.rst\nsandbox/*\nmeta/*\ndoc/mocodo_notebook\ndoc/.ipynb*\nsandbox*.*\npaper/*\n*.lp\n*.log\n.DS_Store\nmagic/build/*\nmagic/dist/*\nmagic/mocodo_magic.egg-info/*\nmagic/README.rst\nweb/sessions/*\nweb/lib/*\n.pytest_cache/*\n.ipynb_checkpoints/*\n*/.ipynb_checkpoints/*\npoetry.lock\nmocodo_web.py\nUntitled.ipynb\n*.vsix\nmocodo/resources/relation_templates/_graph.gv\nmocodo/resources/relation_templates/_graph.svg\nEGC2024\nlooping/\n\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017- Aristide Grange\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "**Octobre 2025.** Basthon prend maintenant en charge Mocodo 4.3.2.\n\n**Mars 2025.** Mocodo [4.3](https://github.com/laowantong/mocodo/releases/tag/4.3.2) commence à surfer sur la vague des IA hallucinogénératives : il peut maintenant composer des _prompts_ à copier-coller sous ChatGPT (ou autre) pour réécrire le MCD en cours avec le type des attributs ou l'explication des cardinalités.\n\n**Septembre 2024.** Basthon prend maintenant en charge Mocodo 4.2.8, qui simplifie l'appel à la fonction `mocodo()` de `mocodo.magic`. Voir l'[exemple mis à jour](https://notebook.basthon.fr/?from=examples/python3-mocodo.ipynb) dans la galerie de Basthon.\n\n**Janvier 2024.** Mocodo [4.2](https://github.com/laowantong/mocodo/releases/tag/4.2.0) est maintenant disponible sous [Basthon](https://basthon.fr). Après [Mocodo _online_](https://www.mocodo.net), Basthon constitue donc une deuxième manière d'utiliser Mocodo sans rien installer. Elle a l'avantage de donner accès à l'intégralité des fonctionnalités du logiciel. Merci à son auteur, Romain Casati !\n\n**Novembre 2023.** Mocodo [4.1](https://github.com/laowantong/mocodo/releases/tag/4.1.0) gère les bibliothèques de MCD. Un enseignant peut par exemple placer sur son propre serveur la correction d'un MCD sous un nom « secret », que le moment venu il communiquera oralement à ses étudiants pour leur permettre de le récupérer (soit sous Mocodo online, soit en ligne de commande).\n\n**Octobre 2023.** Mocodo [4](https://github.com/laowantong/mocodo/releases/tag/4.0.4) introduit la gestion manuelle et automatique des contraintes d'optionalité et d'unicité, améliore les interfaces graphique et en ligne de commande, et ajoute un grand nombre de fonctionnalités : coloration syntaxique, liens de partage, exportation en UML, en notation de Chen et _crow's foot_, génération de MCD aléatoires, décomposition des associations et autres opérations de réécriture.\n\n**Septembre 2022.** Mocodo 3 introduit l'[héritage](https://laowantong.github.io/mocodo/doc/fr_refman.html#Héritage-(ou-spécialisation)), l'[agrégation](https://laowantong.github.io/mocodo/doc/fr_refman.html#Agrégation-(ou-pseudo-entité)), les [calques](https://laowantong.github.io/mocodo/doc/fr_refman.html#Héritage-(ou-spécialisation)), les [sorties PDF et PNG](https://laowantong.github.io/mocodo/doc/fr_refman.html#Héritage-(ou-spécialisation)), etc. : [3.0](https://github.com/laowantong/mocodo/releases/tag/3.0), [3.1](https://github.com/laowantong/mocodo/releases/tag/3.1.0), [3.2](https://github.com/laowantong/mocodo/releases/tag/3.2.0).\n\n------\n\n[Documentation](https://laowantong.github.io/mocodo/doc/fr_refman.html) sur une seule page, incluant la sortie de [`mocodo --help`](https://laowantong.github.io/mocodo/doc/fr_refman.html#mocodo---help) et l'[aide-mémoire des transformations](https://laowantong.github.io/mocodo/doc/fr_refman.html#Aide-mémoire-des-arguments-de---transform).\n\n----\n\n![](logos/banner.svg)\n\nMocodo est un logiciel d'aide à l'enseignement et à l'apprentissage des [bases de données relationnelles](https://fr.wikipedia.org/wiki/Base_de_données_relationnelle).\n\n- En entrée, il prend un [MCD](https://fr.wikipedia.org/wiki/Modèle_entité-association) (modèle conceptuel de données) décrit dans un langage dédié minimaliste.\n- En sortie, il produit un diagramme entité-association et, à la demande, un [MLD](https://fr.wikipedia.org/wiki/Merise_(informatique)#MLD_:_modèle_logique_des_données) (schéma relationnel, sous forme graphique ou textuelle), un [DDL](https://fr.wikipedia.org/wiki/Langage_de_définition_de_données) (script SQL de création de la base), un [diagramme de classes UML](https://fr.wikipedia.org/wiki/Diagramme_de_classes), etc.\n- En bonus, il est capable de réarranger automatiquement votre MCD de façon esthétique, et de lui appliquer des opérations de réécriture qui vont du mondain (typographie) à l'académique (décomposition d'associations), en passant par le merveilleux (inférence de types, génération d'exercices et d'exemples).\n\nVous pouvez utiliser Mocodo :\n\n- sur son site web [Mocodo _online_](https://www.mocodo.net) ;\n- dans un document [Jupyter Notebook](https://jupyter.org), avec ou [sans](https://basthon.fr) installation ;\n- en ligne de commande ;\n- comme une bibliothèque Python.\n\n## Tracé du modèle conceptuel\n\nCi-dessous, un exemple d'utilisation sous Jupyter Notebook. L'appel du programme est en première ligne ; le texte-source proprement dit, lignes suivantes. En sortie, le diagramme conceptuel, égayé au passage par l'option `--colors` :\n\n![png](doc/readme/ccp_mcd.png)\n\n![svg](doc/readme/ccp_mcd.svg)\n\n## Opérations de conversion\n\nOn peut récupérer ce texte-source avec `--input` pour lui appliquer diverses opérations. Ainsi, l'appel suivant génère et affiche son MLD, son diagramme relationnel et son DDL :\n\n```\n%mocodo --input ccp --transform mld diagram ddl --colors desert\n```\n\n---\n\n- **CLIENT** (<u>Réf. client</u>, Nom, Prénom, Adresse)\n- **COMMANDE** (<u>Num. commande</u>, Date, Montant, _#Réf. client_)\n- **INCLURE** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\n- **PRODUIT** (<u>Réf. produit</u>, Libellé, Prix unitaire)\n\n---\n\n![svg](doc/readme/ccp_mld.svg)\n\n---\n\n```sql\nCREATE TABLE CLIENT (\n  PRIMARY KEY (ref_client),\n  ref_client VARCHAR(8) NOT NULL,\n  nom VARCHAR(255),\n  prenom VARCHAR(255),\n  adresse VARCHAR(255)\n);\n\nCREATE TABLE COMMANDE (\n  PRIMARY KEY (num_commande),\n  num_commande VARCHAR(8) NOT NULL,\n  date DATE,\n  montant DECIMAL(10,2),\n  ref_client VARCHAR(8) NOT NULL\n);\n\nCREATE TABLE INCLURE (\n  PRIMARY KEY (num_commande, ref_produit),\n  num_commande VARCHAR(8) NOT NULL,\n  ref_produit VARCHAR(8) NOT NULL,\n  quantite INTEGER\n);\n\nCREATE TABLE PRODUIT (\n  PRIMARY KEY (ref_produit),\n  ref_produit VARCHAR(8) NOT NULL,\n  libelle VARCHAR(50),\n  prix_unitaire DECIMAL(10,2)\n);\n\nALTER TABLE COMMANDE ADD FOREIGN KEY (ref_client) REFERENCES CLIENT (ref_client);\n\nALTER TABLE INCLURE ADD FOREIGN KEY (ref_produit) REFERENCES PRODUIT (ref_produit);\nALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);\n```\n\nDans la suite, pour épargner la frappe, les options `--input` et `--transform` seront respectivement abrégées en `-i` et `-t`.\n\nLes opérations de conversion ne se limitent pas forcément au schéma relationnel. En voici une qui extrait un dictionnaire des données, par défaut sous la forme d'un tableau Markdown à trois colonnes :\n\n```\n%mocodo -i ccp -t data_dict\n```\n\n---\n\n| Entité ou association | Libellé de l'attribut | Type          |\n|:----------------------|:----------------------|:--------------|\n| CLIENT                | Adresse               | VARCHAR(255)  |\n| \"                     | Nom                   | VARCHAR(255)  |\n| \"                     | Prénom                | VARCHAR(255)  |\n| \"                     | Réf. client           | VARCHAR(8)    |\n| COMMANDE              | Date                  | DATE          |\n| \"                     | Montant               | DECIMAL(10,2) |\n| \"                     | Num. commande         | VARCHAR(8)    |\n| INCLURE               | Quantité              | INTEGER       |\n| PRODUIT               | Libellé               | VARCHAR(50)   |\n| \"                     | Prix unitaire         | DECIMAL(10,2) |\n| \"                     | Réf. produit          | VARCHAR(8)    |\n\nUne autre qui transcrit le MCD dans la notation _crow's foot_ (`crow`) pour [Mermaid](http://mermaid.js.org) (`mmd`) :\n\n```\n%mocodo -i ccp -t crow:mmd\n```\n\n---\n\n```mmd\nerDiagram\n  CLIENT {\n    VARCHAR(8) ref_client PK\n    VARCHAR(255) nom\n    VARCHAR(255) prenom\n    VARCHAR(255) adresse\n  }\n  COMMANDE {\n    VARCHAR(8) num_commande PK\n    DATE date\n    DECIMAL(10-2) montant\n  }\n  INCLURE {\n    INTEGER quantite PK\n  }\n  PRODUIT {\n    VARCHAR(8) ref_produit PK\n    VARCHAR(50) libelle\n    DECIMAL(10-2) prix_unitaire\n  }\n  CLIENT ||--o{ COMMANDE: PASSER\n  INCLURE }|..|| COMMANDE: DF\n  INCLURE }o..|| PRODUIT: DF\n\n```\n\nLe rendu des diagrammes décrits dans des langages-tiers (comme Mermaid) n'est pas directement pris en charge, mais peut être délégué (`--defer`) de façon transparente au service web approprié. Dans ce cas, c'est la sortie graphique qui est affichée :\n\n```\n%mocodo -i ccp -t crow:mmd --defer\n```\n\n---\n\n![svg](doc/readme/ccp_erd_crow.svg)\n\n## Opérations de réécriture\n\nUne **réécriture** transforme un MCD Mocodo en un autre MCD Mocodo (au contraire d'une **conversion**, qui produit un animal d'une espèce différente).\n\nHeureusement, l'utilisateur n'a pas à réfléchir si la transformation qu'il souhaite appliquer est une réécriture ou une conversion : dans les deux cas, il invoque `-t` (c'est-à-dire `--transform`), et Mocodo se débrouille.\n\nEn guise de premier exemple de réécriture, mettons les noms des entités et associations (`boxes`) en majuscules, et les libellés (`labels`) en ASCII et _snake case_ :\n\n```\n%mocodo -i ccp -t upper:boxes ascii:labels snake:labels --colors brewer+3\n```\n\n![svg](doc/readme/ccp_mcd_ascii.svg)\n\n---\n\n    %%mocodo --colors brewer+3\n    CLIENT: ref_client [VARCHAR(8)], nom [VARCHAR(255)], prenom [VARCHAR(255)], adresse [VARCHAR(255)]\n    PASSER, 0N CLIENT, 11 COMMANDE\n    COMMANDE: num_commande [VARCHAR(8)], date [DATE], montant [DECIMAL(10,2)]\n    INCLURE, 1N COMMANDE, 0N PRODUIT: quantite [INTEGER]\n    PRODUIT: ref_produit [VARCHAR(8)], libelle [VARCHAR(50)], prix_unitaire [DECIMAL(10,2)]\n\nRemarquez que l'exécution d'une réécriture affiche, au-dessous du diagramme, le code-source résultant. Celui-ci est précédé de la commande magique originale, _privée de l'option `-i` et de toute opération de réécriture_. Ces dispositions permettent de continuer à travailler directement dessus si on le copie-colle dans une autre cellule.\n\nPlusieurs opérations de réécriture de nature sémantique sont également offertes. Par exemple, on peut décomposer un MCD quelconque en un MCD équivalent, mais n'employant que des dépendances fonctionnelles et des entités faibles :\n\n```\n%mocodo -i ccp --select mcd -t explode:weak,arity=2 arrange:wide --seed=3 --colors brewer+3\n```\n\n![svg](doc/readme/ccp_mcd_explode.svg)\n\nNotez la sous-option `arrange:wide`. Elle a procédé à une réorganisation aléatoire des boîtes, ce que l'insertion de deux nouvelles associations de dépendance fonctionnelles avait rendu nécessaire. Quant à l'option `--seed=3`, elle garantit que le résultat sera le même à chaque exécution.\n\nPour vous familiariser avec Mocodo, le plus simple est d'utiliser [sa version en ligne](https://www.mocodo.net). Vous pourrez ensuite vous plonger dans la [documentation](https://laowantong.github.io/mocodo/doc/fr_refman.html).\n"
  },
  {
    "path": "doc/build_doc.sh",
    "content": "# Export directly from the notebook File > Save and export notebook as > HTML\n"
  },
  {
    "path": "doc/examples/four_random_layouts.mcd",
    "content": "::\nTincidunt1, 11 Ante1, 0N Massa1\n::::::\n\nEuismod1, 0N Massa1, 0N Massa1\nMassa1: metus, posuere\nConvallis1, 0N Aliquet1, 0N Ante1: vestibulum\nAnte1: vitae, tempor\n:::\nRisus2, 1N Aliquet2, 0N Massa2\nMassa2: metus, posuere\nEuismod2, 0N Massa2, 0N Massa2\n\n:\nRisus1, 1N Aliquet1, 0N Massa1\nAliquet1: hendrerit, metus, lacus, quis\nRutrum1, 0N Gravida1, 0N Ante1, 0N Aliquet1: faucibus, curae\nGravida1: ornare\n:\nUltrices2, 01 Aliquet2, 0N Aliquet2\nAliquet2: hendrerit, metus, lacus, quis\nConvallis2, 0N Aliquet2, 0N Ante2: vestibulum\nTincidunt2, 11 Ante2, 0N Massa2\n\n::\nUltrices1, 01 Aliquet1, 0N Aliquet1\n:::\nGravida2: ornare\nRutrum2, 0N Gravida2, 0N Ante2, 0N Aliquet2: faucibus, curae\nAnte2: vitae, tempor\n:\n\nUltrices3, 01 Aliquet3, 0N Aliquet3\nAliquet3: hendrerit, metus, lacus, quis\nRisus3, 1N Aliquet3, 0N Massa3\n:::\nRisus4, 1N Aliquet4, 0N Massa4\nAliquet4: hendrerit, metus, lacus, quis\nUltrices4, 01 Aliquet4, 0N Aliquet4\n:\n\nRutrum3, 0N Gravida3, 0N Ante3, 0N Aliquet3: faucibus, curae\nConvallis3, 0N Aliquet3, 0N Ante3: vestibulum\nMassa3: metus, posuere\nEuismod3, 0N Massa3, 0N Massa3\n:\nEuismod4, 0N Massa4, 0N Massa4\nMassa4: metus, posuere\nConvallis4, 0N Aliquet4, 0N Ante4: vestibulum\nRutrum4, 0N Gravida4, 0N Ante4, 0N Aliquet4: faucibus, curae\nGravida4: ornare\n\nGravida3: ornare\nAnte3: vitae, tempor\nTincidunt3, 11 Ante3, 0N Massa3\n:::\nTincidunt4, 11 Ante4, 0N Massa4\nAnte4: vitae, tempor\n::\n"
  },
  {
    "path": "doc/examples/landing.mcd",
    "content": "AYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n"
  },
  {
    "path": "doc/examples/option_syntax_1.abnf",
    "content": "start = opt \" \" (arg *(\",\" arg))\n\narg = subopt [\":\" subarg *(\",\" subarg)]\n\nsubarg = subsubarg [\"=\" subsubopt]\n"
  },
  {
    "path": "doc/examples/option_syntax_2.abnf",
    "content": "start = opt \" \" ((subopt [\":\" (subsubarg [\"=\" subsubopt]) *(\",\" (subsubarg [\"=\" subsubopt]))]) *(\",\" (subopt [\":\" (subsubarg [\"=\" subsubopt]) *(\",\" (subsubarg [\"=\" subsubopt]))])))"
  },
  {
    "path": "doc/fr_cheat_sheet.md",
    "content": "### Opérations de conversion\n\n| Sous-option | Description | Exemples | Explications |\n| :-- | :-- | :-- | :-- |\n| <span style=\"font-family:monospace; font-weight:600\">ast</span> | crée l'arbre de syntaxe abstraite du texte source (pour le débogage) |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">chen</span> | convertit le modèle conceptuel dans la notation de Chen | `` chen `` | sans attributs |\n|  |  | `` chen:attrs `` | avec attributs |\n|  |  | `` chen:attrs --defer `` | calcule le rendu graphique via un service web |\n|  |  | `` chen:layout=circo,mindist=2,scale=0.6 `` | ajoute des options arbitraires pour Graphviz |\n| <span title=\"Alias : crowfoot, crowsfoot.\" style=\"font-family:monospace; font-weight:600\">crow</span> | convertit le modèle conceptuel dans la notation crow's foot | `` crow `` | format Graphviz |\n|  |  | `` crow --defer `` | calcule le rendu graphique via un service web |\n|  |  | `` crow:mmd `` | format Mermaid |\n|  |  | `` crow:mermaid `` | idem |\n| <span style=\"font-family:monospace; font-weight:600\">d2</span> | convertit le modèle conceptuel en un schéma relationnel au format D2 |  |  |\n| <span title=\"Alias : data_dictionary.\" style=\"font-family:monospace; font-weight:600\">data_dict</span> | extrait tous les attributs du MCD dans une table | `` data_dict `` | tableau Markdown, trois colonnes |\n|  |  | `` data_dict:label `` | liste Markdown, une colonne |\n|  |  | `` data_dict:label,type='Description' `` | deux colonnes, un libellé personnalisé |\n|  |  | `` data_dict:label='Attribut',type='Description' `` | deux colonnes, deux libellés personnalisés |\n|  |  | `` data_dict:**box**='Entité ou<br>association',label,`type`=`'Type de données'` `` | mise en forme de certains libellés |\n|  |  | `` data_dict:tsv `` | tableau TSV, trois colonnes |\n|  |  | `` data_dict:tsv,label `` | liste des attributs séparés par des retours à la ligne |\n| <span style=\"font-family:monospace; font-weight:600\">dbml</span> | convertit le modèle conceptuel en un schéma relationnel au format DBML | `` dbml `` | version de base |\n|  |  | `` dbml:b `` | avec _boilerplate_ |\n| <span style=\"font-family:monospace; font-weight:600\">debug</span> | liste des informations internes relatives à la conversion en schéma relationnel |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">dependencies</span> | convertit le modèle conceptuel en un graphe de dépendances |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">diagram</span> | convertit le modèle conceptuel en un diagramme relationnel au format Mocodo | `` diagram `` | version de base |\n|  |  | `` diagram:c `` | avec contraintes d'unicité et d'optionalité |\n| <span style=\"font-family:monospace; font-weight:600\">html</span> | convertit le modèle conceptuel en un schéma relationnel au format HTML | `` html `` | version de base |\n|  |  | `` html:b `` | avec _boilerplate_ |\n|  |  | `` html:c `` | avec contraintes d'unicité et d'optionalité |\n|  |  | `` html:e `` | avec explications |\n|  |  | `` html:bce `` | avec _boilerplate_, contraintes et explications |\n| <span title=\"Alias : tex.\" style=\"font-family:monospace; font-weight:600\">latex</span> | convertit le modèle conceptuel en un schéma relationnel au format LaTeX | `` latex `` | version de base |\n|  |  | `` latex:b `` | avec _boilerplate_ |\n|  |  | `` latex:c `` | avec contraintes d'unicité et d'optionalité |\n|  |  | `` latex:e `` | avec explications |\n|  |  | `` latex:bce `` | avec _boilerplate_, contraintes et explications |\n| <span title=\"Alias : md, mld.\" style=\"font-family:monospace; font-weight:600\">markdown</span> | convertit le modèle conceptuel en un schéma relationnel au format Markdown | `` markdown `` | version de base |\n|  |  | `` markdown:c `` | avec contraintes d'unicité et d'optionalité |\n|  |  | `` markdown:e `` | avec explications |\n|  |  | `` markdown:ce `` | avec contraintes et explications |\n| <span title=\"Alias : ms_sql, sql_server, sqlserver.\" style=\"font-family:monospace; font-weight:600\">mssql</span> | convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server | `` mssql `` | version de base |\n|  |  | `` mssql:b `` | avec _boilerplate_ |\n| <span style=\"font-family:monospace; font-weight:600\">mysql</span> | convertit le modèle conceptuel en un modèle physique pour MySQL | `` mysql `` | version de base |\n|  |  | `` mysql:b `` | avec _boilerplate_ |\n| <span title=\"Alias : oracle_db.\" style=\"font-family:monospace; font-weight:600\">oracle</span> | convertit le modèle conceptuel en un modèle physique pour Oracle DB | `` oracle `` | version de base |\n|  |  | `` oracle:b `` | avec _boilerplate_ |\n| <span title=\"Alias : postgres.\" style=\"font-family:monospace; font-weight:600\">postgresql</span> | convertit le modèle conceptuel en un modèle physique pour PostgreSQL | `` postgresql `` | version de base |\n|  |  | `` postgresql:b `` | avec _boilerplate_ |\n| <span title=\"Alias : chat, chatbot, ia, ai.\" style=\"font-family:monospace; font-weight:600\">prompt</span> | génère un prompt pour demander à une IA de compléter le MCD | `` prompt:cards `` | avec les explications des cardinalités |\n|  |  | `` prompt:types `` | avec les types des attributs |\n| <span title=\"Alias : template, relation_template.\" style=\"font-family:monospace; font-weight:600\">relation</span> | convertit le modèle conceptuel en schéma relationnel avec le gabarit donné | `` relation:path/to/my_template.yaml `` | chemin relatif, extension obligatoire |\n| <span title=\"Alias : url, link, qr, qr_code.\" style=\"font-family:monospace; font-weight:600\">share</span> | encode le MCD dans une URL pour Mocodo online | `` qr --defer `` | génère un QR code via un service web |\n| <span title=\"Alias : ddl.\" style=\"font-family:monospace; font-weight:600\">sql</span> | convertit le modèle conceptuel en un modèle physique pour SQL |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">sqlite</span> | convertit le modèle conceptuel en un modèle physique pour SQLite | `` sqlite `` | version de base |\n|  |  | `` sqlite:b `` | avec _boilerplate_ |\n| <span title=\"Alias : txt.\" style=\"font-family:monospace; font-weight:600\">text</span> | convertit le modèle conceptuel en un schéma relationnel au format texte | `` text `` | version de base |\n|  |  | `` text:c `` | avec contraintes d'unicité et d'optionalité |\n|  |  | `` html:e `` | avec explications |\n|  |  | `` html:ce `` | avec contraintes et explications |\n| <span title=\"Alias : uml, class_diagram.\" style=\"font-family:monospace; font-weight:600\">uml</span> | convertit le modèle conceptuel en diagramme de classes UML | `` uml `` | format PlantUML |\n|  |  | `` uml:plantuml `` | idem |\n|  |  | `` uml --defer `` | calcule le rendu graphique via un service web |\n|  |  | `` uml:plantuml=- `` | supprime les styles par défaut |\n|  |  | `` uml:plantuml='skinparam backgroundColor yellow\\nskinparam classAttributeFontName Arial\\n' `` | ajoute des styles personnalisés |\n\n### Opérations de réécriture\n\n| Sous-option | Description | Exemples | Explications |\n| :-- | :-- | :-- | :-- |\n| <span style=\"font-family:monospace; font-weight:600\">arrange</span> | réarrange la disposition, soit par Branch & Bound, soit avec un algorithme génétique | `` arrange `` | B&B sans contraintes |\n|  |  | `` arrange:timeout=60 `` | B&B limité à une minute |\n|  |  | `` arrange:wide `` | B&B privilégiant la largeur |\n|  |  | `` arrange:current `` | B&B sur la grille courante |\n|  |  | `` arrange:balanced=0 `` | B&B sur la plus petite grille équilibrée |\n|  |  | `` arrange:balanced=1 `` | B&B sur la seconde plus petite grille équilibrée |\n|  |  | `` arrange:algo=ga `` | algorithme génétique |\n| <span style=\"font-family:monospace; font-weight:600\">ascii</span> | réécrit les éléments donnés en ASCII | `` ascii:roles,labels `` | rôles, libellés des boîtes et des attributs en ASCII |\n| <span title=\"Alias : camelcase, camel_case.\" style=\"font-family:monospace; font-weight:600\">camel</span> | réécrit les éléments donnés en camelCase |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">capitalize</span> | réécrit les éléments donnés en capitalisant la première lettre de chaque mot |  |  |\n| <span title=\"Alias : case_fold.\" style=\"font-family:monospace; font-weight:600\">casefold</span> | réécrit les éléments donnés en minuscules, mais plus agressivement que « lower » |  |  |\n| <span title=\"Alias : add, insert, make, guess, infer, complete, new.\" style=\"font-family:monospace; font-weight:600\">create</span> | essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants | `` guess:types `` | deviner les types manquants |\n|  |  | `` create:types= `` | remplacer les types manquants par `[]` |\n|  |  | `` create:types=TODO `` | remplacer les types manquants par `[TODO]` |\n|  |  | `` make:entities `` | réparer l'oubli d'entités référencées dans des associations |\n|  |  | `` create:dfs `` | mettre des DF partout où c'est possible |\n|  |  | `` add:df_arrows `` | ajouter des flèches aux DF 11 |\n|  |  | `` add:cifs `` | ajouter les CIF correspondant aux agrégats |\n|  |  | `` add:cifs=light `` | même chose en visualisation allégée |\n|  |  | `` add:roles `` | mettre comme rôles le nom des associations partout où c'est utile |\n| <span title=\"Alias : del, suppress, erase, remove, hide, empty.\" style=\"font-family:monospace; font-weight:600\">delete</span> | supprime les éléments donnés quand c'est possible | `` empty `` | ne garde que la structure et le nom des boîtes |\n|  |  | `` delete:types,notes,attrs,cards `` | idem |\n|  |  | `` delete:cards `` | remplace les cardinalités par `XX` |\n|  |  | `` delete:card_prefixes `` | supprime les marqueurs d'entités faibles et d'agrégats |\n|  |  | `` delete:dfs `` | supprime les entités indépendantes dont tous les attributs sont identifiants (et les DF qui les relient) |\n| <span style=\"font-family:monospace; font-weight:600\">drain</span> | déplace tout attribut d'association (1,1) vers l'entité appropriée |  |  |\n| <span title=\"Alias : drown_by_numbers, anonymize, anonymise.\" style=\"font-family:monospace; font-weight:600\">drown</span> | remplace tous les noms d'éléments par un libellé générique numéroté |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">echo</span> | réécrit le texte source tel quel |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">explode</span> | décompose toute association n-aire (*,N) en n associations binaires | `` explode arrange `` | décomposer les non-DF ternaires et plus, puis réarranger |\n|  |  | `` explode:arity=3 arrange `` | idem |\n|  |  | `` explode:weak arrange `` | idem, avec création d'entités faibles |\n|  |  | `` explode:arity=2.5 arrange `` | étendre aux non-DF binaires porteuses d'attributs |\n|  |  | `` explode:arity=2 arrange `` | étendre à toutes les non-DF binaires |\n| <span style=\"font-family:monospace; font-weight:600\">fix</span> | essaie de corriger les erreurs courantes dans les éléments donnés | `` fix:cards `` | normaliser les cardinalités en 01, 11, 0N et 1N |\n| <span title=\"Alias : mirror, reflect.\" style=\"font-family:monospace; font-weight:600\">flip</span> | applique au diagramme une symétrie verticale, horizontale ou diagonale | `` flip:v `` | symétrie verticale |\n|  |  | `` flip:h `` | symétrie horizontale |\n|  |  | `` flip:d `` | symétrie selon la seconde diagonale |\n|  |  | `` flip:vhd `` | symétrie selon la première diagonale |\n|  |  | `` flip:dhv `` | idem (ordre indifférent) |\n| <span style=\"font-family:monospace; font-weight:600\">grow</span> | ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations) | `` grow arrange `` | ajouter des éléments avec les paramètres par défaut, puis réarranger |\n|  |  | `` grow:n=10 `` | nombre total d'associations à ajouter (défaut) |\n|  |  | `` grow:arity_1=2 `` | nombre d'associations réflexives (défaut) |\n|  |  | `` grow:arity_3=2 `` | nombre d'associations ternaires (défaut) |\n|  |  | `` grow:arity_4=0 `` | nombre d'associations quaternaires (défaut) |\n|  |  | `` grow:doubles=1 `` | nombre d'associations liant deux mêmes entités (défaut) |\n|  |  | `` grow:composite_ids=1 `` | nombre d'identifiants composites (défaut) |\n|  |  | `` grow:ent_attrs=4 `` | nombre maximal d'attributs par entité (défaut) |\n|  |  | `` grow:assoc_attrs=2 `` | nombre maximal d'attributs par association (défaut) |\n|  |  | `` grow:'*1-*N'=3 `` | nombre d'associations `*1-*N` (défaut) |\n|  |  | `` grow:'01-11'=1 `` | nombre d'associations `01-11` (défaut) |\n|  |  | `` grow:'_11-*N'=1 `` | une entité faible (zéro par défaut) |\n|  |  | `` grow:'/1N-*N'=1 `` | un agrégat (zéro par défaut) |\n|  |  | `` grow:from_scratch arrange `` | à partir d'un MCD vide |\n|  |  | `` grow:grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange `` | créer un MCD d'entraînement à la conversion en relationnel |\n| <span title=\"Alias : lowercase, lower_case.\" style=\"font-family:monospace; font-weight:600\">lower</span> | réécrit les éléments donnés en minuscules | `` lower:attrs,roles `` | attributs et rôles en minuscules |\n| <span title=\"Alias : pascalcase, pascal_case.\" style=\"font-family:monospace; font-weight:600\">pascal</span> | réécrit les élements donnés en PascalCase |  |  |\n| <span title=\"Alias : prepend.\" style=\"font-family:monospace; font-weight:600\">prefix</span> | préfixe les éléments donnés avec la chaîne donnée | `` prefix:roles='-' `` | force les rôles à remplacer le nom des clés étrangères lors du passage au relationnel |\n| <span title=\"Alias : rand, random, randomise, obfuscate, obscure.\" style=\"font-family:monospace; font-weight:600\">randomize</span> | garde la structure, mais randomise les éléments donnés quand c'est possible | `` obfuscate `` | libellés remplacés par du Lorem Ipsum |\n|  |  | `` obfuscate:labels=lorem `` | idem |\n|  |  | `` obfuscate:labels=disparition `` | idem, lexique du roman de Perec |\n|  |  | `` obfuscate:labels=en4 `` | idem, mots anglais de 4 lettres (SFW) |\n|  |  | `` obfuscate:attrs=fr,boxes=fr5 `` | idem, mots français de longueur quelconque pour les attributs, de 5 lettres pour les boîtes |\n|  |  | `` randomize:types `` | types randomisés avec les fréquences de `default_datatypes_fr.tsv`. |\n| <span title=\"Alias : substitute, sub, repl.\" style=\"font-family:monospace; font-weight:600\">replace</span> | réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné | `` replace:boxes='DIRIGER/RÉPONDRE DE' `` | renomme une boîte |\n|  |  | `` replace:texts='personel/personnel' `` | corrige une faute d'orthographe |\n|  |  | `` replace:replace:texts='_/ ' `` | remplace les tirets bas par des espaces |\n|  |  | `` replace:types='VARCHAR/VARCHAR2' `` | modifie un nom de type |\n|  |  | `` replace:cards=0N/1N `` | remplace toutes les cardinalités 0N par 1N |\n|  |  | `` replace:cards=1N//1N `` | crée des agrégats un peu partout |\n|  |  | `` replace:cards='0/X' replace:cards='11/X1' replace:cards='1N/XN' `` | masque les cardinalités minimales |\n|  |  | `` delete:card_prefixes replace:cards=11/_11 `` | ajoute des marqueurs d'entités faibles |\n| <span title=\"Alias : cut, interval.\" style=\"font-family:monospace; font-weight:600\">slice</span> | réécrit les éléments donnés en n'en gardant qu'une tranche donnée | `` slice:boxes=5:10 `` | de l'indice 5 (inclus) à l'indice 10 (exclu) |\n|  |  | `` slice:boxes=5: `` | supprime les 5 premiers caractères |\n|  |  | `` slice:boxes=:5 `` | ne garde que les 5 premiers caractères |\n|  |  | `` slice:boxes=:-5 `` | supprime les 5 derniers caractères |\n|  |  | `` slice:boxes=: `` | équivalent de `echo` |\n|  |  | `` slice:boxes= `` | idem |\n|  |  | `` slice:boxes `` | idem |\n| <span title=\"Alias : snakecase, snake_case.\" style=\"font-family:monospace; font-weight:600\">snake</span> | réécrit les éléments donnés en snake_case |  |  |\n| <span style=\"font-family:monospace; font-weight:600\">split</span> | décompose toute association n-aire (*,1) en n-1 associations binaires | `` split arrange `` | décomposer, puis réarranger |\n| <span title=\"Alias : append.\" style=\"font-family:monospace; font-weight:600\">suffix</span> | suffixe les éléments donnés avec la chaîne donnée | `` suffix:boxes=1 `` | Ajoute un suffixe numérique au nom des boîtes en vue de mettre un MCD et sa copie sur le même diagramme. |\n| <span title=\"Alias : swap_case.\" style=\"font-family:monospace; font-weight:600\">swapcase</span> | réécrit les éléments donnés en inversant la casse de chaque lettre |  |  |\n| <span title=\"Alias : titlecase, title_case.\" style=\"font-family:monospace; font-weight:600\">title</span> | réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule |  |  |\n| <span title=\"Alias : trunc, shorten.\" style=\"font-family:monospace; font-weight:600\">truncate</span> | tronque les éléments donnés à la longueur donnée (par défaut : 64) | `` truncate:boxes=10 `` | tronque les noms des boîtes à 10 caractères |\n| <span title=\"Alias : uppercase, upper_case.\" style=\"font-family:monospace; font-weight:600\">upper</span> | réécrit les éléments donnés en majuscules | `` upper:boxes `` | noms des boîtes en majuscules |"
  },
  {
    "path": "doc/fr_refman.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n<head><meta charset=\"utf-8\"/>\n<meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\"/>\n<title>fr_refman</title><script src=\"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js\"></script>\n<style type=\"text/css\">\n    pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.highlight .hll { background-color: var(--jp-cell-editor-active-background) }\n.highlight { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\n.highlight .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\n.highlight .err { color: var(--jp-mirror-editor-error-color) } /* Error */\n.highlight .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\n.highlight .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\n.highlight .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\n.highlight .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\n.highlight .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\n.highlight .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\n.highlight .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\n.highlight .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\n.highlight .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\n.highlight .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\n.highlight .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\n.highlight .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\n.highlight .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\n.highlight .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\n.highlight .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\n.highlight .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\n.highlight .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\n.highlight .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\n.highlight .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\n.highlight .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\n.highlight .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\n.highlight .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\n.highlight .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\n.highlight .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\n.highlight .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\n.highlight .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\n.highlight .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\n.highlight .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\n.highlight .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\n.highlight .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\n.highlight .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\n.highlight .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\n.highlight .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\n.highlight .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\n.highlight .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\n.highlight .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\n.highlight .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\n.highlight .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\n.highlight .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */\n  </style>\n<style type=\"text/css\">\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*\n * Mozilla scrollbar styling\n */\n\n/* use standard opaque scrollbars for most nodes */\n[data-jp-theme-scrollbars='true'] {\n  scrollbar-color: rgb(var(--jp-scrollbar-thumb-color))\n    var(--jp-scrollbar-background-color);\n}\n\n/* for code nodes, use a transparent style of scrollbar. These selectors\n * will match lower in the tree, and so will override the above */\n[data-jp-theme-scrollbars='true'] .CodeMirror-hscrollbar,\n[data-jp-theme-scrollbars='true'] .CodeMirror-vscrollbar {\n  scrollbar-color: rgba(var(--jp-scrollbar-thumb-color), 0.5) transparent;\n}\n\n/* tiny scrollbar */\n\n.jp-scrollbar-tiny {\n  scrollbar-color: rgba(var(--jp-scrollbar-thumb-color), 0.5) transparent;\n  scrollbar-width: thin;\n}\n\n/* tiny scrollbar */\n\n.jp-scrollbar-tiny::-webkit-scrollbar,\n.jp-scrollbar-tiny::-webkit-scrollbar-corner {\n  background-color: transparent;\n  height: 4px;\n  width: 4px;\n}\n\n.jp-scrollbar-tiny::-webkit-scrollbar-thumb {\n  background: rgba(var(--jp-scrollbar-thumb-color), 0.5);\n}\n\n.jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal {\n  border-left: 0 solid transparent;\n  border-right: 0 solid transparent;\n}\n\n.jp-scrollbar-tiny::-webkit-scrollbar-track:vertical {\n  border-top: 0 solid transparent;\n  border-bottom: 0 solid transparent;\n}\n\n/*\n * Lumino\n */\n\n.lm-ScrollBar[data-orientation='horizontal'] {\n  min-height: 16px;\n  max-height: 16px;\n  min-width: 45px;\n  border-top: 1px solid #a0a0a0;\n}\n\n.lm-ScrollBar[data-orientation='vertical'] {\n  min-width: 16px;\n  max-width: 16px;\n  min-height: 45px;\n  border-left: 1px solid #a0a0a0;\n}\n\n.lm-ScrollBar-button {\n  background-color: #f0f0f0;\n  background-position: center center;\n  min-height: 15px;\n  max-height: 15px;\n  min-width: 15px;\n  max-width: 15px;\n}\n\n.lm-ScrollBar-button:hover {\n  background-color: #dadada;\n}\n\n.lm-ScrollBar-button.lm-mod-active {\n  background-color: #cdcdcd;\n}\n\n.lm-ScrollBar-track {\n  background: #f0f0f0;\n}\n\n.lm-ScrollBar-thumb {\n  background: #cdcdcd;\n}\n\n.lm-ScrollBar-thumb:hover {\n  background: #bababa;\n}\n\n.lm-ScrollBar-thumb.lm-mod-active {\n  background: #a0a0a0;\n}\n\n.lm-ScrollBar[data-orientation='horizontal'] .lm-ScrollBar-thumb {\n  height: 100%;\n  min-width: 15px;\n  border-left: 1px solid #a0a0a0;\n  border-right: 1px solid #a0a0a0;\n}\n\n.lm-ScrollBar[data-orientation='vertical'] .lm-ScrollBar-thumb {\n  width: 100%;\n  min-height: 15px;\n  border-top: 1px solid #a0a0a0;\n  border-bottom: 1px solid #a0a0a0;\n}\n\n.lm-ScrollBar[data-orientation='horizontal']\n  .lm-ScrollBar-button[data-action='decrement'] {\n  background-image: var(--jp-icon-caret-left);\n  background-size: 17px;\n}\n\n.lm-ScrollBar[data-orientation='horizontal']\n  .lm-ScrollBar-button[data-action='increment'] {\n  background-image: var(--jp-icon-caret-right);\n  background-size: 17px;\n}\n\n.lm-ScrollBar[data-orientation='vertical']\n  .lm-ScrollBar-button[data-action='decrement'] {\n  background-image: var(--jp-icon-caret-up);\n  background-size: 17px;\n}\n\n.lm-ScrollBar[data-orientation='vertical']\n  .lm-ScrollBar-button[data-action='increment'] {\n  background-image: var(--jp-icon-caret-down);\n  background-size: 17px;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-Widget {\n  box-sizing: border-box;\n  position: relative;\n  overflow: hidden;\n}\n\n.lm-Widget.lm-mod-hidden {\n  display: none !important;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.lm-AccordionPanel[data-orientation='horizontal'] > .lm-AccordionPanel-title {\n  /* Title is rotated for horizontal accordion panel using CSS */\n  display: block;\n  transform-origin: top left;\n  transform: rotate(-90deg) translate(-100%);\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-CommandPalette {\n  display: flex;\n  flex-direction: column;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.lm-CommandPalette-search {\n  flex: 0 0 auto;\n}\n\n.lm-CommandPalette-content {\n  flex: 1 1 auto;\n  margin: 0;\n  padding: 0;\n  min-height: 0;\n  overflow: auto;\n  list-style-type: none;\n}\n\n.lm-CommandPalette-header {\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.lm-CommandPalette-item {\n  display: flex;\n  flex-direction: row;\n}\n\n.lm-CommandPalette-itemIcon {\n  flex: 0 0 auto;\n}\n\n.lm-CommandPalette-itemContent {\n  flex: 1 1 auto;\n  overflow: hidden;\n}\n\n.lm-CommandPalette-itemShortcut {\n  flex: 0 0 auto;\n}\n\n.lm-CommandPalette-itemLabel {\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.lm-close-icon {\n  border: 1px solid transparent;\n  background-color: transparent;\n  position: absolute;\n  z-index: 1;\n  right: 3%;\n  top: 0;\n  bottom: 0;\n  margin: auto;\n  padding: 7px 0;\n  display: none;\n  vertical-align: middle;\n  outline: 0;\n  cursor: pointer;\n}\n.lm-close-icon:after {\n  content: 'X';\n  display: block;\n  width: 15px;\n  height: 15px;\n  text-align: center;\n  color: #000;\n  font-weight: normal;\n  font-size: 12px;\n  cursor: pointer;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-DockPanel {\n  z-index: 0;\n}\n\n.lm-DockPanel-widget {\n  z-index: 0;\n}\n\n.lm-DockPanel-tabBar {\n  z-index: 1;\n}\n\n.lm-DockPanel-handle {\n  z-index: 2;\n}\n\n.lm-DockPanel-handle.lm-mod-hidden {\n  display: none !important;\n}\n\n.lm-DockPanel-handle:after {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  content: '';\n}\n\n.lm-DockPanel-handle[data-orientation='horizontal'] {\n  cursor: ew-resize;\n}\n\n.lm-DockPanel-handle[data-orientation='vertical'] {\n  cursor: ns-resize;\n}\n\n.lm-DockPanel-handle[data-orientation='horizontal']:after {\n  left: 50%;\n  min-width: 8px;\n  transform: translateX(-50%);\n}\n\n.lm-DockPanel-handle[data-orientation='vertical']:after {\n  top: 50%;\n  min-height: 8px;\n  transform: translateY(-50%);\n}\n\n.lm-DockPanel-overlay {\n  z-index: 3;\n  box-sizing: border-box;\n  pointer-events: none;\n}\n\n.lm-DockPanel-overlay.lm-mod-hidden {\n  display: none !important;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-Menu {\n  z-index: 10000;\n  position: absolute;\n  white-space: nowrap;\n  overflow-x: hidden;\n  overflow-y: auto;\n  outline: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.lm-Menu-content {\n  margin: 0;\n  padding: 0;\n  display: table;\n  list-style-type: none;\n}\n\n.lm-Menu-item {\n  display: table-row;\n}\n\n.lm-Menu-item.lm-mod-hidden,\n.lm-Menu-item.lm-mod-collapsed {\n  display: none !important;\n}\n\n.lm-Menu-itemIcon,\n.lm-Menu-itemSubmenuIcon {\n  display: table-cell;\n  text-align: center;\n}\n\n.lm-Menu-itemLabel {\n  display: table-cell;\n  text-align: left;\n}\n\n.lm-Menu-itemShortcut {\n  display: table-cell;\n  text-align: right;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-MenuBar {\n  outline: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.lm-MenuBar-content {\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: row;\n  list-style-type: none;\n}\n\n.lm-MenuBar-item {\n  box-sizing: border-box;\n}\n\n.lm-MenuBar-itemIcon,\n.lm-MenuBar-itemLabel {\n  display: inline-block;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-ScrollBar {\n  display: flex;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.lm-ScrollBar[data-orientation='horizontal'] {\n  flex-direction: row;\n}\n\n.lm-ScrollBar[data-orientation='vertical'] {\n  flex-direction: column;\n}\n\n.lm-ScrollBar-button {\n  box-sizing: border-box;\n  flex: 0 0 auto;\n}\n\n.lm-ScrollBar-track {\n  box-sizing: border-box;\n  position: relative;\n  overflow: hidden;\n  flex: 1 1 auto;\n}\n\n.lm-ScrollBar-thumb {\n  box-sizing: border-box;\n  position: absolute;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-SplitPanel-child {\n  z-index: 0;\n}\n\n.lm-SplitPanel-handle {\n  z-index: 1;\n}\n\n.lm-SplitPanel-handle.lm-mod-hidden {\n  display: none !important;\n}\n\n.lm-SplitPanel-handle:after {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  content: '';\n}\n\n.lm-SplitPanel[data-orientation='horizontal'] > .lm-SplitPanel-handle {\n  cursor: ew-resize;\n}\n\n.lm-SplitPanel[data-orientation='vertical'] > .lm-SplitPanel-handle {\n  cursor: ns-resize;\n}\n\n.lm-SplitPanel[data-orientation='horizontal'] > .lm-SplitPanel-handle:after {\n  left: 50%;\n  min-width: 8px;\n  transform: translateX(-50%);\n}\n\n.lm-SplitPanel[data-orientation='vertical'] > .lm-SplitPanel-handle:after {\n  top: 50%;\n  min-height: 8px;\n  transform: translateY(-50%);\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-TabBar {\n  display: flex;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.lm-TabBar[data-orientation='horizontal'] {\n  flex-direction: row;\n  align-items: flex-end;\n}\n\n.lm-TabBar[data-orientation='vertical'] {\n  flex-direction: column;\n  align-items: flex-end;\n}\n\n.lm-TabBar-content {\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex: 1 1 auto;\n  list-style-type: none;\n}\n\n.lm-TabBar[data-orientation='horizontal'] > .lm-TabBar-content {\n  flex-direction: row;\n}\n\n.lm-TabBar[data-orientation='vertical'] > .lm-TabBar-content {\n  flex-direction: column;\n}\n\n.lm-TabBar-tab {\n  display: flex;\n  flex-direction: row;\n  box-sizing: border-box;\n  overflow: hidden;\n  touch-action: none; /* Disable native Drag/Drop */\n}\n\n.lm-TabBar-tabIcon,\n.lm-TabBar-tabCloseIcon {\n  flex: 0 0 auto;\n}\n\n.lm-TabBar-tabLabel {\n  flex: 1 1 auto;\n  overflow: hidden;\n  white-space: nowrap;\n}\n\n.lm-TabBar-tabInput {\n  user-select: all;\n  width: 100%;\n  box-sizing: border-box;\n}\n\n.lm-TabBar-tab.lm-mod-hidden {\n  display: none !important;\n}\n\n.lm-TabBar-addButton.lm-mod-hidden {\n  display: none !important;\n}\n\n.lm-TabBar.lm-mod-dragging .lm-TabBar-tab {\n  position: relative;\n}\n\n.lm-TabBar.lm-mod-dragging[data-orientation='horizontal'] .lm-TabBar-tab {\n  left: 0;\n  transition: left 150ms ease;\n}\n\n.lm-TabBar.lm-mod-dragging[data-orientation='vertical'] .lm-TabBar-tab {\n  top: 0;\n  transition: top 150ms ease;\n}\n\n.lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging {\n  transition: none;\n}\n\n.lm-TabBar-tabLabel .lm-TabBar-tabInput {\n  user-select: all;\n  width: 100%;\n  box-sizing: border-box;\n  background: inherit;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-TabPanel-tabBar {\n  z-index: 1;\n}\n\n.lm-TabPanel-stackedPanel {\n  z-index: 0;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-Collapse {\n  display: flex;\n  flex-direction: column;\n  align-items: stretch;\n}\n\n.jp-Collapse-header {\n  padding: 1px 12px;\n  background-color: var(--jp-layout-color1);\n  border-bottom: solid var(--jp-border-width) var(--jp-border-color2);\n  color: var(--jp-ui-font-color1);\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  font-size: var(--jp-ui-font-size0);\n  font-weight: 600;\n  text-transform: uppercase;\n  user-select: none;\n}\n\n.jp-Collapser-icon {\n  height: 16px;\n}\n\n.jp-Collapse-header-collapsed .jp-Collapser-icon {\n  transform: rotate(-90deg);\n  margin: auto 0;\n}\n\n.jp-Collapser-title {\n  line-height: 25px;\n}\n\n.jp-Collapse-contents {\n  padding: 0 12px;\n  background-color: var(--jp-layout-color1);\n  color: var(--jp-ui-font-color1);\n  overflow: auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/* This file was auto-generated by ensureUiComponents() in @jupyterlab/buildutils */\n\n/**\n * (DEPRECATED) Support for consuming icons as CSS background images\n */\n\n/* Icons urls */\n\n:root {\n  --jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);\n  --jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);\n  --jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);\n  --jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);\n  --jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-code-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CiAgICA8cGF0aCBkPSJNNi41OSwzLjQxTDIsOEw2LjU5LDEyLjZMOCwxMS4xOEw0LjgyLDhMOCw0LjgyTDYuNTksMy40MU0xMi40MSwzLjQxTDExLDQuODJMMTQuMTgsOEwxMSwxMS4xOEwxMi40MSwxMi42TDE3LDhMMTIuNDEsMy40MU0yMS41OSwxMS41OUwxMy41LDE5LjY4TDkuODMsMTZMOC40MiwxNy40MUwxMy41LDIyLjVMMjMsMTNMMjEuNTksMTEuNTlaIiAvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);\n  --jp-icon-collapse-all: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTggMmMxIDAgMTEgMCAxMiAwczIgMSAyIDJjMCAxIDAgMTEgMCAxMnMwIDItMiAyQzIwIDE0IDIwIDQgMjAgNFMxMCA0IDYgNGMwLTIgMS0yIDItMnoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTE4IDhjMC0xLTEtMi0yLTJTNSA2IDQgNnMtMiAxLTIgMmMwIDEgMCAxMSAwIDEyczEgMiAyIDJjMSAwIDExIDAgMTIgMHMyLTEgMi0yYzAtMSAwLTExIDAtMTJ6bS0yIDB2MTJINFY4eiIgLz4KICAgICAgICA8cGF0aCBkPSJNNiAxM3YyaDh2LTJ6IiAvPgogICAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);\n  --jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-error: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjE5IiByPSIyIi8+PHBhdGggZD0iTTEwIDNoNHYxMmgtNHoiLz48L2c+CjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiLz4KPC9zdmc+Cg==);\n  --jp-icon-expand-all: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTggMmMxIDAgMTEgMCAxMiAwczIgMSAyIDJjMCAxIDAgMTEgMCAxMnMwIDItMiAyQzIwIDE0IDIwIDQgMjAgNFMxMCA0IDYgNGMwLTIgMS0yIDItMnoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTE4IDhjMC0xLTEtMi0yLTJTNSA2IDQgNnMtMiAxLTIgMmMwIDEgMCAxMSAwIDEyczEgMiAyIDJjMSAwIDExIDAgMTIgMHMyLTEgMi0yYzAtMSAwLTExIDAtMTJ6bS0yIDB2MTJINFY4eiIgLz4KICAgICAgICA8cGF0aCBkPSJNMTEgMTBIOXYzSDZ2MmgzdjNoMnYtM2gzdi0yaC0zeiIgLz4KICAgIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);\n  --jp-icon-filter-dot: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTE0LDEyVjE5Ljg4QzE0LjA0LDIwLjE4IDEzLjk0LDIwLjUgMTMuNzEsMjAuNzFDMTMuMzIsMjEuMSAxMi42OSwyMS4xIDEyLjMsMjAuNzFMMTAuMjksMTguN0MxMC4wNiwxOC40NyA5Ljk2LDE4LjE2IDEwLDE3Ljg3VjEySDkuOTdMNC4yMSw0LjYyQzMuODcsNC4xOSAzLjk1LDMuNTYgNC4zOCwzLjIyQzQuNTcsMy4wOCA0Ljc4LDMgNSwzVjNIMTlWM0MxOS4yMiwzIDE5LjQzLDMuMDggMTkuNjIsMy4yMkMyMC4wNSwzLjU2IDIwLjEzLDQuMTkgMTkuNzksNC42MkwxNC4wMywxMkgxNFoiIC8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWRvdCIgZmlsbD0iI0ZGRiI+CiAgICA8Y2lyY2xlIGN4PSIxOCIgY3k9IjE3IiByPSIzIj48L2NpcmNsZT4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-filter: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTE0LDEyVjE5Ljg4QzE0LjA0LDIwLjE4IDEzLjk0LDIwLjUgMTMuNzEsMjAuNzFDMTMuMzIsMjEuMSAxMi42OSwyMS4xIDEyLjMsMjAuNzFMMTAuMjksMTguN0MxMC4wNiwxOC40NyA5Ljk2LDE4LjE2IDEwLDE3Ljg3VjEySDkuOTdMNC4yMSw0LjYyQzMuODcsNC4xOSAzLjk1LDMuNTYgNC4zOCwzLjIyQzQuNTcsMy4wOCA0Ljc4LDMgNSwzVjNIMTlWM0MxOS4yMiwzIDE5LjQzLDMuMDggMTkuNjIsMy4yMkMyMC4wNSwzLjU2IDIwLjEzLDQuMTkgMTkuNzksNC42MkwxNC4wMywxMkgxNFoiIC8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);\n  --jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);\n  --jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUwLjk3OCA1MC45NzgiPgoJPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KCQk8cGF0aCBkPSJNNDMuNTIsNy40NThDMzguNzExLDIuNjQ4LDMyLjMwNywwLDI1LjQ4OSwwQzE4LjY3LDAsMTIuMjY2LDIuNjQ4LDcuNDU4LDcuNDU4CgkJCWMtOS45NDMsOS45NDEtOS45NDMsMjYuMTE5LDAsMzYuMDYyYzQuODA5LDQuODA5LDExLjIxMiw3LjQ1NiwxOC4wMzEsNy40NThjMCwwLDAuMDAxLDAsMC4wMDIsMAoJCQljNi44MTYsMCwxMy4yMjEtMi42NDgsMTguMDI5LTcuNDU4YzQuODA5LTQuODA5LDcuNDU3LTExLjIxMiw3LjQ1Ny0xOC4wM0M1MC45NzcsMTguNjcsNDguMzI4LDEyLjI2Niw0My41Miw3LjQ1OHoKCQkJIE00Mi4xMDYsNDIuMTA1Yy00LjQzMiw0LjQzMS0xMC4zMzIsNi44NzItMTYuNjE1LDYuODcyaC0wLjAwMmMtNi4yODUtMC4wMDEtMTIuMTg3LTIuNDQxLTE2LjYxNy02Ljg3MgoJCQljLTkuMTYyLTkuMTYzLTkuMTYyLTI0LjA3MSwwLTMzLjIzM0MxMy4zMDMsNC40NCwxOS4yMDQsMiwyNS40ODksMmM2LjI4NCwwLDEyLjE4NiwyLjQ0LDE2LjYxNyw2Ljg3MgoJCQljNC40MzEsNC40MzEsNi44NzEsMTAuMzMyLDYuODcxLDE2LjYxN0M0OC45NzcsMzEuNzcyLDQ2LjUzNiwzNy42NzUsNDIuMTA2LDQyLjEwNXoiLz4KCQk8cGF0aCBkPSJNMjMuNTc4LDMyLjIxOGMtMC4wMjMtMS43MzQsMC4xNDMtMy4wNTksMC40OTYtMy45NzJjMC4zNTMtMC45MTMsMS4xMS0xLjk5NywyLjI3Mi0zLjI1MwoJCQljMC40NjgtMC41MzYsMC45MjMtMS4wNjIsMS4zNjctMS41NzVjMC42MjYtMC43NTMsMS4xMDQtMS40NzgsMS40MzYtMi4xNzVjMC4zMzEtMC43MDcsMC40OTUtMS41NDEsMC40OTUtMi41CgkJCWMwLTEuMDk2LTAuMjYtMi4wODgtMC43NzktMi45NzljLTAuNTY1LTAuODc5LTEuNTAxLTEuMzM2LTIuODA2LTEuMzY5Yy0xLjgwMiwwLjA1Ny0yLjk4NSwwLjY2Ny0zLjU1LDEuODMyCgkJCWMtMC4zMDEsMC41MzUtMC41MDMsMS4xNDEtMC42MDcsMS44MTRjLTAuMTM5LDAuNzA3LTAuMjA3LDEuNDMyLTAuMjA3LDIuMTc0aC0yLjkzN2MtMC4wOTEtMi4yMDgsMC40MDctNC4xMTQsMS40OTMtNS43MTkKCQkJYzEuMDYyLTEuNjQsMi44NTUtMi40ODEsNS4zNzgtMi41MjdjMi4xNiwwLjAyMywzLjg3NCwwLjYwOCw1LjE0MSwxLjc1OGMxLjI3OCwxLjE2LDEuOTI5LDIuNzY0LDEuOTUsNC44MTEKCQkJYzAsMS4xNDItMC4xMzcsMi4xMTEtMC40MSwyLjkxMWMtMC4zMDksMC44NDUtMC43MzEsMS41OTMtMS4yNjgsMi4yNDNjLTAuNDkyLDAuNjUtMS4wNjgsMS4zMTgtMS43MywyLjAwMgoJCQljLTAuNjUsMC42OTctMS4zMTMsMS40NzktMS45ODcsMi4zNDZjLTAuMjM5LDAuMzc3LTAuNDI5LDAuNzc3LTAuNTY1LDEuMTk5Yy0wLjE2LDAuOTU5LTAuMjE3LDEuOTUxLTAuMTcxLDIuOTc5CgkJCUMyNi41ODksMzIuMjE4LDIzLjU3OCwzMi4yMTgsMjMuNTc4LDMyLjIxOHogTTIzLjU3OCwzOC4yMnYtMy40ODRoMy4wNzZ2My40ODRIMjMuNTc4eiIvPgoJPC9nPgo8L3N2Zz4K);\n  --jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);\n  --jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);\n  --jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);\n  --jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);\n  --jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);\n  --jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4K);\n  --jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);\n  --jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);\n  --jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);\n  --jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);\n  --jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);\n  --jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);\n  --jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);\n  --jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);\n  --jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);\n  --jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);\n  --jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);\n  --jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);\n  --jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);\n  --jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4K);\n  --jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);\n  --jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-word: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KIDxnIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzQxNDE0MSI+CiAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiA8L2c+CiA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSguNDMgLjA0MDEpIiBmaWxsPSIjZmZmIj4KICA8cGF0aCBkPSJtNC4xNCA4Ljc2cTAuMDY4Mi0xLjg5IDIuNDItMS44OSAxLjE2IDAgMS42OCAwLjQyIDAuNTY3IDAuNDEgMC41NjcgMS4xNnYzLjQ3cTAgMC40NjIgMC41MTQgMC40NjIgMC4xMDMgMCAwLjItMC4wMjMxdjAuNzE0cS0wLjM5OSAwLjEwMy0wLjY1MSAwLjEwMy0wLjQ1MiAwLTAuNjkzLTAuMjItMC4yMzEtMC4yLTAuMjg0LTAuNjYyLTAuOTU2IDAuODcyLTIgMC44NzItMC45MDMgMC0xLjQ3LTAuNDcyLTAuNTI1LTAuNDcyLTAuNTI1LTEuMjYgMC0wLjI2MiAwLjA0NTItMC40NzIgMC4wNTY3LTAuMjIgMC4xMTYtMC4zNzggMC4wNjgyLTAuMTY4IDAuMjMxLTAuMzA0IDAuMTU4LTAuMTQ3IDAuMjYyLTAuMjQyIDAuMTE2LTAuMDkxNCAwLjM2OC0wLjE2OCAwLjI2Mi0wLjA5MTQgMC4zOTktMC4xMjYgMC4xMzYtMC4wNDUyIDAuNDcyLTAuMTAzIDAuMzM2LTAuMDU3OCAwLjUwNC0wLjA3OTggMC4xNTgtMC4wMjMxIDAuNTY3LTAuMDc5OCAwLjU1Ni0wLjA2ODIgMC43NzctMC4yMjEgMC4yMi0wLjE1MiAwLjIyLTAuNDQxdi0wLjI1MnEwLTAuNDMtMC4zNTctMC42NjItMC4zMzYtMC4yMzEtMC45NzYtMC4yMzEtMC42NjIgMC0wLjk5OCAwLjI2Mi0wLjMzNiAwLjI1Mi0wLjM5OSAwLjc5OHptMS44OSAzLjY4cTAuNzg4IDAgMS4yNi0wLjQxIDAuNTA0LTAuNDIgMC41MDQtMC45MDN2LTEuMDVxLTAuMjg0IDAuMTM2LTAuODYxIDAuMjMxLTAuNTY3IDAuMDkxNC0wLjk4NyAwLjE1OC0wLjQyIDAuMDY4Mi0wLjc2NiAwLjMyNi0wLjMzNiAwLjI1Mi0wLjMzNiAwLjcwNHQwLjMwNCAwLjcwNCAwLjg2MSAwLjI1MnoiIHN0cm9rZS13aWR0aD0iMS4wNSIvPgogIDxwYXRoIGQ9Im0xMCA0LjU2aDAuOTQ1djMuMTVxMC42NTEtMC45NzYgMS44OS0wLjk3NiAxLjE2IDAgMS44OSAwLjg0IDAuNjgyIDAuODQgMC42ODIgMi4zMSAwIDEuNDctMC43MDQgMi40Mi0wLjcwNCAwLjg4Mi0xLjg5IDAuODgyLTEuMjYgMC0xLjg5LTEuMDJ2MC43NjZoLTAuODV6bTIuNjIgMy4wNHEtMC43NDYgMC0xLjE2IDAuNjQtMC40NTIgMC42My0wLjQ1MiAxLjY4IDAgMS4wNSAwLjQ1MiAxLjY4dDEuMTYgMC42M3EwLjc3NyAwIDEuMjYtMC42MyAwLjQ5NC0wLjY0IDAuNDk0LTEuNjggMC0xLjA1LTAuNDcyLTEuNjgtMC40NjItMC42NC0xLjI2LTAuNjR6IiBzdHJva2Utd2lkdGg9IjEuMDUiLz4KICA8cGF0aCBkPSJtMi43MyAxNS44IDEzLjYgMC4wMDgxYzAuMDA2OSAwIDAtMi42IDAtMi42IDAtMC4wMDc4LTEuMTUgMC0xLjE1IDAtMC4wMDY5IDAtMC4wMDgzIDEuNS0wLjAwODMgMS41LTJlLTMgLTAuMDAxNC0xMS4zLTAuMDAxNC0xMS4zLTAuMDAxNGwtMC4wMDU5Mi0xLjVjMC0wLjAwNzgtMS4xNyAwLjAwMTMtMS4xNyAwLjAwMTN6IiBzdHJva2Utd2lkdGg9Ii45NzUiLz4KIDwvZz4KPC9zdmc+Cg==);\n  --jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K);\n}\n\n/* Icon CSS class declarations */\n\n.jp-AddAboveIcon {\n  background-image: var(--jp-icon-add-above);\n}\n\n.jp-AddBelowIcon {\n  background-image: var(--jp-icon-add-below);\n}\n\n.jp-AddIcon {\n  background-image: var(--jp-icon-add);\n}\n\n.jp-BellIcon {\n  background-image: var(--jp-icon-bell);\n}\n\n.jp-BugDotIcon {\n  background-image: var(--jp-icon-bug-dot);\n}\n\n.jp-BugIcon {\n  background-image: var(--jp-icon-bug);\n}\n\n.jp-BuildIcon {\n  background-image: var(--jp-icon-build);\n}\n\n.jp-CaretDownEmptyIcon {\n  background-image: var(--jp-icon-caret-down-empty);\n}\n\n.jp-CaretDownEmptyThinIcon {\n  background-image: var(--jp-icon-caret-down-empty-thin);\n}\n\n.jp-CaretDownIcon {\n  background-image: var(--jp-icon-caret-down);\n}\n\n.jp-CaretLeftIcon {\n  background-image: var(--jp-icon-caret-left);\n}\n\n.jp-CaretRightIcon {\n  background-image: var(--jp-icon-caret-right);\n}\n\n.jp-CaretUpEmptyThinIcon {\n  background-image: var(--jp-icon-caret-up-empty-thin);\n}\n\n.jp-CaretUpIcon {\n  background-image: var(--jp-icon-caret-up);\n}\n\n.jp-CaseSensitiveIcon {\n  background-image: var(--jp-icon-case-sensitive);\n}\n\n.jp-CheckIcon {\n  background-image: var(--jp-icon-check);\n}\n\n.jp-CircleEmptyIcon {\n  background-image: var(--jp-icon-circle-empty);\n}\n\n.jp-CircleIcon {\n  background-image: var(--jp-icon-circle);\n}\n\n.jp-ClearIcon {\n  background-image: var(--jp-icon-clear);\n}\n\n.jp-CloseIcon {\n  background-image: var(--jp-icon-close);\n}\n\n.jp-CodeCheckIcon {\n  background-image: var(--jp-icon-code-check);\n}\n\n.jp-CodeIcon {\n  background-image: var(--jp-icon-code);\n}\n\n.jp-CollapseAllIcon {\n  background-image: var(--jp-icon-collapse-all);\n}\n\n.jp-ConsoleIcon {\n  background-image: var(--jp-icon-console);\n}\n\n.jp-CopyIcon {\n  background-image: var(--jp-icon-copy);\n}\n\n.jp-CopyrightIcon {\n  background-image: var(--jp-icon-copyright);\n}\n\n.jp-CutIcon {\n  background-image: var(--jp-icon-cut);\n}\n\n.jp-DeleteIcon {\n  background-image: var(--jp-icon-delete);\n}\n\n.jp-DownloadIcon {\n  background-image: var(--jp-icon-download);\n}\n\n.jp-DuplicateIcon {\n  background-image: var(--jp-icon-duplicate);\n}\n\n.jp-EditIcon {\n  background-image: var(--jp-icon-edit);\n}\n\n.jp-EllipsesIcon {\n  background-image: var(--jp-icon-ellipses);\n}\n\n.jp-ErrorIcon {\n  background-image: var(--jp-icon-error);\n}\n\n.jp-ExpandAllIcon {\n  background-image: var(--jp-icon-expand-all);\n}\n\n.jp-ExtensionIcon {\n  background-image: var(--jp-icon-extension);\n}\n\n.jp-FastForwardIcon {\n  background-image: var(--jp-icon-fast-forward);\n}\n\n.jp-FileIcon {\n  background-image: var(--jp-icon-file);\n}\n\n.jp-FileUploadIcon {\n  background-image: var(--jp-icon-file-upload);\n}\n\n.jp-FilterDotIcon {\n  background-image: var(--jp-icon-filter-dot);\n}\n\n.jp-FilterIcon {\n  background-image: var(--jp-icon-filter);\n}\n\n.jp-FilterListIcon {\n  background-image: var(--jp-icon-filter-list);\n}\n\n.jp-FolderFavoriteIcon {\n  background-image: var(--jp-icon-folder-favorite);\n}\n\n.jp-FolderIcon {\n  background-image: var(--jp-icon-folder);\n}\n\n.jp-HomeIcon {\n  background-image: var(--jp-icon-home);\n}\n\n.jp-Html5Icon {\n  background-image: var(--jp-icon-html5);\n}\n\n.jp-ImageIcon {\n  background-image: var(--jp-icon-image);\n}\n\n.jp-InfoIcon {\n  background-image: var(--jp-icon-info);\n}\n\n.jp-InspectorIcon {\n  background-image: var(--jp-icon-inspector);\n}\n\n.jp-JsonIcon {\n  background-image: var(--jp-icon-json);\n}\n\n.jp-JuliaIcon {\n  background-image: var(--jp-icon-julia);\n}\n\n.jp-JupyterFaviconIcon {\n  background-image: var(--jp-icon-jupyter-favicon);\n}\n\n.jp-JupyterIcon {\n  background-image: var(--jp-icon-jupyter);\n}\n\n.jp-JupyterlabWordmarkIcon {\n  background-image: var(--jp-icon-jupyterlab-wordmark);\n}\n\n.jp-KernelIcon {\n  background-image: var(--jp-icon-kernel);\n}\n\n.jp-KeyboardIcon {\n  background-image: var(--jp-icon-keyboard);\n}\n\n.jp-LaunchIcon {\n  background-image: var(--jp-icon-launch);\n}\n\n.jp-LauncherIcon {\n  background-image: var(--jp-icon-launcher);\n}\n\n.jp-LineFormIcon {\n  background-image: var(--jp-icon-line-form);\n}\n\n.jp-LinkIcon {\n  background-image: var(--jp-icon-link);\n}\n\n.jp-ListIcon {\n  background-image: var(--jp-icon-list);\n}\n\n.jp-MarkdownIcon {\n  background-image: var(--jp-icon-markdown);\n}\n\n.jp-MoveDownIcon {\n  background-image: var(--jp-icon-move-down);\n}\n\n.jp-MoveUpIcon {\n  background-image: var(--jp-icon-move-up);\n}\n\n.jp-NewFolderIcon {\n  background-image: var(--jp-icon-new-folder);\n}\n\n.jp-NotTrustedIcon {\n  background-image: var(--jp-icon-not-trusted);\n}\n\n.jp-NotebookIcon {\n  background-image: var(--jp-icon-notebook);\n}\n\n.jp-NumberingIcon {\n  background-image: var(--jp-icon-numbering);\n}\n\n.jp-OfflineBoltIcon {\n  background-image: var(--jp-icon-offline-bolt);\n}\n\n.jp-PaletteIcon {\n  background-image: var(--jp-icon-palette);\n}\n\n.jp-PasteIcon {\n  background-image: var(--jp-icon-paste);\n}\n\n.jp-PdfIcon {\n  background-image: var(--jp-icon-pdf);\n}\n\n.jp-PythonIcon {\n  background-image: var(--jp-icon-python);\n}\n\n.jp-RKernelIcon {\n  background-image: var(--jp-icon-r-kernel);\n}\n\n.jp-ReactIcon {\n  background-image: var(--jp-icon-react);\n}\n\n.jp-RedoIcon {\n  background-image: var(--jp-icon-redo);\n}\n\n.jp-RefreshIcon {\n  background-image: var(--jp-icon-refresh);\n}\n\n.jp-RegexIcon {\n  background-image: var(--jp-icon-regex);\n}\n\n.jp-RunIcon {\n  background-image: var(--jp-icon-run);\n}\n\n.jp-RunningIcon {\n  background-image: var(--jp-icon-running);\n}\n\n.jp-SaveIcon {\n  background-image: var(--jp-icon-save);\n}\n\n.jp-SearchIcon {\n  background-image: var(--jp-icon-search);\n}\n\n.jp-SettingsIcon {\n  background-image: var(--jp-icon-settings);\n}\n\n.jp-ShareIcon {\n  background-image: var(--jp-icon-share);\n}\n\n.jp-SpreadsheetIcon {\n  background-image: var(--jp-icon-spreadsheet);\n}\n\n.jp-StopIcon {\n  background-image: var(--jp-icon-stop);\n}\n\n.jp-TabIcon {\n  background-image: var(--jp-icon-tab);\n}\n\n.jp-TableRowsIcon {\n  background-image: var(--jp-icon-table-rows);\n}\n\n.jp-TagIcon {\n  background-image: var(--jp-icon-tag);\n}\n\n.jp-TerminalIcon {\n  background-image: var(--jp-icon-terminal);\n}\n\n.jp-TextEditorIcon {\n  background-image: var(--jp-icon-text-editor);\n}\n\n.jp-TocIcon {\n  background-image: var(--jp-icon-toc);\n}\n\n.jp-TreeViewIcon {\n  background-image: var(--jp-icon-tree-view);\n}\n\n.jp-TrustedIcon {\n  background-image: var(--jp-icon-trusted);\n}\n\n.jp-UndoIcon {\n  background-image: var(--jp-icon-undo);\n}\n\n.jp-UserIcon {\n  background-image: var(--jp-icon-user);\n}\n\n.jp-UsersIcon {\n  background-image: var(--jp-icon-users);\n}\n\n.jp-VegaIcon {\n  background-image: var(--jp-icon-vega);\n}\n\n.jp-WordIcon {\n  background-image: var(--jp-icon-word);\n}\n\n.jp-YamlIcon {\n  background-image: var(--jp-icon-yaml);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/**\n * (DEPRECATED) Support for consuming icons as CSS background images\n */\n\n.jp-Icon,\n.jp-MaterialIcon {\n  background-position: center;\n  background-repeat: no-repeat;\n  background-size: 16px;\n  min-width: 16px;\n  min-height: 16px;\n}\n\n.jp-Icon-cover {\n  background-position: center;\n  background-repeat: no-repeat;\n  background-size: cover;\n}\n\n/**\n * (DEPRECATED) Support for specific CSS icon sizes\n */\n\n.jp-Icon-16 {\n  background-size: 16px;\n  min-width: 16px;\n  min-height: 16px;\n}\n\n.jp-Icon-18 {\n  background-size: 18px;\n  min-width: 18px;\n  min-height: 18px;\n}\n\n.jp-Icon-20 {\n  background-size: 20px;\n  min-width: 20px;\n  min-height: 20px;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.lm-TabBar .lm-TabBar-addButton {\n  align-items: center;\n  display: flex;\n  padding: 4px;\n  padding-bottom: 5px;\n  margin-right: 1px;\n  background-color: var(--jp-layout-color2);\n}\n\n.lm-TabBar .lm-TabBar-addButton:hover {\n  background-color: var(--jp-layout-color1);\n}\n\n.lm-DockPanel-tabBar .lm-TabBar-tab {\n  width: var(--jp-private-horizontal-tab-width);\n}\n\n.lm-DockPanel-tabBar .lm-TabBar-content {\n  flex: unset;\n}\n\n.lm-DockPanel-tabBar[data-orientation='horizontal'] {\n  flex: 1 1 auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/**\n * Support for icons as inline SVG HTMLElements\n */\n\n/* recolor the primary elements of an icon */\n.jp-icon0[fill] {\n  fill: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon1[fill] {\n  fill: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon2[fill] {\n  fill: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon3[fill] {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon4[fill] {\n  fill: var(--jp-inverse-layout-color4);\n}\n\n.jp-icon0[stroke] {\n  stroke: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon1[stroke] {\n  stroke: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon2[stroke] {\n  stroke: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon3[stroke] {\n  stroke: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon4[stroke] {\n  stroke: var(--jp-inverse-layout-color4);\n}\n\n/* recolor the accent elements of an icon */\n.jp-icon-accent0[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.jp-icon-accent1[fill] {\n  fill: var(--jp-layout-color1);\n}\n\n.jp-icon-accent2[fill] {\n  fill: var(--jp-layout-color2);\n}\n\n.jp-icon-accent3[fill] {\n  fill: var(--jp-layout-color3);\n}\n\n.jp-icon-accent4[fill] {\n  fill: var(--jp-layout-color4);\n}\n\n.jp-icon-accent0[stroke] {\n  stroke: var(--jp-layout-color0);\n}\n\n.jp-icon-accent1[stroke] {\n  stroke: var(--jp-layout-color1);\n}\n\n.jp-icon-accent2[stroke] {\n  stroke: var(--jp-layout-color2);\n}\n\n.jp-icon-accent3[stroke] {\n  stroke: var(--jp-layout-color3);\n}\n\n.jp-icon-accent4[stroke] {\n  stroke: var(--jp-layout-color4);\n}\n\n/* set the color of an icon to transparent */\n.jp-icon-none[fill] {\n  fill: none;\n}\n\n.jp-icon-none[stroke] {\n  stroke: none;\n}\n\n/* brand icon colors. Same for light and dark */\n.jp-icon-brand0[fill] {\n  fill: var(--jp-brand-color0);\n}\n\n.jp-icon-brand1[fill] {\n  fill: var(--jp-brand-color1);\n}\n\n.jp-icon-brand2[fill] {\n  fill: var(--jp-brand-color2);\n}\n\n.jp-icon-brand3[fill] {\n  fill: var(--jp-brand-color3);\n}\n\n.jp-icon-brand4[fill] {\n  fill: var(--jp-brand-color4);\n}\n\n.jp-icon-brand0[stroke] {\n  stroke: var(--jp-brand-color0);\n}\n\n.jp-icon-brand1[stroke] {\n  stroke: var(--jp-brand-color1);\n}\n\n.jp-icon-brand2[stroke] {\n  stroke: var(--jp-brand-color2);\n}\n\n.jp-icon-brand3[stroke] {\n  stroke: var(--jp-brand-color3);\n}\n\n.jp-icon-brand4[stroke] {\n  stroke: var(--jp-brand-color4);\n}\n\n/* warn icon colors. Same for light and dark */\n.jp-icon-warn0[fill] {\n  fill: var(--jp-warn-color0);\n}\n\n.jp-icon-warn1[fill] {\n  fill: var(--jp-warn-color1);\n}\n\n.jp-icon-warn2[fill] {\n  fill: var(--jp-warn-color2);\n}\n\n.jp-icon-warn3[fill] {\n  fill: var(--jp-warn-color3);\n}\n\n.jp-icon-warn0[stroke] {\n  stroke: var(--jp-warn-color0);\n}\n\n.jp-icon-warn1[stroke] {\n  stroke: var(--jp-warn-color1);\n}\n\n.jp-icon-warn2[stroke] {\n  stroke: var(--jp-warn-color2);\n}\n\n.jp-icon-warn3[stroke] {\n  stroke: var(--jp-warn-color3);\n}\n\n/* icon colors that contrast well with each other and most backgrounds */\n.jp-icon-contrast0[fill] {\n  fill: var(--jp-icon-contrast-color0);\n}\n\n.jp-icon-contrast1[fill] {\n  fill: var(--jp-icon-contrast-color1);\n}\n\n.jp-icon-contrast2[fill] {\n  fill: var(--jp-icon-contrast-color2);\n}\n\n.jp-icon-contrast3[fill] {\n  fill: var(--jp-icon-contrast-color3);\n}\n\n.jp-icon-contrast0[stroke] {\n  stroke: var(--jp-icon-contrast-color0);\n}\n\n.jp-icon-contrast1[stroke] {\n  stroke: var(--jp-icon-contrast-color1);\n}\n\n.jp-icon-contrast2[stroke] {\n  stroke: var(--jp-icon-contrast-color2);\n}\n\n.jp-icon-contrast3[stroke] {\n  stroke: var(--jp-icon-contrast-color3);\n}\n\n.jp-icon-dot[fill] {\n  fill: var(--jp-warn-color0);\n}\n\n.jp-jupyter-icon-color[fill] {\n  fill: var(--jp-jupyter-icon-color, var(--jp-warn-color0));\n}\n\n.jp-notebook-icon-color[fill] {\n  fill: var(--jp-notebook-icon-color, var(--jp-warn-color0));\n}\n\n.jp-json-icon-color[fill] {\n  fill: var(--jp-json-icon-color, var(--jp-warn-color1));\n}\n\n.jp-console-icon-color[fill] {\n  fill: var(--jp-console-icon-color, white);\n}\n\n.jp-console-icon-background-color[fill] {\n  fill: var(--jp-console-icon-background-color, var(--jp-brand-color1));\n}\n\n.jp-terminal-icon-color[fill] {\n  fill: var(--jp-terminal-icon-color, var(--jp-layout-color2));\n}\n\n.jp-terminal-icon-background-color[fill] {\n  fill: var(\n    --jp-terminal-icon-background-color,\n    var(--jp-inverse-layout-color2)\n  );\n}\n\n.jp-text-editor-icon-color[fill] {\n  fill: var(--jp-text-editor-icon-color, var(--jp-inverse-layout-color3));\n}\n\n.jp-inspector-icon-color[fill] {\n  fill: var(--jp-inspector-icon-color, var(--jp-inverse-layout-color3));\n}\n\n/* CSS for icons in selected filebrowser listing items */\n.jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill] {\n  fill: #fff;\n}\n\n.jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill] {\n  fill: var(--jp-brand-color1);\n}\n\n/* stylelint-disable selector-max-class, selector-max-compound-selectors */\n\n/**\n* TODO: come up with non css-hack solution for showing the busy icon on top\n*  of the close icon\n* CSS for complex behavior of close icon of tabs in the main area tabbar\n*/\n.lm-DockPanel-tabBar\n  .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty\n  > .lm-TabBar-tabCloseIcon\n  > :not(:hover)\n  > .jp-icon3[fill] {\n  fill: none;\n}\n\n.lm-DockPanel-tabBar\n  .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty\n  > .lm-TabBar-tabCloseIcon\n  > :not(:hover)\n  > .jp-icon-busy[fill] {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n/* stylelint-enable selector-max-class, selector-max-compound-selectors */\n\n/* CSS for icons in status bar */\n#jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill] {\n  fill: #fff;\n}\n\n#jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill] {\n  fill: var(--jp-brand-color1);\n}\n\n/* special handling for splash icon CSS. While the theme CSS reloads during\n   splash, the splash icon can loose theming. To prevent that, we set a\n   default for its color variable */\n:root {\n  --jp-warn-color0: var(--md-orange-700);\n}\n\n/* not sure what to do with this one, used in filebrowser listing */\n.jp-DragIcon {\n  margin-right: 4px;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/**\n * Support for alt colors for icons as inline SVG HTMLElements\n */\n\n/* alt recolor the primary elements of an icon */\n.jp-icon-alt .jp-icon0[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.jp-icon-alt .jp-icon1[fill] {\n  fill: var(--jp-layout-color1);\n}\n\n.jp-icon-alt .jp-icon2[fill] {\n  fill: var(--jp-layout-color2);\n}\n\n.jp-icon-alt .jp-icon3[fill] {\n  fill: var(--jp-layout-color3);\n}\n\n.jp-icon-alt .jp-icon4[fill] {\n  fill: var(--jp-layout-color4);\n}\n\n.jp-icon-alt .jp-icon0[stroke] {\n  stroke: var(--jp-layout-color0);\n}\n\n.jp-icon-alt .jp-icon1[stroke] {\n  stroke: var(--jp-layout-color1);\n}\n\n.jp-icon-alt .jp-icon2[stroke] {\n  stroke: var(--jp-layout-color2);\n}\n\n.jp-icon-alt .jp-icon3[stroke] {\n  stroke: var(--jp-layout-color3);\n}\n\n.jp-icon-alt .jp-icon4[stroke] {\n  stroke: var(--jp-layout-color4);\n}\n\n/* alt recolor the accent elements of an icon */\n.jp-icon-alt .jp-icon-accent0[fill] {\n  fill: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-alt .jp-icon-accent1[fill] {\n  fill: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-alt .jp-icon-accent2[fill] {\n  fill: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-alt .jp-icon-accent3[fill] {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-alt .jp-icon-accent4[fill] {\n  fill: var(--jp-inverse-layout-color4);\n}\n\n.jp-icon-alt .jp-icon-accent0[stroke] {\n  stroke: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-alt .jp-icon-accent1[stroke] {\n  stroke: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-alt .jp-icon-accent2[stroke] {\n  stroke: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-alt .jp-icon-accent3[stroke] {\n  stroke: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-alt .jp-icon-accent4[stroke] {\n  stroke: var(--jp-inverse-layout-color4);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content {\n  display: none !important;\n}\n\n/**\n * Support for hover colors for icons as inline SVG HTMLElements\n */\n\n/**\n * regular colors\n */\n\n/* recolor the primary elements of an icon */\n.jp-icon-hover :hover .jp-icon0-hover[fill] {\n  fill: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-hover :hover .jp-icon1-hover[fill] {\n  fill: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-hover :hover .jp-icon2-hover[fill] {\n  fill: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-hover :hover .jp-icon3-hover[fill] {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-hover :hover .jp-icon4-hover[fill] {\n  fill: var(--jp-inverse-layout-color4);\n}\n\n.jp-icon-hover :hover .jp-icon0-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-hover :hover .jp-icon1-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-hover :hover .jp-icon2-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-hover :hover .jp-icon3-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-hover :hover .jp-icon4-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color4);\n}\n\n/* recolor the accent elements of an icon */\n.jp-icon-hover :hover .jp-icon-accent0-hover[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.jp-icon-hover :hover .jp-icon-accent1-hover[fill] {\n  fill: var(--jp-layout-color1);\n}\n\n.jp-icon-hover :hover .jp-icon-accent2-hover[fill] {\n  fill: var(--jp-layout-color2);\n}\n\n.jp-icon-hover :hover .jp-icon-accent3-hover[fill] {\n  fill: var(--jp-layout-color3);\n}\n\n.jp-icon-hover :hover .jp-icon-accent4-hover[fill] {\n  fill: var(--jp-layout-color4);\n}\n\n.jp-icon-hover :hover .jp-icon-accent0-hover[stroke] {\n  stroke: var(--jp-layout-color0);\n}\n\n.jp-icon-hover :hover .jp-icon-accent1-hover[stroke] {\n  stroke: var(--jp-layout-color1);\n}\n\n.jp-icon-hover :hover .jp-icon-accent2-hover[stroke] {\n  stroke: var(--jp-layout-color2);\n}\n\n.jp-icon-hover :hover .jp-icon-accent3-hover[stroke] {\n  stroke: var(--jp-layout-color3);\n}\n\n.jp-icon-hover :hover .jp-icon-accent4-hover[stroke] {\n  stroke: var(--jp-layout-color4);\n}\n\n/* set the color of an icon to transparent */\n.jp-icon-hover :hover .jp-icon-none-hover[fill] {\n  fill: none;\n}\n\n.jp-icon-hover :hover .jp-icon-none-hover[stroke] {\n  stroke: none;\n}\n\n/**\n * inverse colors\n */\n\n/* inverse recolor the primary elements of an icon */\n.jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill] {\n  fill: var(--jp-layout-color1);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill] {\n  fill: var(--jp-layout-color2);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill] {\n  fill: var(--jp-layout-color3);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill] {\n  fill: var(--jp-layout-color4);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke] {\n  stroke: var(--jp-layout-color0);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke] {\n  stroke: var(--jp-layout-color1);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke] {\n  stroke: var(--jp-layout-color2);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke] {\n  stroke: var(--jp-layout-color3);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke] {\n  stroke: var(--jp-layout-color4);\n}\n\n/* inverse recolor the accent elements of an icon */\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill] {\n  fill: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill] {\n  fill: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill] {\n  fill: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill] {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill] {\n  fill: var(--jp-inverse-layout-color4);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color0);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color1);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color2);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color3);\n}\n\n.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke] {\n  stroke: var(--jp-inverse-layout-color4);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-IFrame {\n  width: 100%;\n  height: 100%;\n}\n\n.jp-IFrame > iframe {\n  border: none;\n}\n\n/*\nWhen drag events occur, `lm-mod-override-cursor` is added to the body.\nBecause iframes steal all cursor events, the following two rules are necessary\nto suppress pointer events while resize drags are occurring. There may be a\nbetter solution to this problem.\n*/\nbody.lm-mod-override-cursor .jp-IFrame {\n  position: relative;\n}\n\nbody.lm-mod-override-cursor .jp-IFrame::before {\n  content: '';\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background: transparent;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2016, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-HoverBox {\n  position: fixed;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-FormGroup-content fieldset {\n  border: none;\n  padding: 0;\n  min-width: 0;\n  width: 100%;\n}\n\n/* stylelint-disable selector-max-type */\n\n.jp-FormGroup-content fieldset .jp-inputFieldWrapper input,\n.jp-FormGroup-content fieldset .jp-inputFieldWrapper select,\n.jp-FormGroup-content fieldset .jp-inputFieldWrapper textarea {\n  font-size: var(--jp-content-font-size2);\n  border-color: var(--jp-input-border-color);\n  border-style: solid;\n  border-radius: var(--jp-border-radius);\n  border-width: 1px;\n  padding: 6px 8px;\n  background: none;\n  color: var(--jp-ui-font-color0);\n  height: inherit;\n}\n\n.jp-FormGroup-content fieldset input[type='checkbox'] {\n  position: relative;\n  top: 2px;\n  margin-left: 0;\n}\n\n.jp-FormGroup-content button.jp-mod-styled {\n  cursor: pointer;\n}\n\n.jp-FormGroup-content .checkbox label {\n  cursor: pointer;\n  font-size: var(--jp-content-font-size1);\n}\n\n.jp-FormGroup-content .jp-root > fieldset > legend {\n  display: none;\n}\n\n.jp-FormGroup-content .jp-root > fieldset > p {\n  display: none;\n}\n\n/** copy of `input.jp-mod-styled:focus` style */\n.jp-FormGroup-content fieldset input:focus,\n.jp-FormGroup-content fieldset select:focus {\n  -moz-outline-radius: unset;\n  outline: var(--jp-border-width) solid var(--md-blue-500);\n  outline-offset: -1px;\n  box-shadow: inset 0 0 4px var(--md-blue-300);\n}\n\n.jp-FormGroup-content fieldset input:hover:not(:focus),\n.jp-FormGroup-content fieldset select:hover:not(:focus) {\n  background-color: var(--jp-border-color2);\n}\n\n/* stylelint-enable selector-max-type */\n\n.jp-FormGroup-content .checkbox .field-description {\n  /* Disable default description field for checkbox:\n   because other widgets do not have description fields,\n   we add descriptions to each widget on the field level.\n  */\n  display: none;\n}\n\n.jp-FormGroup-content #root__description {\n  display: none;\n}\n\n.jp-FormGroup-content .jp-modifiedIndicator {\n  width: 5px;\n  background-color: var(--jp-brand-color2);\n  margin-top: 0;\n  margin-left: calc(var(--jp-private-settingeditor-modifier-indent) * -1);\n  flex-shrink: 0;\n}\n\n.jp-FormGroup-content .jp-modifiedIndicator.jp-errorIndicator {\n  background-color: var(--jp-error-color0);\n  margin-right: 0.5em;\n}\n\n/* RJSF ARRAY style */\n\n.jp-arrayFieldWrapper legend {\n  font-size: var(--jp-content-font-size2);\n  color: var(--jp-ui-font-color0);\n  flex-basis: 100%;\n  padding: 4px 0;\n  font-weight: var(--jp-content-heading-font-weight);\n  border-bottom: 1px solid var(--jp-border-color2);\n}\n\n.jp-arrayFieldWrapper .field-description {\n  padding: 4px 0;\n  white-space: pre-wrap;\n}\n\n.jp-arrayFieldWrapper .array-item {\n  width: 100%;\n  border: 1px solid var(--jp-border-color2);\n  border-radius: 4px;\n  margin: 4px;\n}\n\n.jp-ArrayOperations {\n  display: flex;\n  margin-left: 8px;\n}\n\n.jp-ArrayOperationsButton {\n  margin: 2px;\n}\n\n.jp-ArrayOperationsButton .jp-icon3[fill] {\n  fill: var(--jp-ui-font-color0);\n}\n\nbutton.jp-ArrayOperationsButton.jp-mod-styled:disabled {\n  cursor: not-allowed;\n  opacity: 0.5;\n}\n\n/* RJSF form validation error */\n\n.jp-FormGroup-content .validationErrors {\n  color: var(--jp-error-color0);\n}\n\n/* Hide panel level error as duplicated the field level error */\n.jp-FormGroup-content .panel.errors {\n  display: none;\n}\n\n/* RJSF normal content (settings-editor) */\n\n.jp-FormGroup-contentNormal {\n  display: flex;\n  align-items: center;\n  flex-wrap: wrap;\n}\n\n.jp-FormGroup-contentNormal .jp-FormGroup-contentItem {\n  margin-left: 7px;\n  color: var(--jp-ui-font-color0);\n}\n\n.jp-FormGroup-contentNormal .jp-FormGroup-description {\n  flex-basis: 100%;\n  padding: 4px 7px;\n}\n\n.jp-FormGroup-contentNormal .jp-FormGroup-default {\n  flex-basis: 100%;\n  padding: 4px 7px;\n}\n\n.jp-FormGroup-contentNormal .jp-FormGroup-fieldLabel {\n  font-size: var(--jp-content-font-size1);\n  font-weight: normal;\n  min-width: 120px;\n}\n\n.jp-FormGroup-contentNormal fieldset:not(:first-child) {\n  margin-left: 7px;\n}\n\n.jp-FormGroup-contentNormal .field-array-of-string .array-item {\n  /* Display `jp-ArrayOperations` buttons side-by-side with content except\n    for small screens where flex-wrap will place them one below the other.\n  */\n  display: flex;\n  align-items: center;\n  flex-wrap: wrap;\n}\n\n.jp-FormGroup-contentNormal .jp-objectFieldWrapper .form-group {\n  padding: 2px 8px 2px var(--jp-private-settingeditor-modifier-indent);\n  margin-top: 2px;\n}\n\n/* RJSF compact content (metadata-form) */\n\n.jp-FormGroup-content.jp-FormGroup-contentCompact {\n  width: 100%;\n}\n\n.jp-FormGroup-contentCompact .form-group {\n  display: flex;\n  padding: 0.5em 0.2em 0.5em 0;\n}\n\n.jp-FormGroup-contentCompact\n  .jp-FormGroup-compactTitle\n  .jp-FormGroup-description {\n  font-size: var(--jp-ui-font-size1);\n  color: var(--jp-ui-font-color2);\n}\n\n.jp-FormGroup-contentCompact .jp-FormGroup-fieldLabel {\n  padding-bottom: 0.3em;\n}\n\n.jp-FormGroup-contentCompact .jp-inputFieldWrapper .form-control {\n  width: 100%;\n  box-sizing: border-box;\n}\n\n.jp-FormGroup-contentCompact .jp-arrayFieldWrapper .jp-FormGroup-compactTitle {\n  padding-bottom: 7px;\n}\n\n.jp-FormGroup-contentCompact\n  .jp-objectFieldWrapper\n  .jp-objectFieldWrapper\n  .form-group {\n  padding: 2px 8px 2px var(--jp-private-settingeditor-modifier-indent);\n  margin-top: 2px;\n}\n\n.jp-FormGroup-contentCompact ul.error-detail {\n  margin-block-start: 0.5em;\n  margin-block-end: 0.5em;\n  padding-inline-start: 1em;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.jp-SidePanel {\n  display: flex;\n  flex-direction: column;\n  min-width: var(--jp-sidebar-min-width);\n  overflow-y: auto;\n  color: var(--jp-ui-font-color1);\n  background: var(--jp-layout-color1);\n  font-size: var(--jp-ui-font-size1);\n}\n\n.jp-SidePanel-header {\n  flex: 0 0 auto;\n  display: flex;\n  border-bottom: var(--jp-border-width) solid var(--jp-border-color2);\n  font-size: var(--jp-ui-font-size0);\n  font-weight: 600;\n  letter-spacing: 1px;\n  margin: 0;\n  padding: 2px;\n  text-transform: uppercase;\n}\n\n.jp-SidePanel-toolbar {\n  flex: 0 0 auto;\n}\n\n.jp-SidePanel-content {\n  flex: 1 1 auto;\n}\n\n.jp-SidePanel-toolbar,\n.jp-AccordionPanel-toolbar {\n  height: var(--jp-private-toolbar-height);\n}\n\n.jp-SidePanel-toolbar.jp-Toolbar-micro {\n  display: none;\n}\n\n.lm-AccordionPanel .jp-AccordionPanel-title {\n  box-sizing: border-box;\n  line-height: 25px;\n  margin: 0;\n  display: flex;\n  align-items: center;\n  background: var(--jp-layout-color1);\n  color: var(--jp-ui-font-color1);\n  border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);\n  box-shadow: var(--jp-toolbar-box-shadow);\n  font-size: var(--jp-ui-font-size0);\n}\n\n.jp-AccordionPanel-title {\n  cursor: pointer;\n  user-select: none;\n  -moz-user-select: none;\n  -webkit-user-select: none;\n  text-transform: uppercase;\n}\n\n.lm-AccordionPanel[data-orientation='horizontal'] > .jp-AccordionPanel-title {\n  /* Title is rotated for horizontal accordion panel using CSS */\n  display: block;\n  transform-origin: top left;\n  transform: rotate(-90deg) translate(-100%);\n}\n\n.jp-AccordionPanel-title .lm-AccordionPanel-titleLabel {\n  user-select: none;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n\n.jp-AccordionPanel-title .lm-AccordionPanel-titleCollapser {\n  transform: rotate(-90deg);\n  margin: auto 0;\n  height: 16px;\n}\n\n.jp-AccordionPanel-title.lm-mod-expanded .lm-AccordionPanel-titleCollapser {\n  transform: rotate(0deg);\n}\n\n.lm-AccordionPanel .jp-AccordionPanel-toolbar {\n  background: none;\n  box-shadow: none;\n  border: none;\n  margin-left: auto;\n}\n\n.lm-AccordionPanel .lm-SplitPanel-handle:hover {\n  background: var(--jp-layout-color3);\n}\n\n.jp-text-truncated {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2017, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-Spinner {\n  position: absolute;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  z-index: 10;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  background: var(--jp-layout-color0);\n  outline: none;\n}\n\n.jp-SpinnerContent {\n  font-size: 10px;\n  margin: 50px auto;\n  text-indent: -9999em;\n  width: 3em;\n  height: 3em;\n  border-radius: 50%;\n  background: var(--jp-brand-color3);\n  background: linear-gradient(\n    to right,\n    #f37626 10%,\n    rgba(255, 255, 255, 0) 42%\n  );\n  position: relative;\n  animation: load3 1s infinite linear, fadeIn 1s;\n}\n\n.jp-SpinnerContent::before {\n  width: 50%;\n  height: 50%;\n  background: #f37626;\n  border-radius: 100% 0 0;\n  position: absolute;\n  top: 0;\n  left: 0;\n  content: '';\n}\n\n.jp-SpinnerContent::after {\n  background: var(--jp-layout-color0);\n  width: 75%;\n  height: 75%;\n  border-radius: 50%;\n  content: '';\n  margin: auto;\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  right: 0;\n}\n\n@keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes load3 {\n  0% {\n    transform: rotate(0deg);\n  }\n\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2017, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\nbutton.jp-mod-styled {\n  font-size: var(--jp-ui-font-size1);\n  color: var(--jp-ui-font-color0);\n  border: none;\n  box-sizing: border-box;\n  text-align: center;\n  line-height: 32px;\n  height: 32px;\n  padding: 0 12px;\n  letter-spacing: 0.8px;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n}\n\ninput.jp-mod-styled {\n  background: var(--jp-input-background);\n  height: 28px;\n  box-sizing: border-box;\n  border: var(--jp-border-width) solid var(--jp-border-color1);\n  padding-left: 7px;\n  padding-right: 7px;\n  font-size: var(--jp-ui-font-size2);\n  color: var(--jp-ui-font-color0);\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n}\n\ninput[type='checkbox'].jp-mod-styled {\n  appearance: checkbox;\n  -webkit-appearance: checkbox;\n  -moz-appearance: checkbox;\n  height: auto;\n}\n\ninput.jp-mod-styled:focus {\n  border: var(--jp-border-width) solid var(--md-blue-500);\n  box-shadow: inset 0 0 4px var(--md-blue-300);\n}\n\n.jp-select-wrapper {\n  display: flex;\n  position: relative;\n  flex-direction: column;\n  padding: 1px;\n  background-color: var(--jp-layout-color1);\n  box-sizing: border-box;\n  margin-bottom: 12px;\n}\n\n.jp-select-wrapper:not(.multiple) {\n  height: 28px;\n}\n\n.jp-select-wrapper.jp-mod-focused select.jp-mod-styled {\n  border: var(--jp-border-width) solid var(--jp-input-active-border-color);\n  box-shadow: var(--jp-input-box-shadow);\n  background-color: var(--jp-input-active-background);\n}\n\nselect.jp-mod-styled:hover {\n  cursor: pointer;\n  color: var(--jp-ui-font-color0);\n  background-color: var(--jp-input-hover-background);\n  box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5);\n}\n\nselect.jp-mod-styled {\n  flex: 1 1 auto;\n  width: 100%;\n  font-size: var(--jp-ui-font-size2);\n  background: var(--jp-input-background);\n  color: var(--jp-ui-font-color0);\n  padding: 0 25px 0 8px;\n  border: var(--jp-border-width) solid var(--jp-input-border-color);\n  border-radius: 0;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n}\n\nselect.jp-mod-styled:not([multiple]) {\n  height: 32px;\n}\n\nselect.jp-mod-styled[multiple] {\n  max-height: 200px;\n  overflow-y: auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-switch {\n  display: flex;\n  align-items: center;\n  padding-left: 4px;\n  padding-right: 4px;\n  font-size: var(--jp-ui-font-size1);\n  background-color: transparent;\n  color: var(--jp-ui-font-color1);\n  border: none;\n  height: 20px;\n}\n\n.jp-switch:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-switch-label {\n  margin-right: 5px;\n  font-family: var(--jp-ui-font-family);\n}\n\n.jp-switch-track {\n  cursor: pointer;\n  background-color: var(--jp-switch-color, var(--jp-border-color1));\n  -webkit-transition: 0.4s;\n  transition: 0.4s;\n  border-radius: 34px;\n  height: 16px;\n  width: 35px;\n  position: relative;\n}\n\n.jp-switch-track::before {\n  content: '';\n  position: absolute;\n  height: 10px;\n  width: 10px;\n  margin: 3px;\n  left: 0;\n  background-color: var(--jp-ui-inverse-font-color1);\n  -webkit-transition: 0.4s;\n  transition: 0.4s;\n  border-radius: 50%;\n}\n\n.jp-switch[aria-checked='true'] .jp-switch-track {\n  background-color: var(--jp-switch-true-position-color, var(--jp-warn-color0));\n}\n\n.jp-switch[aria-checked='true'] .jp-switch-track::before {\n  /* track width (35) - margins (3 + 3) - thumb width (10) */\n  left: 19px;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2016, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-private-toolbar-height: calc(\n    28px + var(--jp-border-width)\n  ); /* leave 28px for content */\n}\n\n.jp-Toolbar {\n  color: var(--jp-ui-font-color1);\n  flex: 0 0 auto;\n  display: flex;\n  flex-direction: row;\n  border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);\n  box-shadow: var(--jp-toolbar-box-shadow);\n  background: var(--jp-toolbar-background);\n  min-height: var(--jp-toolbar-micro-height);\n  padding: 2px;\n  z-index: 8;\n  overflow-x: hidden;\n}\n\n/* Toolbar items */\n\n.jp-Toolbar > .jp-Toolbar-item.jp-Toolbar-spacer {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.jp-Toolbar-item.jp-Toolbar-kernelStatus {\n  display: inline-block;\n  width: 32px;\n  background-repeat: no-repeat;\n  background-position: center;\n  background-size: 16px;\n}\n\n.jp-Toolbar > .jp-Toolbar-item {\n  flex: 0 0 auto;\n  display: flex;\n  padding-left: 1px;\n  padding-right: 1px;\n  font-size: var(--jp-ui-font-size1);\n  line-height: var(--jp-private-toolbar-height);\n  height: 100%;\n}\n\n/* Toolbar buttons */\n\n/* This is the div we use to wrap the react component into a Widget */\ndiv.jp-ToolbarButton {\n  color: transparent;\n  border: none;\n  box-sizing: border-box;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  padding: 0;\n  margin: 0;\n}\n\nbutton.jp-ToolbarButtonComponent {\n  background: var(--jp-layout-color1);\n  border: none;\n  box-sizing: border-box;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  padding: 0 6px;\n  margin: 0;\n  height: 24px;\n  border-radius: var(--jp-border-radius);\n  display: flex;\n  align-items: center;\n  text-align: center;\n  font-size: 14px;\n  min-width: unset;\n  min-height: unset;\n}\n\nbutton.jp-ToolbarButtonComponent:disabled {\n  opacity: 0.4;\n}\n\nbutton.jp-ToolbarButtonComponent > span {\n  padding: 0;\n  flex: 0 0 auto;\n}\n\nbutton.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label {\n  font-size: var(--jp-ui-font-size1);\n  line-height: 100%;\n  padding-left: 2px;\n  color: var(--jp-ui-font-color1);\n  font-family: var(--jp-ui-font-family);\n}\n\n#jp-main-dock-panel[data-mode='single-document']\n  .jp-MainAreaWidget\n  > .jp-Toolbar.jp-Toolbar-micro {\n  padding: 0;\n  min-height: 0;\n}\n\n#jp-main-dock-panel[data-mode='single-document']\n  .jp-MainAreaWidget\n  > .jp-Toolbar {\n  border: none;\n  box-shadow: none;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.jp-WindowedPanel-outer {\n  position: relative;\n  overflow-y: auto;\n}\n\n.jp-WindowedPanel-inner {\n  position: relative;\n}\n\n.jp-WindowedPanel-window {\n  position: absolute;\n  left: 0;\n  right: 0;\n  overflow: visible;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/* Sibling imports */\n\nbody {\n  color: var(--jp-ui-font-color1);\n  font-size: var(--jp-ui-font-size1);\n}\n\n/* Disable native link decoration styles everywhere outside of dialog boxes */\na {\n  text-decoration: unset;\n  color: unset;\n}\n\na:hover {\n  text-decoration: unset;\n  color: unset;\n}\n\n/* Accessibility for links inside dialog box text */\n.jp-Dialog-content a {\n  text-decoration: revert;\n  color: var(--jp-content-link-color);\n}\n\n.jp-Dialog-content a:hover {\n  text-decoration: revert;\n}\n\n/* Styles for ui-components */\n.jp-Button {\n  color: var(--jp-ui-font-color2);\n  border-radius: var(--jp-border-radius);\n  padding: 0 12px;\n  font-size: var(--jp-ui-font-size1);\n\n  /* Copy from blueprint 3 */\n  display: inline-flex;\n  flex-direction: row;\n  border: none;\n  cursor: pointer;\n  align-items: center;\n  justify-content: center;\n  text-align: left;\n  vertical-align: middle;\n  min-height: 30px;\n  min-width: 30px;\n}\n\n.jp-Button:disabled {\n  cursor: not-allowed;\n}\n\n.jp-Button:empty {\n  padding: 0 !important;\n}\n\n.jp-Button.jp-mod-small {\n  min-height: 24px;\n  min-width: 24px;\n  font-size: 12px;\n  padding: 0 7px;\n}\n\n/* Use our own theme for hover styles */\n.jp-Button.jp-mod-minimal:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-Button.jp-mod-minimal {\n  background: none;\n}\n\n.jp-InputGroup {\n  display: block;\n  position: relative;\n}\n\n.jp-InputGroup input {\n  box-sizing: border-box;\n  border: none;\n  border-radius: 0;\n  background-color: transparent;\n  color: var(--jp-ui-font-color0);\n  box-shadow: inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color);\n  padding-bottom: 0;\n  padding-top: 0;\n  padding-left: 10px;\n  padding-right: 28px;\n  position: relative;\n  width: 100%;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  font-size: 14px;\n  font-weight: 400;\n  height: 30px;\n  line-height: 30px;\n  outline: none;\n  vertical-align: middle;\n}\n\n.jp-InputGroup input:focus {\n  box-shadow: inset 0 0 0 var(--jp-border-width)\n      var(--jp-input-active-box-shadow-color),\n    inset 0 0 0 3px var(--jp-input-active-box-shadow-color);\n}\n\n.jp-InputGroup input:disabled {\n  cursor: not-allowed;\n  resize: block;\n  background-color: var(--jp-layout-color2);\n  color: var(--jp-ui-font-color2);\n}\n\n.jp-InputGroup input:disabled ~ span {\n  cursor: not-allowed;\n  color: var(--jp-ui-font-color2);\n}\n\n.jp-InputGroup input::placeholder,\ninput::placeholder {\n  color: var(--jp-ui-font-color2);\n}\n\n.jp-InputGroupAction {\n  position: absolute;\n  bottom: 1px;\n  right: 0;\n  padding: 6px;\n}\n\n.jp-HTMLSelect.jp-DefaultStyle select {\n  background-color: initial;\n  border: none;\n  border-radius: 0;\n  box-shadow: none;\n  color: var(--jp-ui-font-color0);\n  display: block;\n  font-size: var(--jp-ui-font-size1);\n  font-family: var(--jp-ui-font-family);\n  height: 24px;\n  line-height: 14px;\n  padding: 0 25px 0 10px;\n  text-align: left;\n  -moz-appearance: none;\n  -webkit-appearance: none;\n}\n\n.jp-HTMLSelect.jp-DefaultStyle select:disabled {\n  background-color: var(--jp-layout-color2);\n  color: var(--jp-ui-font-color2);\n  cursor: not-allowed;\n  resize: block;\n}\n\n.jp-HTMLSelect.jp-DefaultStyle select:disabled ~ span {\n  cursor: not-allowed;\n}\n\n/* Use our own theme for hover and option styles */\n/* stylelint-disable-next-line selector-max-type */\n.jp-HTMLSelect.jp-DefaultStyle select:hover,\n.jp-HTMLSelect.jp-DefaultStyle select > option {\n  background-color: var(--jp-layout-color2);\n  color: var(--jp-ui-font-color0);\n}\n\nselect {\n  box-sizing: border-box;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Styles\n|----------------------------------------------------------------------------*/\n\n.jp-StatusBar-Widget {\n  display: flex;\n  align-items: center;\n  background: var(--jp-layout-color2);\n  min-height: var(--jp-statusbar-height);\n  justify-content: space-between;\n  padding: 0 10px;\n}\n\n.jp-StatusBar-Left {\n  display: flex;\n  align-items: center;\n  flex-direction: row;\n}\n\n.jp-StatusBar-Middle {\n  display: flex;\n  align-items: center;\n}\n\n.jp-StatusBar-Right {\n  display: flex;\n  align-items: center;\n  flex-direction: row-reverse;\n}\n\n.jp-StatusBar-Item {\n  max-height: var(--jp-statusbar-height);\n  margin: 0 2px;\n  height: var(--jp-statusbar-height);\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  color: var(--jp-ui-font-color1);\n  padding: 0 6px;\n}\n\n.jp-mod-highlighted:hover {\n  background-color: var(--jp-layout-color3);\n}\n\n.jp-mod-clicked {\n  background-color: var(--jp-brand-color1);\n}\n\n.jp-mod-clicked:hover {\n  background-color: var(--jp-brand-color0);\n}\n\n.jp-mod-clicked .jp-StatusBar-TextItem {\n  color: var(--jp-ui-inverse-font-color1);\n}\n\n.jp-StatusBar-HoverItem {\n  box-shadow: '0px 4px 4px rgba(0, 0, 0, 0.25)';\n}\n\n.jp-StatusBar-TextItem {\n  font-size: var(--jp-ui-font-size1);\n  font-family: var(--jp-ui-font-family);\n  line-height: 24px;\n  color: var(--jp-ui-font-color1);\n}\n\n.jp-StatusBar-GroupItem {\n  display: flex;\n  align-items: center;\n  flex-direction: row;\n}\n\n.jp-Statusbar-ProgressCircle svg {\n  display: block;\n  margin: 0 auto;\n  width: 16px;\n  height: 24px;\n  align-self: normal;\n}\n\n.jp-Statusbar-ProgressCircle path {\n  fill: var(--jp-inverse-layout-color3);\n}\n\n.jp-Statusbar-ProgressBar-progress-bar {\n  height: 10px;\n  width: 100px;\n  border: solid 0.25px var(--jp-brand-color2);\n  border-radius: 3px;\n  overflow: hidden;\n  align-self: center;\n}\n\n.jp-Statusbar-ProgressBar-progress-bar > div {\n  background-color: var(--jp-brand-color2);\n  background-image: linear-gradient(\n    -45deg,\n    rgba(255, 255, 255, 0.2) 25%,\n    transparent 25%,\n    transparent 50%,\n    rgba(255, 255, 255, 0.2) 50%,\n    rgba(255, 255, 255, 0.2) 75%,\n    transparent 75%,\n    transparent\n  );\n  background-size: 40px 40px;\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: 12px;\n  line-height: 14px;\n  color: #fff;\n  text-align: center;\n  animation: jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite;\n}\n\n.jp-Statusbar-ProgressBar-progress-bar p {\n  color: var(--jp-ui-font-color1);\n  font-family: var(--jp-ui-font-family);\n  font-size: var(--jp-ui-font-size1);\n  line-height: 10px;\n  width: 100px;\n}\n\n@keyframes jp-Statusbar-ExecutionTime-progress-bar {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 40px 40px;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Variables\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-private-commandpalette-search-height: 28px;\n}\n\n/*-----------------------------------------------------------------------------\n| Overall styles\n|----------------------------------------------------------------------------*/\n\n.lm-CommandPalette {\n  padding-bottom: 0;\n  color: var(--jp-ui-font-color1);\n  background: var(--jp-layout-color1);\n\n  /* This is needed so that all font sizing of children done in ems is\n   * relative to this base size */\n  font-size: var(--jp-ui-font-size1);\n}\n\n/*-----------------------------------------------------------------------------\n| Modal variant\n|----------------------------------------------------------------------------*/\n\n.jp-ModalCommandPalette {\n  position: absolute;\n  z-index: 10000;\n  top: 38px;\n  left: 30%;\n  margin: 0;\n  padding: 4px;\n  width: 40%;\n  box-shadow: var(--jp-elevation-z4);\n  border-radius: 4px;\n  background: var(--jp-layout-color0);\n}\n\n.jp-ModalCommandPalette .lm-CommandPalette {\n  max-height: 40vh;\n}\n\n.jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon::after {\n  display: none;\n}\n\n.jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header {\n  display: none;\n}\n\n.jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item {\n  margin-left: 4px;\n  margin-right: 4px;\n}\n\n.jp-ModalCommandPalette\n  .lm-CommandPalette\n  .lm-CommandPalette-item.lm-mod-disabled {\n  display: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Search\n|----------------------------------------------------------------------------*/\n\n.lm-CommandPalette-search {\n  padding: 4px;\n  background-color: var(--jp-layout-color1);\n  z-index: 2;\n}\n\n.lm-CommandPalette-wrapper {\n  overflow: overlay;\n  padding: 0 9px;\n  background-color: var(--jp-input-active-background);\n  height: 30px;\n  box-shadow: inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color);\n}\n\n.lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper {\n  box-shadow: inset 0 0 0 1px var(--jp-input-active-box-shadow-color),\n    inset 0 0 0 3px var(--jp-input-active-box-shadow-color);\n}\n\n.jp-SearchIconGroup {\n  color: white;\n  background-color: var(--jp-brand-color1);\n  position: absolute;\n  top: 4px;\n  right: 4px;\n  padding: 5px 5px 1px;\n}\n\n.jp-SearchIconGroup svg {\n  height: 20px;\n  width: 20px;\n}\n\n.jp-SearchIconGroup .jp-icon3[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.lm-CommandPalette-input {\n  background: transparent;\n  width: calc(100% - 18px);\n  float: left;\n  border: none;\n  outline: none;\n  font-size: var(--jp-ui-font-size1);\n  color: var(--jp-ui-font-color0);\n  line-height: var(--jp-private-commandpalette-search-height);\n}\n\n.lm-CommandPalette-input::-webkit-input-placeholder,\n.lm-CommandPalette-input::-moz-placeholder,\n.lm-CommandPalette-input:-ms-input-placeholder {\n  color: var(--jp-ui-font-color2);\n  font-size: var(--jp-ui-font-size1);\n}\n\n/*-----------------------------------------------------------------------------\n| Results\n|----------------------------------------------------------------------------*/\n\n.lm-CommandPalette-header:first-child {\n  margin-top: 0;\n}\n\n.lm-CommandPalette-header {\n  border-bottom: solid var(--jp-border-width) var(--jp-border-color2);\n  color: var(--jp-ui-font-color1);\n  cursor: pointer;\n  display: flex;\n  font-size: var(--jp-ui-font-size0);\n  font-weight: 600;\n  letter-spacing: 1px;\n  margin-top: 8px;\n  padding: 8px 0 8px 12px;\n  text-transform: uppercase;\n}\n\n.lm-CommandPalette-header.lm-mod-active {\n  background: var(--jp-layout-color2);\n}\n\n.lm-CommandPalette-header > mark {\n  background-color: transparent;\n  font-weight: bold;\n  color: var(--jp-ui-font-color1);\n}\n\n.lm-CommandPalette-item {\n  padding: 4px 12px 4px 4px;\n  color: var(--jp-ui-font-color1);\n  font-size: var(--jp-ui-font-size1);\n  font-weight: 400;\n  display: flex;\n}\n\n.lm-CommandPalette-item.lm-mod-disabled {\n  color: var(--jp-ui-font-color2);\n}\n\n.lm-CommandPalette-item.lm-mod-active {\n  color: var(--jp-ui-inverse-font-color1);\n  background: var(--jp-brand-color1);\n}\n\n.lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel > mark {\n  color: var(--jp-ui-inverse-font-color0);\n}\n\n.lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill] {\n  fill: var(--jp-layout-color0);\n}\n\n.lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled) {\n  color: var(--jp-ui-inverse-font-color1);\n  background: var(--jp-brand-color1);\n}\n\n.lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled) {\n  background: var(--jp-layout-color2);\n}\n\n.lm-CommandPalette-itemContent {\n  overflow: hidden;\n}\n\n.lm-CommandPalette-itemLabel > mark {\n  color: var(--jp-ui-font-color0);\n  background-color: transparent;\n  font-weight: bold;\n}\n\n.lm-CommandPalette-item.lm-mod-disabled mark {\n  color: var(--jp-ui-font-color2);\n}\n\n.lm-CommandPalette-item .lm-CommandPalette-itemIcon {\n  margin: 0 4px 0 0;\n  position: relative;\n  width: 16px;\n  top: 2px;\n  flex: 0 0 auto;\n}\n\n.lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon {\n  opacity: 0.6;\n}\n\n.lm-CommandPalette-item .lm-CommandPalette-itemShortcut {\n  flex: 0 0 auto;\n}\n\n.lm-CommandPalette-itemCaption {\n  display: none;\n}\n\n.lm-CommandPalette-content {\n  background-color: var(--jp-layout-color1);\n}\n\n.lm-CommandPalette-content:empty::after {\n  content: 'No results';\n  margin: auto;\n  margin-top: 20px;\n  width: 100px;\n  display: block;\n  font-size: var(--jp-ui-font-size2);\n  font-family: var(--jp-ui-font-family);\n  font-weight: lighter;\n}\n\n.lm-CommandPalette-emptyMessage {\n  text-align: center;\n  margin-top: 24px;\n  line-height: 1.32;\n  padding: 0 8px;\n  color: var(--jp-content-font-color3);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2017, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-Dialog {\n  position: absolute;\n  z-index: 10000;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  top: 0;\n  left: 0;\n  margin: 0;\n  padding: 0;\n  width: 100%;\n  height: 100%;\n  background: var(--jp-dialog-background);\n}\n\n.jp-Dialog-content {\n  display: flex;\n  flex-direction: column;\n  margin-left: auto;\n  margin-right: auto;\n  background: var(--jp-layout-color1);\n  padding: 24px 24px 12px;\n  min-width: 300px;\n  min-height: 150px;\n  max-width: 1000px;\n  max-height: 500px;\n  box-sizing: border-box;\n  box-shadow: var(--jp-elevation-z20);\n  word-wrap: break-word;\n  border-radius: var(--jp-border-radius);\n\n  /* This is needed so that all font sizing of children done in ems is\n   * relative to this base size */\n  font-size: var(--jp-ui-font-size1);\n  color: var(--jp-ui-font-color1);\n  resize: both;\n}\n\n.jp-Dialog-content.jp-Dialog-content-small {\n  max-width: 500px;\n}\n\n.jp-Dialog-button {\n  overflow: visible;\n}\n\nbutton.jp-Dialog-button:focus {\n  outline: 1px solid var(--jp-brand-color1);\n  outline-offset: 4px;\n  -moz-outline-radius: 0;\n}\n\nbutton.jp-Dialog-button:focus::-moz-focus-inner {\n  border: 0;\n}\n\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus {\n  outline-offset: 4px;\n  -moz-outline-radius: 0;\n}\n\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus {\n  outline: 1px solid var(--jp-accept-color-normal, var(--jp-brand-color1));\n}\n\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus {\n  outline: 1px solid var(--jp-warn-color-normal, var(--jp-error-color1));\n}\n\nbutton.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus {\n  outline: 1px solid var(--jp-reject-color-normal, var(--md-grey-600));\n}\n\nbutton.jp-Dialog-close-button {\n  padding: 0;\n  height: 100%;\n  min-width: unset;\n  min-height: unset;\n}\n\n.jp-Dialog-header {\n  display: flex;\n  justify-content: space-between;\n  flex: 0 0 auto;\n  padding-bottom: 12px;\n  font-size: var(--jp-ui-font-size3);\n  font-weight: 400;\n  color: var(--jp-ui-font-color1);\n}\n\n.jp-Dialog-body {\n  display: flex;\n  flex-direction: column;\n  flex: 1 1 auto;\n  font-size: var(--jp-ui-font-size1);\n  background: var(--jp-layout-color1);\n  color: var(--jp-ui-font-color1);\n  overflow: auto;\n}\n\n.jp-Dialog-footer {\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-end;\n  align-items: center;\n  flex: 0 0 auto;\n  margin-left: -12px;\n  margin-right: -12px;\n  padding: 12px;\n}\n\n.jp-Dialog-checkbox {\n  padding-right: 5px;\n}\n\n.jp-Dialog-checkbox > input:focus-visible {\n  outline: 1px solid var(--jp-input-active-border-color);\n  outline-offset: 1px;\n}\n\n.jp-Dialog-spacer {\n  flex: 1 1 auto;\n}\n\n.jp-Dialog-title {\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.jp-Dialog-body > .jp-select-wrapper {\n  width: 100%;\n}\n\n.jp-Dialog-body > button {\n  padding: 0 16px;\n}\n\n.jp-Dialog-body > label {\n  line-height: 1.4;\n  color: var(--jp-ui-font-color0);\n}\n\n.jp-Dialog-button.jp-mod-styled:not(:last-child) {\n  margin-right: 12px;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.jp-Input-Boolean-Dialog {\n  flex-direction: row-reverse;\n  align-items: end;\n  width: 100%;\n}\n\n.jp-Input-Boolean-Dialog > label {\n  flex: 1 1 auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2016, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-MainAreaWidget > :focus {\n  outline: none;\n}\n\n.jp-MainAreaWidget .jp-MainAreaWidget-error {\n  padding: 6px;\n}\n\n.jp-MainAreaWidget .jp-MainAreaWidget-error > pre {\n  width: auto;\n  padding: 10px;\n  background: var(--jp-error-color3);\n  border: var(--jp-border-width) solid var(--jp-error-color1);\n  border-radius: var(--jp-border-radius);\n  color: var(--jp-ui-font-color1);\n  font-size: var(--jp-ui-font-size1);\n  white-space: pre-wrap;\n  word-wrap: break-word;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/**\n * google-material-color v1.2.6\n * https://github.com/danlevan/google-material-color\n */\n:root {\n  --md-red-50: #ffebee;\n  --md-red-100: #ffcdd2;\n  --md-red-200: #ef9a9a;\n  --md-red-300: #e57373;\n  --md-red-400: #ef5350;\n  --md-red-500: #f44336;\n  --md-red-600: #e53935;\n  --md-red-700: #d32f2f;\n  --md-red-800: #c62828;\n  --md-red-900: #b71c1c;\n  --md-red-A100: #ff8a80;\n  --md-red-A200: #ff5252;\n  --md-red-A400: #ff1744;\n  --md-red-A700: #d50000;\n  --md-pink-50: #fce4ec;\n  --md-pink-100: #f8bbd0;\n  --md-pink-200: #f48fb1;\n  --md-pink-300: #f06292;\n  --md-pink-400: #ec407a;\n  --md-pink-500: #e91e63;\n  --md-pink-600: #d81b60;\n  --md-pink-700: #c2185b;\n  --md-pink-800: #ad1457;\n  --md-pink-900: #880e4f;\n  --md-pink-A100: #ff80ab;\n  --md-pink-A200: #ff4081;\n  --md-pink-A400: #f50057;\n  --md-pink-A700: #c51162;\n  --md-purple-50: #f3e5f5;\n  --md-purple-100: #e1bee7;\n  --md-purple-200: #ce93d8;\n  --md-purple-300: #ba68c8;\n  --md-purple-400: #ab47bc;\n  --md-purple-500: #9c27b0;\n  --md-purple-600: #8e24aa;\n  --md-purple-700: #7b1fa2;\n  --md-purple-800: #6a1b9a;\n  --md-purple-900: #4a148c;\n  --md-purple-A100: #ea80fc;\n  --md-purple-A200: #e040fb;\n  --md-purple-A400: #d500f9;\n  --md-purple-A700: #a0f;\n  --md-deep-purple-50: #ede7f6;\n  --md-deep-purple-100: #d1c4e9;\n  --md-deep-purple-200: #b39ddb;\n  --md-deep-purple-300: #9575cd;\n  --md-deep-purple-400: #7e57c2;\n  --md-deep-purple-500: #673ab7;\n  --md-deep-purple-600: #5e35b1;\n  --md-deep-purple-700: #512da8;\n  --md-deep-purple-800: #4527a0;\n  --md-deep-purple-900: #311b92;\n  --md-deep-purple-A100: #b388ff;\n  --md-deep-purple-A200: #7c4dff;\n  --md-deep-purple-A400: #651fff;\n  --md-deep-purple-A700: #6200ea;\n  --md-indigo-50: #e8eaf6;\n  --md-indigo-100: #c5cae9;\n  --md-indigo-200: #9fa8da;\n  --md-indigo-300: #7986cb;\n  --md-indigo-400: #5c6bc0;\n  --md-indigo-500: #3f51b5;\n  --md-indigo-600: #3949ab;\n  --md-indigo-700: #303f9f;\n  --md-indigo-800: #283593;\n  --md-indigo-900: #1a237e;\n  --md-indigo-A100: #8c9eff;\n  --md-indigo-A200: #536dfe;\n  --md-indigo-A400: #3d5afe;\n  --md-indigo-A700: #304ffe;\n  --md-blue-50: #e3f2fd;\n  --md-blue-100: #bbdefb;\n  --md-blue-200: #90caf9;\n  --md-blue-300: #64b5f6;\n  --md-blue-400: #42a5f5;\n  --md-blue-500: #2196f3;\n  --md-blue-600: #1e88e5;\n  --md-blue-700: #1976d2;\n  --md-blue-800: #1565c0;\n  --md-blue-900: #0d47a1;\n  --md-blue-A100: #82b1ff;\n  --md-blue-A200: #448aff;\n  --md-blue-A400: #2979ff;\n  --md-blue-A700: #2962ff;\n  --md-light-blue-50: #e1f5fe;\n  --md-light-blue-100: #b3e5fc;\n  --md-light-blue-200: #81d4fa;\n  --md-light-blue-300: #4fc3f7;\n  --md-light-blue-400: #29b6f6;\n  --md-light-blue-500: #03a9f4;\n  --md-light-blue-600: #039be5;\n  --md-light-blue-700: #0288d1;\n  --md-light-blue-800: #0277bd;\n  --md-light-blue-900: #01579b;\n  --md-light-blue-A100: #80d8ff;\n  --md-light-blue-A200: #40c4ff;\n  --md-light-blue-A400: #00b0ff;\n  --md-light-blue-A700: #0091ea;\n  --md-cyan-50: #e0f7fa;\n  --md-cyan-100: #b2ebf2;\n  --md-cyan-200: #80deea;\n  --md-cyan-300: #4dd0e1;\n  --md-cyan-400: #26c6da;\n  --md-cyan-500: #00bcd4;\n  --md-cyan-600: #00acc1;\n  --md-cyan-700: #0097a7;\n  --md-cyan-800: #00838f;\n  --md-cyan-900: #006064;\n  --md-cyan-A100: #84ffff;\n  --md-cyan-A200: #18ffff;\n  --md-cyan-A400: #00e5ff;\n  --md-cyan-A700: #00b8d4;\n  --md-teal-50: #e0f2f1;\n  --md-teal-100: #b2dfdb;\n  --md-teal-200: #80cbc4;\n  --md-teal-300: #4db6ac;\n  --md-teal-400: #26a69a;\n  --md-teal-500: #009688;\n  --md-teal-600: #00897b;\n  --md-teal-700: #00796b;\n  --md-teal-800: #00695c;\n  --md-teal-900: #004d40;\n  --md-teal-A100: #a7ffeb;\n  --md-teal-A200: #64ffda;\n  --md-teal-A400: #1de9b6;\n  --md-teal-A700: #00bfa5;\n  --md-green-50: #e8f5e9;\n  --md-green-100: #c8e6c9;\n  --md-green-200: #a5d6a7;\n  --md-green-300: #81c784;\n  --md-green-400: #66bb6a;\n  --md-green-500: #4caf50;\n  --md-green-600: #43a047;\n  --md-green-700: #388e3c;\n  --md-green-800: #2e7d32;\n  --md-green-900: #1b5e20;\n  --md-green-A100: #b9f6ca;\n  --md-green-A200: #69f0ae;\n  --md-green-A400: #00e676;\n  --md-green-A700: #00c853;\n  --md-light-green-50: #f1f8e9;\n  --md-light-green-100: #dcedc8;\n  --md-light-green-200: #c5e1a5;\n  --md-light-green-300: #aed581;\n  --md-light-green-400: #9ccc65;\n  --md-light-green-500: #8bc34a;\n  --md-light-green-600: #7cb342;\n  --md-light-green-700: #689f38;\n  --md-light-green-800: #558b2f;\n  --md-light-green-900: #33691e;\n  --md-light-green-A100: #ccff90;\n  --md-light-green-A200: #b2ff59;\n  --md-light-green-A400: #76ff03;\n  --md-light-green-A700: #64dd17;\n  --md-lime-50: #f9fbe7;\n  --md-lime-100: #f0f4c3;\n  --md-lime-200: #e6ee9c;\n  --md-lime-300: #dce775;\n  --md-lime-400: #d4e157;\n  --md-lime-500: #cddc39;\n  --md-lime-600: #c0ca33;\n  --md-lime-700: #afb42b;\n  --md-lime-800: #9e9d24;\n  --md-lime-900: #827717;\n  --md-lime-A100: #f4ff81;\n  --md-lime-A200: #eeff41;\n  --md-lime-A400: #c6ff00;\n  --md-lime-A700: #aeea00;\n  --md-yellow-50: #fffde7;\n  --md-yellow-100: #fff9c4;\n  --md-yellow-200: #fff59d;\n  --md-yellow-300: #fff176;\n  --md-yellow-400: #ffee58;\n  --md-yellow-500: #ffeb3b;\n  --md-yellow-600: #fdd835;\n  --md-yellow-700: #fbc02d;\n  --md-yellow-800: #f9a825;\n  --md-yellow-900: #f57f17;\n  --md-yellow-A100: #ffff8d;\n  --md-yellow-A200: #ff0;\n  --md-yellow-A400: #ffea00;\n  --md-yellow-A700: #ffd600;\n  --md-amber-50: #fff8e1;\n  --md-amber-100: #ffecb3;\n  --md-amber-200: #ffe082;\n  --md-amber-300: #ffd54f;\n  --md-amber-400: #ffca28;\n  --md-amber-500: #ffc107;\n  --md-amber-600: #ffb300;\n  --md-amber-700: #ffa000;\n  --md-amber-800: #ff8f00;\n  --md-amber-900: #ff6f00;\n  --md-amber-A100: #ffe57f;\n  --md-amber-A200: #ffd740;\n  --md-amber-A400: #ffc400;\n  --md-amber-A700: #ffab00;\n  --md-orange-50: #fff3e0;\n  --md-orange-100: #ffe0b2;\n  --md-orange-200: #ffcc80;\n  --md-orange-300: #ffb74d;\n  --md-orange-400: #ffa726;\n  --md-orange-500: #ff9800;\n  --md-orange-600: #fb8c00;\n  --md-orange-700: #f57c00;\n  --md-orange-800: #ef6c00;\n  --md-orange-900: #e65100;\n  --md-orange-A100: #ffd180;\n  --md-orange-A200: #ffab40;\n  --md-orange-A400: #ff9100;\n  --md-orange-A700: #ff6d00;\n  --md-deep-orange-50: #fbe9e7;\n  --md-deep-orange-100: #ffccbc;\n  --md-deep-orange-200: #ffab91;\n  --md-deep-orange-300: #ff8a65;\n  --md-deep-orange-400: #ff7043;\n  --md-deep-orange-500: #ff5722;\n  --md-deep-orange-600: #f4511e;\n  --md-deep-orange-700: #e64a19;\n  --md-deep-orange-800: #d84315;\n  --md-deep-orange-900: #bf360c;\n  --md-deep-orange-A100: #ff9e80;\n  --md-deep-orange-A200: #ff6e40;\n  --md-deep-orange-A400: #ff3d00;\n  --md-deep-orange-A700: #dd2c00;\n  --md-brown-50: #efebe9;\n  --md-brown-100: #d7ccc8;\n  --md-brown-200: #bcaaa4;\n  --md-brown-300: #a1887f;\n  --md-brown-400: #8d6e63;\n  --md-brown-500: #795548;\n  --md-brown-600: #6d4c41;\n  --md-brown-700: #5d4037;\n  --md-brown-800: #4e342e;\n  --md-brown-900: #3e2723;\n  --md-grey-50: #fafafa;\n  --md-grey-100: #f5f5f5;\n  --md-grey-200: #eee;\n  --md-grey-300: #e0e0e0;\n  --md-grey-400: #bdbdbd;\n  --md-grey-500: #9e9e9e;\n  --md-grey-600: #757575;\n  --md-grey-700: #616161;\n  --md-grey-800: #424242;\n  --md-grey-900: #212121;\n  --md-blue-grey-50: #eceff1;\n  --md-blue-grey-100: #cfd8dc;\n  --md-blue-grey-200: #b0bec5;\n  --md-blue-grey-300: #90a4ae;\n  --md-blue-grey-400: #78909c;\n  --md-blue-grey-500: #607d8b;\n  --md-blue-grey-600: #546e7a;\n  --md-blue-grey-700: #455a64;\n  --md-blue-grey-800: #37474f;\n  --md-blue-grey-900: #263238;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2017, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| RenderedText\n|----------------------------------------------------------------------------*/\n\n:root {\n  /* This is the padding value to fill the gaps between lines containing spans with background color. */\n  --jp-private-code-span-padding: calc(\n    (var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2\n  );\n}\n\n.jp-RenderedText {\n  text-align: left;\n  padding-left: var(--jp-code-padding);\n  line-height: var(--jp-code-line-height);\n  font-family: var(--jp-code-font-family);\n}\n\n.jp-RenderedText pre,\n.jp-RenderedJavaScript pre,\n.jp-RenderedHTMLCommon pre {\n  color: var(--jp-content-font-color1);\n  font-size: var(--jp-code-font-size);\n  border: none;\n  margin: 0;\n  padding: 0;\n}\n\n.jp-RenderedText pre a:link {\n  text-decoration: none;\n  color: var(--jp-content-link-color);\n}\n\n.jp-RenderedText pre a:hover {\n  text-decoration: underline;\n  color: var(--jp-content-link-color);\n}\n\n.jp-RenderedText pre a:visited {\n  text-decoration: none;\n  color: var(--jp-content-link-color);\n}\n\n/* console foregrounds and backgrounds */\n.jp-RenderedText pre .ansi-black-fg {\n  color: #3e424d;\n}\n\n.jp-RenderedText pre .ansi-red-fg {\n  color: #e75c58;\n}\n\n.jp-RenderedText pre .ansi-green-fg {\n  color: #00a250;\n}\n\n.jp-RenderedText pre .ansi-yellow-fg {\n  color: #ddb62b;\n}\n\n.jp-RenderedText pre .ansi-blue-fg {\n  color: #208ffb;\n}\n\n.jp-RenderedText pre .ansi-magenta-fg {\n  color: #d160c4;\n}\n\n.jp-RenderedText pre .ansi-cyan-fg {\n  color: #60c6c8;\n}\n\n.jp-RenderedText pre .ansi-white-fg {\n  color: #c5c1b4;\n}\n\n.jp-RenderedText pre .ansi-black-bg {\n  background-color: #3e424d;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-red-bg {\n  background-color: #e75c58;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-green-bg {\n  background-color: #00a250;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-yellow-bg {\n  background-color: #ddb62b;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-blue-bg {\n  background-color: #208ffb;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-magenta-bg {\n  background-color: #d160c4;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-cyan-bg {\n  background-color: #60c6c8;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-white-bg {\n  background-color: #c5c1b4;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-black-intense-fg {\n  color: #282c36;\n}\n\n.jp-RenderedText pre .ansi-red-intense-fg {\n  color: #b22b31;\n}\n\n.jp-RenderedText pre .ansi-green-intense-fg {\n  color: #007427;\n}\n\n.jp-RenderedText pre .ansi-yellow-intense-fg {\n  color: #b27d12;\n}\n\n.jp-RenderedText pre .ansi-blue-intense-fg {\n  color: #0065ca;\n}\n\n.jp-RenderedText pre .ansi-magenta-intense-fg {\n  color: #a03196;\n}\n\n.jp-RenderedText pre .ansi-cyan-intense-fg {\n  color: #258f8f;\n}\n\n.jp-RenderedText pre .ansi-white-intense-fg {\n  color: #a1a6b2;\n}\n\n.jp-RenderedText pre .ansi-black-intense-bg {\n  background-color: #282c36;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-red-intense-bg {\n  background-color: #b22b31;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-green-intense-bg {\n  background-color: #007427;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-yellow-intense-bg {\n  background-color: #b27d12;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-blue-intense-bg {\n  background-color: #0065ca;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-magenta-intense-bg {\n  background-color: #a03196;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-cyan-intense-bg {\n  background-color: #258f8f;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-white-intense-bg {\n  background-color: #a1a6b2;\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-default-inverse-fg {\n  color: var(--jp-ui-inverse-font-color0);\n}\n\n.jp-RenderedText pre .ansi-default-inverse-bg {\n  background-color: var(--jp-inverse-layout-color0);\n  padding: var(--jp-private-code-span-padding) 0;\n}\n\n.jp-RenderedText pre .ansi-bold {\n  font-weight: bold;\n}\n\n.jp-RenderedText pre .ansi-underline {\n  text-decoration: underline;\n}\n\n.jp-RenderedText[data-mime-type='application/vnd.jupyter.stderr'] {\n  background: var(--jp-rendermime-error-background);\n  padding-top: var(--jp-code-padding);\n}\n\n/*-----------------------------------------------------------------------------\n| RenderedLatex\n|----------------------------------------------------------------------------*/\n\n.jp-RenderedLatex {\n  color: var(--jp-content-font-color1);\n  font-size: var(--jp-content-font-size1);\n  line-height: var(--jp-content-line-height);\n}\n\n/* Left-justify outputs.*/\n.jp-OutputArea-output.jp-RenderedLatex {\n  padding: var(--jp-code-padding);\n  text-align: left;\n}\n\n/*-----------------------------------------------------------------------------\n| RenderedHTML\n|----------------------------------------------------------------------------*/\n\n.jp-RenderedHTMLCommon {\n  color: var(--jp-content-font-color1);\n  font-family: var(--jp-content-font-family);\n  font-size: var(--jp-content-font-size1);\n  line-height: var(--jp-content-line-height);\n\n  /* Give a bit more R padding on Markdown text to keep line lengths reasonable */\n  padding-right: 20px;\n}\n\n.jp-RenderedHTMLCommon em {\n  font-style: italic;\n}\n\n.jp-RenderedHTMLCommon strong {\n  font-weight: bold;\n}\n\n.jp-RenderedHTMLCommon u {\n  text-decoration: underline;\n}\n\n.jp-RenderedHTMLCommon a:link {\n  text-decoration: none;\n  color: var(--jp-content-link-color);\n}\n\n.jp-RenderedHTMLCommon a:hover {\n  text-decoration: underline;\n  color: var(--jp-content-link-color);\n}\n\n.jp-RenderedHTMLCommon a:visited {\n  text-decoration: none;\n  color: var(--jp-content-link-color);\n}\n\n/* Headings */\n\n.jp-RenderedHTMLCommon h1,\n.jp-RenderedHTMLCommon h2,\n.jp-RenderedHTMLCommon h3,\n.jp-RenderedHTMLCommon h4,\n.jp-RenderedHTMLCommon h5,\n.jp-RenderedHTMLCommon h6 {\n  line-height: var(--jp-content-heading-line-height);\n  font-weight: var(--jp-content-heading-font-weight);\n  font-style: normal;\n  margin: var(--jp-content-heading-margin-top) 0\n    var(--jp-content-heading-margin-bottom) 0;\n}\n\n.jp-RenderedHTMLCommon h1:first-child,\n.jp-RenderedHTMLCommon h2:first-child,\n.jp-RenderedHTMLCommon h3:first-child,\n.jp-RenderedHTMLCommon h4:first-child,\n.jp-RenderedHTMLCommon h5:first-child,\n.jp-RenderedHTMLCommon h6:first-child {\n  margin-top: calc(0.5 * var(--jp-content-heading-margin-top));\n}\n\n.jp-RenderedHTMLCommon h1:last-child,\n.jp-RenderedHTMLCommon h2:last-child,\n.jp-RenderedHTMLCommon h3:last-child,\n.jp-RenderedHTMLCommon h4:last-child,\n.jp-RenderedHTMLCommon h5:last-child,\n.jp-RenderedHTMLCommon h6:last-child {\n  margin-bottom: calc(0.5 * var(--jp-content-heading-margin-bottom));\n}\n\n.jp-RenderedHTMLCommon h1 {\n  font-size: var(--jp-content-font-size5);\n}\n\n.jp-RenderedHTMLCommon h2 {\n  font-size: var(--jp-content-font-size4);\n}\n\n.jp-RenderedHTMLCommon h3 {\n  font-size: var(--jp-content-font-size3);\n}\n\n.jp-RenderedHTMLCommon h4 {\n  font-size: var(--jp-content-font-size2);\n}\n\n.jp-RenderedHTMLCommon h5 {\n  font-size: var(--jp-content-font-size1);\n}\n\n.jp-RenderedHTMLCommon h6 {\n  font-size: var(--jp-content-font-size0);\n}\n\n/* Lists */\n\n/* stylelint-disable selector-max-type, selector-max-compound-selectors */\n\n.jp-RenderedHTMLCommon ul:not(.list-inline),\n.jp-RenderedHTMLCommon ol:not(.list-inline) {\n  padding-left: 2em;\n}\n\n.jp-RenderedHTMLCommon ul {\n  list-style: disc;\n}\n\n.jp-RenderedHTMLCommon ul ul {\n  list-style: square;\n}\n\n.jp-RenderedHTMLCommon ul ul ul {\n  list-style: circle;\n}\n\n.jp-RenderedHTMLCommon ol {\n  list-style: decimal;\n}\n\n.jp-RenderedHTMLCommon ol ol {\n  list-style: upper-alpha;\n}\n\n.jp-RenderedHTMLCommon ol ol ol {\n  list-style: lower-alpha;\n}\n\n.jp-RenderedHTMLCommon ol ol ol ol {\n  list-style: lower-roman;\n}\n\n.jp-RenderedHTMLCommon ol ol ol ol ol {\n  list-style: decimal;\n}\n\n.jp-RenderedHTMLCommon ol,\n.jp-RenderedHTMLCommon ul {\n  margin-bottom: 1em;\n}\n\n.jp-RenderedHTMLCommon ul ul,\n.jp-RenderedHTMLCommon ul ol,\n.jp-RenderedHTMLCommon ol ul,\n.jp-RenderedHTMLCommon ol ol {\n  margin-bottom: 0;\n}\n\n/* stylelint-enable selector-max-type, selector-max-compound-selectors */\n\n.jp-RenderedHTMLCommon hr {\n  color: var(--jp-border-color2);\n  background-color: var(--jp-border-color1);\n  margin-top: 1em;\n  margin-bottom: 1em;\n}\n\n.jp-RenderedHTMLCommon > pre {\n  margin: 1.5em 2em;\n}\n\n.jp-RenderedHTMLCommon pre,\n.jp-RenderedHTMLCommon code {\n  border: 0;\n  background-color: var(--jp-layout-color0);\n  color: var(--jp-content-font-color1);\n  font-family: var(--jp-code-font-family);\n  font-size: inherit;\n  line-height: var(--jp-code-line-height);\n  padding: 0;\n  white-space: pre-wrap;\n}\n\n.jp-RenderedHTMLCommon :not(pre) > code {\n  background-color: var(--jp-layout-color2);\n  padding: 1px 5px;\n}\n\n/* Tables */\n\n.jp-RenderedHTMLCommon table {\n  border-collapse: collapse;\n  border-spacing: 0;\n  border: none;\n  color: var(--jp-ui-font-color1);\n  font-size: var(--jp-ui-font-size1);\n  table-layout: fixed;\n  margin-left: auto;\n  margin-bottom: 1em;\n  margin-right: auto;\n}\n\n.jp-RenderedHTMLCommon thead {\n  border-bottom: var(--jp-border-width) solid var(--jp-border-color1);\n  vertical-align: bottom;\n}\n\n.jp-RenderedHTMLCommon td,\n.jp-RenderedHTMLCommon th,\n.jp-RenderedHTMLCommon tr {\n  vertical-align: middle;\n  padding: 0.5em;\n  line-height: normal;\n  white-space: normal;\n  max-width: none;\n  border: none;\n}\n\n.jp-RenderedMarkdown.jp-RenderedHTMLCommon td,\n.jp-RenderedMarkdown.jp-RenderedHTMLCommon th {\n  max-width: none;\n}\n\n:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon td,\n:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon th,\n:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon tr {\n  text-align: right;\n}\n\n.jp-RenderedHTMLCommon th {\n  font-weight: bold;\n}\n\n.jp-RenderedHTMLCommon tbody tr:nth-child(odd) {\n  background: var(--jp-layout-color0);\n}\n\n.jp-RenderedHTMLCommon tbody tr:nth-child(even) {\n  background: var(--jp-rendermime-table-row-background);\n}\n\n.jp-RenderedHTMLCommon tbody tr:hover {\n  background: var(--jp-rendermime-table-row-hover-background);\n}\n\n.jp-RenderedHTMLCommon p {\n  text-align: left;\n  margin: 0;\n  margin-bottom: 1em;\n}\n\n.jp-RenderedHTMLCommon img {\n  -moz-force-broken-image-icon: 1;\n}\n\n/* Restrict to direct children as other images could be nested in other content. */\n.jp-RenderedHTMLCommon > img {\n  display: block;\n  margin-left: 0;\n  margin-right: 0;\n  margin-bottom: 1em;\n}\n\n/* Change color behind transparent images if they need it... */\n[data-jp-theme-light='false'] .jp-RenderedImage img.jp-needs-light-background {\n  background-color: var(--jp-inverse-layout-color1);\n}\n\n[data-jp-theme-light='true'] .jp-RenderedImage img.jp-needs-dark-background {\n  background-color: var(--jp-inverse-layout-color1);\n}\n\n.jp-RenderedHTMLCommon img,\n.jp-RenderedImage img,\n.jp-RenderedHTMLCommon svg,\n.jp-RenderedSVG svg {\n  max-width: 100%;\n  height: auto;\n}\n\n.jp-RenderedHTMLCommon img.jp-mod-unconfined,\n.jp-RenderedImage img.jp-mod-unconfined,\n.jp-RenderedHTMLCommon svg.jp-mod-unconfined,\n.jp-RenderedSVG svg.jp-mod-unconfined {\n  max-width: none;\n}\n\n.jp-RenderedHTMLCommon .alert {\n  padding: var(--jp-notebook-padding);\n  border: var(--jp-border-width) solid transparent;\n  border-radius: var(--jp-border-radius);\n  margin-bottom: 1em;\n}\n\n.jp-RenderedHTMLCommon .alert-info {\n  color: var(--jp-info-color0);\n  background-color: var(--jp-info-color3);\n  border-color: var(--jp-info-color2);\n}\n\n.jp-RenderedHTMLCommon .alert-info hr {\n  border-color: var(--jp-info-color3);\n}\n\n.jp-RenderedHTMLCommon .alert-info > p:last-child,\n.jp-RenderedHTMLCommon .alert-info > ul:last-child {\n  margin-bottom: 0;\n}\n\n.jp-RenderedHTMLCommon .alert-warning {\n  color: var(--jp-warn-color0);\n  background-color: var(--jp-warn-color3);\n  border-color: var(--jp-warn-color2);\n}\n\n.jp-RenderedHTMLCommon .alert-warning hr {\n  border-color: var(--jp-warn-color3);\n}\n\n.jp-RenderedHTMLCommon .alert-warning > p:last-child,\n.jp-RenderedHTMLCommon .alert-warning > ul:last-child {\n  margin-bottom: 0;\n}\n\n.jp-RenderedHTMLCommon .alert-success {\n  color: var(--jp-success-color0);\n  background-color: var(--jp-success-color3);\n  border-color: var(--jp-success-color2);\n}\n\n.jp-RenderedHTMLCommon .alert-success hr {\n  border-color: var(--jp-success-color3);\n}\n\n.jp-RenderedHTMLCommon .alert-success > p:last-child,\n.jp-RenderedHTMLCommon .alert-success > ul:last-child {\n  margin-bottom: 0;\n}\n\n.jp-RenderedHTMLCommon .alert-danger {\n  color: var(--jp-error-color0);\n  background-color: var(--jp-error-color3);\n  border-color: var(--jp-error-color2);\n}\n\n.jp-RenderedHTMLCommon .alert-danger hr {\n  border-color: var(--jp-error-color3);\n}\n\n.jp-RenderedHTMLCommon .alert-danger > p:last-child,\n.jp-RenderedHTMLCommon .alert-danger > ul:last-child {\n  margin-bottom: 0;\n}\n\n.jp-RenderedHTMLCommon blockquote {\n  margin: 1em 2em;\n  padding: 0 1em;\n  border-left: 5px solid var(--jp-border-color2);\n}\n\na.jp-InternalAnchorLink {\n  visibility: hidden;\n  margin-left: 8px;\n  color: var(--md-blue-800);\n}\n\nh1:hover .jp-InternalAnchorLink,\nh2:hover .jp-InternalAnchorLink,\nh3:hover .jp-InternalAnchorLink,\nh4:hover .jp-InternalAnchorLink,\nh5:hover .jp-InternalAnchorLink,\nh6:hover .jp-InternalAnchorLink {\n  visibility: visible;\n}\n\n.jp-RenderedHTMLCommon kbd {\n  background-color: var(--jp-rendermime-table-row-background);\n  border: 1px solid var(--jp-border-color0);\n  border-bottom-color: var(--jp-border-color2);\n  border-radius: 3px;\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n  display: inline-block;\n  font-size: var(--jp-ui-font-size0);\n  line-height: 1em;\n  padding: 0.2em 0.5em;\n}\n\n/* Most direct children of .jp-RenderedHTMLCommon have a margin-bottom of 1.0.\n * At the bottom of cells this is a bit too much as there is also spacing\n * between cells. Going all the way to 0 gets too tight between markdown and\n * code cells.\n */\n.jp-RenderedHTMLCommon > *:last-child {\n  margin-bottom: 0.5em;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Copyright (c) 2014-2017, PhosphorJS Contributors\n|\n| Distributed under the terms of the BSD 3-Clause License.\n|\n| The full license is in the file LICENSE, distributed with this software.\n|----------------------------------------------------------------------------*/\n\n.lm-cursor-backdrop {\n  position: fixed;\n  width: 200px;\n  height: 200px;\n  margin-top: -100px;\n  margin-left: -100px;\n  will-change: transform;\n  z-index: 100;\n}\n\n.lm-mod-drag-image {\n  will-change: transform;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.jp-lineFormSearch {\n  padding: 4px 12px;\n  background-color: var(--jp-layout-color2);\n  box-shadow: var(--jp-toolbar-box-shadow);\n  z-index: 2;\n  font-size: var(--jp-ui-font-size1);\n}\n\n.jp-lineFormCaption {\n  font-size: var(--jp-ui-font-size0);\n  line-height: var(--jp-ui-font-size1);\n  margin-top: 4px;\n  color: var(--jp-ui-font-color0);\n}\n\n.jp-baseLineForm {\n  border: none;\n  border-radius: 0;\n  position: absolute;\n  background-size: 16px;\n  background-repeat: no-repeat;\n  background-position: center;\n  outline: none;\n}\n\n.jp-lineFormButtonContainer {\n  top: 4px;\n  right: 8px;\n  height: 24px;\n  padding: 0 12px;\n  width: 12px;\n}\n\n.jp-lineFormButtonIcon {\n  top: 0;\n  right: 0;\n  background-color: var(--jp-brand-color1);\n  height: 100%;\n  width: 100%;\n  box-sizing: border-box;\n  padding: 4px 6px;\n}\n\n.jp-lineFormButton {\n  top: 0;\n  right: 0;\n  background-color: transparent;\n  height: 100%;\n  width: 100%;\n  box-sizing: border-box;\n}\n\n.jp-lineFormWrapper {\n  overflow: hidden;\n  padding: 0 8px;\n  border: 1px solid var(--jp-border-color0);\n  background-color: var(--jp-input-active-background);\n  height: 22px;\n}\n\n.jp-lineFormWrapperFocusWithin {\n  border: var(--jp-border-width) solid var(--md-blue-500);\n  box-shadow: inset 0 0 4px var(--md-blue-300);\n}\n\n.jp-lineFormInput {\n  background: transparent;\n  width: 200px;\n  height: 100%;\n  border: none;\n  outline: none;\n  color: var(--jp-ui-font-color0);\n  line-height: 28px;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) 2014-2016, Jupyter Development Team.\n|\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-JSONEditor {\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n}\n\n.jp-JSONEditor-host {\n  flex: 1 1 auto;\n  border: var(--jp-border-width) solid var(--jp-input-border-color);\n  border-radius: 0;\n  background: var(--jp-layout-color0);\n  min-height: 50px;\n  padding: 1px;\n}\n\n.jp-JSONEditor.jp-mod-error .jp-JSONEditor-host {\n  border-color: red;\n  outline-color: red;\n}\n\n.jp-JSONEditor-header {\n  display: flex;\n  flex: 1 0 auto;\n  padding: 0 0 0 12px;\n}\n\n.jp-JSONEditor-header label {\n  flex: 0 0 auto;\n}\n\n.jp-JSONEditor-commitButton {\n  height: 16px;\n  width: 16px;\n  background-size: 18px;\n  background-repeat: no-repeat;\n  background-position: center;\n}\n\n.jp-JSONEditor-host.jp-mod-focused {\n  background-color: var(--jp-input-active-background);\n  border: 1px solid var(--jp-input-active-border-color);\n  box-shadow: var(--jp-input-box-shadow);\n}\n\n.jp-Editor.jp-mod-dropTarget {\n  border: var(--jp-border-width) solid var(--jp-input-active-border-color);\n  box-shadow: var(--jp-input-box-shadow);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n.jp-DocumentSearch-input {\n  border: none;\n  outline: none;\n  color: var(--jp-ui-font-color0);\n  font-size: var(--jp-ui-font-size1);\n  background-color: var(--jp-layout-color0);\n  font-family: var(--jp-ui-font-family);\n  padding: 2px 1px;\n  resize: none;\n}\n\n.jp-DocumentSearch-overlay {\n  position: absolute;\n  background-color: var(--jp-toolbar-background);\n  border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);\n  border-left: var(--jp-border-width) solid var(--jp-toolbar-border-color);\n  top: 0;\n  right: 0;\n  z-index: 7;\n  min-width: 405px;\n  padding: 2px;\n  font-size: var(--jp-ui-font-size1);\n\n  --jp-private-document-search-button-height: 20px;\n}\n\n.jp-DocumentSearch-overlay button {\n  background-color: var(--jp-toolbar-background);\n  outline: 0;\n}\n\n.jp-DocumentSearch-overlay button:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-DocumentSearch-overlay button:active {\n  background-color: var(--jp-layout-color3);\n}\n\n.jp-DocumentSearch-overlay-row {\n  display: flex;\n  align-items: center;\n  margin-bottom: 2px;\n}\n\n.jp-DocumentSearch-button-content {\n  display: inline-block;\n  cursor: pointer;\n  box-sizing: border-box;\n  width: 100%;\n  height: 100%;\n}\n\n.jp-DocumentSearch-button-content svg {\n  width: 100%;\n  height: 100%;\n}\n\n.jp-DocumentSearch-input-wrapper {\n  border: var(--jp-border-width) solid var(--jp-border-color0);\n  display: flex;\n  background-color: var(--jp-layout-color0);\n  margin: 2px;\n}\n\n.jp-DocumentSearch-input-wrapper:focus-within {\n  border-color: var(--jp-cell-editor-active-border-color);\n}\n\n.jp-DocumentSearch-toggle-wrapper,\n.jp-DocumentSearch-button-wrapper {\n  all: initial;\n  overflow: hidden;\n  display: inline-block;\n  border: none;\n  box-sizing: border-box;\n}\n\n.jp-DocumentSearch-toggle-wrapper {\n  width: 14px;\n  height: 14px;\n}\n\n.jp-DocumentSearch-button-wrapper {\n  width: var(--jp-private-document-search-button-height);\n  height: var(--jp-private-document-search-button-height);\n}\n\n.jp-DocumentSearch-toggle-wrapper:focus,\n.jp-DocumentSearch-button-wrapper:focus {\n  outline: var(--jp-border-width) solid\n    var(--jp-cell-editor-active-border-color);\n  outline-offset: -1px;\n}\n\n.jp-DocumentSearch-toggle-wrapper,\n.jp-DocumentSearch-button-wrapper,\n.jp-DocumentSearch-button-content:focus {\n  outline: none;\n}\n\n.jp-DocumentSearch-toggle-placeholder {\n  width: 5px;\n}\n\n.jp-DocumentSearch-input-button::before {\n  display: block;\n  padding-top: 100%;\n}\n\n.jp-DocumentSearch-input-button-off {\n  opacity: var(--jp-search-toggle-off-opacity);\n}\n\n.jp-DocumentSearch-input-button-off:hover {\n  opacity: var(--jp-search-toggle-hover-opacity);\n}\n\n.jp-DocumentSearch-input-button-on {\n  opacity: var(--jp-search-toggle-on-opacity);\n}\n\n.jp-DocumentSearch-index-counter {\n  padding-left: 10px;\n  padding-right: 10px;\n  user-select: none;\n  min-width: 35px;\n  display: inline-block;\n}\n\n.jp-DocumentSearch-up-down-wrapper {\n  display: inline-block;\n  padding-right: 2px;\n  margin-left: auto;\n  white-space: nowrap;\n}\n\n.jp-DocumentSearch-spacer {\n  margin-left: auto;\n}\n\n.jp-DocumentSearch-up-down-wrapper button {\n  outline: 0;\n  border: none;\n  width: var(--jp-private-document-search-button-height);\n  height: var(--jp-private-document-search-button-height);\n  vertical-align: middle;\n  margin: 1px 5px 2px;\n}\n\n.jp-DocumentSearch-up-down-button:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-DocumentSearch-up-down-button:active {\n  background-color: var(--jp-layout-color3);\n}\n\n.jp-DocumentSearch-filter-button {\n  border-radius: var(--jp-border-radius);\n}\n\n.jp-DocumentSearch-filter-button:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-DocumentSearch-filter-button-enabled {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-DocumentSearch-filter-button-enabled:hover {\n  background-color: var(--jp-layout-color3);\n}\n\n.jp-DocumentSearch-search-options {\n  padding: 0 8px;\n  margin-left: 3px;\n  width: 100%;\n  display: grid;\n  justify-content: start;\n  grid-template-columns: 1fr 1fr;\n  align-items: center;\n  justify-items: stretch;\n}\n\n.jp-DocumentSearch-search-filter-disabled {\n  color: var(--jp-ui-font-color2);\n}\n\n.jp-DocumentSearch-search-filter {\n  display: flex;\n  align-items: center;\n  user-select: none;\n}\n\n.jp-DocumentSearch-regex-error {\n  color: var(--jp-error-color0);\n}\n\n.jp-DocumentSearch-replace-button-wrapper {\n  overflow: hidden;\n  display: inline-block;\n  box-sizing: border-box;\n  border: var(--jp-border-width) solid var(--jp-border-color0);\n  margin: auto 2px;\n  padding: 1px 4px;\n  height: calc(var(--jp-private-document-search-button-height) + 2px);\n}\n\n.jp-DocumentSearch-replace-button-wrapper:focus {\n  border: var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);\n}\n\n.jp-DocumentSearch-replace-button {\n  display: inline-block;\n  text-align: center;\n  cursor: pointer;\n  box-sizing: border-box;\n  color: var(--jp-ui-font-color1);\n\n  /* height - 2 * (padding of wrapper) */\n  line-height: calc(var(--jp-private-document-search-button-height) - 2px);\n  width: 100%;\n  height: 100%;\n}\n\n.jp-DocumentSearch-replace-button:focus {\n  outline: none;\n}\n\n.jp-DocumentSearch-replace-wrapper-class {\n  margin-left: 14px;\n  display: flex;\n}\n\n.jp-DocumentSearch-replace-toggle {\n  border: none;\n  background-color: var(--jp-toolbar-background);\n  border-radius: var(--jp-border-radius);\n}\n\n.jp-DocumentSearch-replace-toggle:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.cm-editor {\n  line-height: var(--jp-code-line-height);\n  font-size: var(--jp-code-font-size);\n  font-family: var(--jp-code-font-family);\n  border: 0;\n  border-radius: 0;\n  height: auto;\n\n  /* Changed to auto to autogrow */\n}\n\n.cm-editor pre {\n  padding: 0 var(--jp-code-padding);\n}\n\n.jp-CodeMirrorEditor[data-type='inline'] .cm-dialog {\n  background-color: var(--jp-layout-color0);\n  color: var(--jp-content-font-color1);\n}\n\n.jp-CodeMirrorEditor {\n  cursor: text;\n}\n\n/* When zoomed out 67% and 33% on a screen of 1440 width x 900 height */\n@media screen and (min-width: 2138px) and (max-width: 4319px) {\n  .jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {\n    border-left: var(--jp-code-cursor-width1) solid\n      var(--jp-editor-cursor-color);\n  }\n}\n\n/* When zoomed out less than 33% */\n@media screen and (min-width: 4320px) {\n  .jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {\n    border-left: var(--jp-code-cursor-width2) solid\n      var(--jp-editor-cursor-color);\n  }\n}\n\n.cm-editor.jp-mod-readOnly .cm-cursor {\n  display: none;\n}\n\n.jp-CollaboratorCursor {\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-top: none;\n  border-bottom: 3px solid;\n  background-clip: content-box;\n  margin-left: -5px;\n  margin-right: -5px;\n}\n\n.cm-searching,\n.cm-searching span {\n  /* `.cm-searching span`: we need to override syntax highlighting */\n  background-color: var(--jp-search-unselected-match-background-color);\n  color: var(--jp-search-unselected-match-color);\n}\n\n.cm-searching::selection,\n.cm-searching span::selection {\n  background-color: var(--jp-search-unselected-match-background-color);\n  color: var(--jp-search-unselected-match-color);\n}\n\n.jp-current-match > .cm-searching,\n.jp-current-match > .cm-searching span,\n.cm-searching > .jp-current-match,\n.cm-searching > .jp-current-match span {\n  background-color: var(--jp-search-selected-match-background-color);\n  color: var(--jp-search-selected-match-color);\n}\n\n.jp-current-match > .cm-searching::selection,\n.cm-searching > .jp-current-match::selection,\n.jp-current-match > .cm-searching span::selection {\n  background-color: var(--jp-search-selected-match-background-color);\n  color: var(--jp-search-selected-match-color);\n}\n\n.cm-trailingspace {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);\n  background-position: center left;\n  background-repeat: repeat-x;\n}\n\n.jp-CollaboratorCursor-hover {\n  position: absolute;\n  z-index: 1;\n  transform: translateX(-50%);\n  color: white;\n  border-radius: 3px;\n  padding-left: 4px;\n  padding-right: 4px;\n  padding-top: 1px;\n  padding-bottom: 1px;\n  text-align: center;\n  font-size: var(--jp-ui-font-size1);\n  white-space: nowrap;\n}\n\n.jp-CodeMirror-ruler {\n  border-left: 1px dashed var(--jp-border-color2);\n}\n\n/* Styles for shared cursors (remote cursor locations and selected ranges) */\n.jp-CodeMirrorEditor .cm-ySelectionCaret {\n  position: relative;\n  border-left: 1px solid black;\n  margin-left: -1px;\n  margin-right: -1px;\n  box-sizing: border-box;\n}\n\n.jp-CodeMirrorEditor .cm-ySelectionCaret > .cm-ySelectionInfo {\n  white-space: nowrap;\n  position: absolute;\n  top: -1.15em;\n  padding-bottom: 0.05em;\n  left: -1px;\n  font-size: 0.95em;\n  font-family: var(--jp-ui-font-family);\n  font-weight: bold;\n  line-height: normal;\n  user-select: none;\n  color: white;\n  padding-left: 2px;\n  padding-right: 2px;\n  z-index: 101;\n  transition: opacity 0.3s ease-in-out;\n}\n\n.jp-CodeMirrorEditor .cm-ySelectionInfo {\n  transition-delay: 0.7s;\n  opacity: 0;\n}\n\n.jp-CodeMirrorEditor .cm-ySelectionCaret:hover > .cm-ySelectionInfo {\n  opacity: 1;\n  transition-delay: 0s;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-MimeDocument {\n  outline: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Variables\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-private-filebrowser-button-height: 28px;\n  --jp-private-filebrowser-button-width: 48px;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-FileBrowser .jp-SidePanel-content {\n  display: flex;\n  flex-direction: column;\n}\n\n.jp-FileBrowser-toolbar.jp-Toolbar {\n  flex-wrap: wrap;\n  row-gap: 12px;\n  border-bottom: none;\n  height: auto;\n  margin: 8px 12px 0;\n  box-shadow: none;\n  padding: 0;\n  justify-content: flex-start;\n}\n\n.jp-FileBrowser-Panel {\n  flex: 1 1 auto;\n  display: flex;\n  flex-direction: column;\n}\n\n.jp-BreadCrumbs {\n  flex: 0 0 auto;\n  margin: 8px 12px;\n}\n\n.jp-BreadCrumbs-item {\n  margin: 0 2px;\n  padding: 0 2px;\n  border-radius: var(--jp-border-radius);\n  cursor: pointer;\n}\n\n.jp-BreadCrumbs-item:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-BreadCrumbs-item:first-child {\n  margin-left: 0;\n}\n\n.jp-BreadCrumbs-item.jp-mod-dropTarget {\n  background-color: var(--jp-brand-color2);\n  opacity: 0.7;\n}\n\n/*-----------------------------------------------------------------------------\n| Buttons\n|----------------------------------------------------------------------------*/\n\n.jp-FileBrowser-toolbar > .jp-Toolbar-item {\n  flex: 0 0 auto;\n  padding-left: 0;\n  padding-right: 2px;\n  align-items: center;\n  height: unset;\n}\n\n.jp-FileBrowser-toolbar > .jp-Toolbar-item .jp-ToolbarButtonComponent {\n  width: 40px;\n}\n\n/*-----------------------------------------------------------------------------\n| Other styles\n|----------------------------------------------------------------------------*/\n\n.jp-FileDialog.jp-mod-conflict input {\n  color: var(--jp-error-color1);\n}\n\n.jp-FileDialog .jp-new-name-title {\n  margin-top: 12px;\n}\n\n.jp-LastModified-hidden {\n  display: none;\n}\n\n.jp-FileSize-hidden {\n  display: none;\n}\n\n.jp-FileBrowser .lm-AccordionPanel > h3:first-child {\n  display: none;\n}\n\n/*-----------------------------------------------------------------------------\n| DirListing\n|----------------------------------------------------------------------------*/\n\n.jp-DirListing {\n  flex: 1 1 auto;\n  display: flex;\n  flex-direction: column;\n  outline: 0;\n}\n\n.jp-DirListing-header {\n  flex: 0 0 auto;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  overflow: hidden;\n  border-top: var(--jp-border-width) solid var(--jp-border-color2);\n  border-bottom: var(--jp-border-width) solid var(--jp-border-color1);\n  box-shadow: var(--jp-toolbar-box-shadow);\n  z-index: 2;\n}\n\n.jp-DirListing-headerItem {\n  padding: 4px 12px 2px;\n  font-weight: 500;\n}\n\n.jp-DirListing-headerItem:hover {\n  background: var(--jp-layout-color2);\n}\n\n.jp-DirListing-headerItem.jp-id-name {\n  flex: 1 0 84px;\n}\n\n.jp-DirListing-headerItem.jp-id-modified {\n  flex: 0 0 112px;\n  border-left: var(--jp-border-width) solid var(--jp-border-color2);\n  text-align: right;\n}\n\n.jp-DirListing-headerItem.jp-id-filesize {\n  flex: 0 0 75px;\n  border-left: var(--jp-border-width) solid var(--jp-border-color2);\n  text-align: right;\n}\n\n.jp-id-narrow {\n  display: none;\n  flex: 0 0 5px;\n  padding: 4px;\n  border-left: var(--jp-border-width) solid var(--jp-border-color2);\n  text-align: right;\n  color: var(--jp-border-color2);\n}\n\n.jp-DirListing-narrow .jp-id-narrow {\n  display: block;\n}\n\n.jp-DirListing-narrow .jp-id-modified,\n.jp-DirListing-narrow .jp-DirListing-itemModified {\n  display: none;\n}\n\n.jp-DirListing-headerItem.jp-mod-selected {\n  font-weight: 600;\n}\n\n/* increase specificity to override bundled default */\n.jp-DirListing-content {\n  flex: 1 1 auto;\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n  overflow: auto;\n  background-color: var(--jp-layout-color1);\n}\n\n.jp-DirListing-content mark {\n  color: var(--jp-ui-font-color0);\n  background-color: transparent;\n  font-weight: bold;\n}\n\n.jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark {\n  color: var(--jp-ui-inverse-font-color0);\n}\n\n/* Style the directory listing content when a user drops a file to upload */\n.jp-DirListing.jp-mod-native-drop .jp-DirListing-content {\n  outline: 5px dashed rgba(128, 128, 128, 0.5);\n  outline-offset: -10px;\n  cursor: copy;\n}\n\n.jp-DirListing-item {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  padding: 4px 12px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.jp-DirListing-checkboxWrapper {\n  /* Increases hit area of checkbox. */\n  padding: 4px;\n}\n\n.jp-DirListing-header\n  .jp-DirListing-checkboxWrapper\n  + .jp-DirListing-headerItem {\n  padding-left: 4px;\n}\n\n.jp-DirListing-content .jp-DirListing-checkboxWrapper {\n  position: relative;\n  left: -4px;\n  margin: -4px 0 -4px -8px;\n}\n\n.jp-DirListing-checkboxWrapper.jp-mod-visible {\n  visibility: visible;\n}\n\n/* For devices that support hovering, hide checkboxes until hovered, selected...\n*/\n@media (hover: hover) {\n  .jp-DirListing-checkboxWrapper {\n    visibility: hidden;\n  }\n\n  .jp-DirListing-item:hover .jp-DirListing-checkboxWrapper,\n  .jp-DirListing-item.jp-mod-selected .jp-DirListing-checkboxWrapper {\n    visibility: visible;\n  }\n}\n\n.jp-DirListing-item[data-is-dot] {\n  opacity: 75%;\n}\n\n.jp-DirListing-item.jp-mod-selected {\n  color: var(--jp-ui-inverse-font-color1);\n  background: var(--jp-brand-color1);\n}\n\n.jp-DirListing-item.jp-mod-dropTarget {\n  background: var(--jp-brand-color3);\n}\n\n.jp-DirListing-item:hover:not(.jp-mod-selected) {\n  background: var(--jp-layout-color2);\n}\n\n.jp-DirListing-itemIcon {\n  flex: 0 0 20px;\n  margin-right: 4px;\n}\n\n.jp-DirListing-itemText {\n  flex: 1 0 64px;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  user-select: none;\n}\n\n.jp-DirListing-itemText:focus {\n  outline-width: 2px;\n  outline-color: var(--jp-inverse-layout-color1);\n  outline-style: solid;\n  outline-offset: 1px;\n}\n\n.jp-DirListing-item.jp-mod-selected .jp-DirListing-itemText:focus {\n  outline-color: var(--jp-layout-color1);\n}\n\n.jp-DirListing-itemModified {\n  flex: 0 0 125px;\n  text-align: right;\n}\n\n.jp-DirListing-itemFileSize {\n  flex: 0 0 90px;\n  text-align: right;\n}\n\n.jp-DirListing-editor {\n  flex: 1 0 64px;\n  outline: none;\n  border: none;\n  color: var(--jp-ui-font-color1);\n  background-color: var(--jp-layout-color1);\n}\n\n.jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon::before {\n  color: var(--jp-success-color1);\n  content: '\\25CF';\n  font-size: 8px;\n  position: absolute;\n  left: -8px;\n}\n\n.jp-DirListing-item.jp-mod-running.jp-mod-selected\n  .jp-DirListing-itemIcon::before {\n  color: var(--jp-ui-inverse-font-color1);\n}\n\n.jp-DirListing-item.lm-mod-drag-image,\n.jp-DirListing-item.jp-mod-selected.lm-mod-drag-image {\n  font-size: var(--jp-ui-font-size1);\n  padding-left: 4px;\n  margin-left: 4px;\n  width: 160px;\n  background-color: var(--jp-ui-inverse-font-color2);\n  box-shadow: var(--jp-elevation-z2);\n  border-radius: 0;\n  color: var(--jp-ui-font-color1);\n  transform: translateX(-40%) translateY(-58%);\n}\n\n.jp-Document {\n  min-width: 120px;\n  min-height: 120px;\n  outline: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Main OutputArea\n| OutputArea has a list of Outputs\n|----------------------------------------------------------------------------*/\n\n.jp-OutputArea {\n  overflow-y: auto;\n}\n\n.jp-OutputArea-child {\n  display: table;\n  table-layout: fixed;\n  width: 100%;\n  overflow: hidden;\n}\n\n.jp-OutputPrompt {\n  width: var(--jp-cell-prompt-width);\n  color: var(--jp-cell-outprompt-font-color);\n  font-family: var(--jp-cell-prompt-font-family);\n  padding: var(--jp-code-padding);\n  letter-spacing: var(--jp-cell-prompt-letter-spacing);\n  line-height: var(--jp-code-line-height);\n  font-size: var(--jp-code-font-size);\n  border: var(--jp-border-width) solid transparent;\n  opacity: var(--jp-cell-prompt-opacity);\n\n  /* Right align prompt text, don't wrap to handle large prompt numbers */\n  text-align: right;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n\n  /* Disable text selection */\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.jp-OutputArea-prompt {\n  display: table-cell;\n  vertical-align: top;\n}\n\n.jp-OutputArea-output {\n  display: table-cell;\n  width: 100%;\n  height: auto;\n  overflow: auto;\n  user-select: text;\n  -moz-user-select: text;\n  -webkit-user-select: text;\n  -ms-user-select: text;\n}\n\n.jp-OutputArea .jp-RenderedText {\n  padding-left: 1ch;\n}\n\n/**\n * Prompt overlay.\n */\n\n.jp-OutputArea-promptOverlay {\n  position: absolute;\n  top: 0;\n  width: var(--jp-cell-prompt-width);\n  height: 100%;\n  opacity: 0.5;\n}\n\n.jp-OutputArea-promptOverlay:hover {\n  background: var(--jp-layout-color2);\n  box-shadow: inset 0 0 1px var(--jp-inverse-layout-color0);\n  cursor: zoom-out;\n}\n\n.jp-mod-outputsScrolled .jp-OutputArea-promptOverlay:hover {\n  cursor: zoom-in;\n}\n\n/**\n * Isolated output.\n */\n.jp-OutputArea-output.jp-mod-isolated {\n  width: 100%;\n  display: block;\n}\n\n/*\nWhen drag events occur, `lm-mod-override-cursor` is added to the body.\nBecause iframes steal all cursor events, the following two rules are necessary\nto suppress pointer events while resize drags are occurring. There may be a\nbetter solution to this problem.\n*/\nbody.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated {\n  position: relative;\n}\n\nbody.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated::before {\n  content: '';\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background: transparent;\n}\n\n/* pre */\n\n.jp-OutputArea-output pre {\n  border: none;\n  margin: 0;\n  padding: 0;\n  overflow-x: auto;\n  overflow-y: auto;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre-wrap;\n}\n\n/* tables */\n\n.jp-OutputArea-output.jp-RenderedHTMLCommon table {\n  margin-left: 0;\n  margin-right: 0;\n}\n\n/* description lists */\n\n.jp-OutputArea-output dl,\n.jp-OutputArea-output dt,\n.jp-OutputArea-output dd {\n  display: block;\n}\n\n.jp-OutputArea-output dl {\n  width: 100%;\n  overflow: hidden;\n  padding: 0;\n  margin: 0;\n}\n\n.jp-OutputArea-output dt {\n  font-weight: bold;\n  float: left;\n  width: 20%;\n  padding: 0;\n  margin: 0;\n}\n\n.jp-OutputArea-output dd {\n  float: left;\n  width: 80%;\n  padding: 0;\n  margin: 0;\n}\n\n.jp-TrimmedOutputs pre {\n  background: var(--jp-layout-color3);\n  font-size: calc(var(--jp-code-font-size) * 1.4);\n  text-align: center;\n  text-transform: uppercase;\n}\n\n/* Hide the gutter in case of\n *  - nested output areas (e.g. in the case of output widgets)\n *  - mirrored output areas\n */\n.jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt {\n  display: none;\n}\n\n/* Hide empty lines in the output area, for instance due to cleared widgets */\n.jp-OutputArea-prompt:empty {\n  padding: 0;\n  border: 0;\n}\n\n/*-----------------------------------------------------------------------------\n| executeResult is added to any Output-result for the display of the object\n| returned by a cell\n|----------------------------------------------------------------------------*/\n\n.jp-OutputArea-output.jp-OutputArea-executeResult {\n  margin-left: 0;\n  width: 100%;\n}\n\n/* Text output with the Out[] prompt needs a top padding to match the\n * alignment of the Out[] prompt itself.\n */\n.jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output {\n  padding-top: var(--jp-code-padding);\n  border-top: var(--jp-border-width) solid transparent;\n}\n\n/*-----------------------------------------------------------------------------\n| The Stdin output\n|----------------------------------------------------------------------------*/\n\n.jp-Stdin-prompt {\n  color: var(--jp-content-font-color0);\n  padding-right: var(--jp-code-padding);\n  vertical-align: baseline;\n  flex: 0 0 auto;\n}\n\n.jp-Stdin-input {\n  font-family: var(--jp-code-font-family);\n  font-size: inherit;\n  color: inherit;\n  background-color: inherit;\n  width: 42%;\n  min-width: 200px;\n\n  /* make sure input baseline aligns with prompt */\n  vertical-align: baseline;\n\n  /* padding + margin = 0.5em between prompt and cursor */\n  padding: 0 0.25em;\n  margin: 0 0.25em;\n  flex: 0 0 70%;\n}\n\n.jp-Stdin-input::placeholder {\n  opacity: 0;\n}\n\n.jp-Stdin-input:focus {\n  box-shadow: none;\n}\n\n.jp-Stdin-input:focus::placeholder {\n  opacity: 1;\n}\n\n/*-----------------------------------------------------------------------------\n| Output Area View\n|----------------------------------------------------------------------------*/\n\n.jp-LinkedOutputView .jp-OutputArea {\n  height: 100%;\n  display: block;\n}\n\n.jp-LinkedOutputView .jp-OutputArea-output:only-child {\n  height: 100%;\n}\n\n/*-----------------------------------------------------------------------------\n| Printing\n|----------------------------------------------------------------------------*/\n\n@media print {\n  .jp-OutputArea-child {\n    break-inside: avoid-page;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Mobile\n|----------------------------------------------------------------------------*/\n@media only screen and (max-width: 760px) {\n  .jp-OutputPrompt {\n    display: table-row;\n    text-align: left;\n  }\n\n  .jp-OutputArea-child .jp-OutputArea-output {\n    display: table-row;\n    margin-left: var(--jp-notebook-padding);\n  }\n}\n\n/* Trimmed outputs warning */\n.jp-TrimmedOutputs > a {\n  margin: 10px;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.jp-TrimmedOutputs > a:hover {\n  text-decoration: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Table of Contents\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-private-toc-active-width: 4px;\n}\n\n.jp-TableOfContents {\n  display: flex;\n  flex-direction: column;\n  background: var(--jp-layout-color1);\n  color: var(--jp-ui-font-color1);\n  font-size: var(--jp-ui-font-size1);\n  height: 100%;\n}\n\n.jp-TableOfContents-placeholder {\n  text-align: center;\n}\n\n.jp-TableOfContents-placeholderContent {\n  color: var(--jp-content-font-color2);\n  padding: 8px;\n}\n\n.jp-TableOfContents-placeholderContent > h3 {\n  margin-bottom: var(--jp-content-heading-margin-bottom);\n}\n\n.jp-TableOfContents .jp-SidePanel-content {\n  overflow-y: auto;\n}\n\n.jp-TableOfContents-tree {\n  margin: 4px;\n}\n\n.jp-TableOfContents ol {\n  list-style-type: none;\n}\n\n/* stylelint-disable-next-line selector-max-type */\n.jp-TableOfContents li > ol {\n  /* Align left border with triangle icon center */\n  padding-left: 11px;\n}\n\n.jp-TableOfContents-content {\n  /* left margin for the active heading indicator */\n  margin: 0 0 0 var(--jp-private-toc-active-width);\n  padding: 0;\n  background-color: var(--jp-layout-color1);\n}\n\n.jp-tocItem {\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.jp-tocItem-heading {\n  display: flex;\n  cursor: pointer;\n}\n\n.jp-tocItem-heading:hover {\n  background-color: var(--jp-layout-color2);\n}\n\n.jp-tocItem-content {\n  display: block;\n  padding: 4px 0;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow-x: hidden;\n}\n\n.jp-tocItem-collapser {\n  height: 20px;\n  margin: 2px 2px 0;\n  padding: 0;\n  background: none;\n  border: none;\n  cursor: pointer;\n}\n\n.jp-tocItem-collapser:hover {\n  background-color: var(--jp-layout-color3);\n}\n\n/* Active heading indicator */\n\n.jp-tocItem-heading::before {\n  content: ' ';\n  background: transparent;\n  width: var(--jp-private-toc-active-width);\n  height: 24px;\n  position: absolute;\n  left: 0;\n  border-radius: var(--jp-border-radius);\n}\n\n.jp-tocItem-heading.jp-tocItem-active::before {\n  background-color: var(--jp-brand-color1);\n}\n\n.jp-tocItem-heading:hover.jp-tocItem-active::before {\n  background: var(--jp-brand-color0);\n  opacity: 1;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n.jp-Collapser {\n  flex: 0 0 var(--jp-cell-collapser-width);\n  padding: 0;\n  margin: 0;\n  border: none;\n  outline: none;\n  background: transparent;\n  border-radius: var(--jp-border-radius);\n  opacity: 1;\n}\n\n.jp-Collapser-child {\n  display: block;\n  width: 100%;\n  box-sizing: border-box;\n\n  /* height: 100% doesn't work because the height of its parent is computed from content */\n  position: absolute;\n  top: 0;\n  bottom: 0;\n}\n\n/*-----------------------------------------------------------------------------\n| Printing\n|----------------------------------------------------------------------------*/\n\n/*\nHiding collapsers in print mode.\n\nNote: input and output wrappers have \"display: block\" propery in print mode.\n*/\n\n@media print {\n  .jp-Collapser {\n    display: none;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Header/Footer\n|----------------------------------------------------------------------------*/\n\n/* Hidden by zero height by default */\n.jp-CellHeader,\n.jp-CellFooter {\n  height: 0;\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  border: none;\n  outline: none;\n  background: transparent;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Input\n|----------------------------------------------------------------------------*/\n\n/* All input areas */\n.jp-InputArea {\n  display: table;\n  table-layout: fixed;\n  width: 100%;\n  overflow: hidden;\n}\n\n.jp-InputArea-editor {\n  display: table-cell;\n  overflow: hidden;\n  vertical-align: top;\n\n  /* This is the non-active, default styling */\n  border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);\n  border-radius: 0;\n  background: var(--jp-cell-editor-background);\n}\n\n.jp-InputPrompt {\n  display: table-cell;\n  vertical-align: top;\n  width: var(--jp-cell-prompt-width);\n  color: var(--jp-cell-inprompt-font-color);\n  font-family: var(--jp-cell-prompt-font-family);\n  padding: var(--jp-code-padding);\n  letter-spacing: var(--jp-cell-prompt-letter-spacing);\n  opacity: var(--jp-cell-prompt-opacity);\n  line-height: var(--jp-code-line-height);\n  font-size: var(--jp-code-font-size);\n  border: var(--jp-border-width) solid transparent;\n\n  /* Right align prompt text, don't wrap to handle large prompt numbers */\n  text-align: right;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n\n  /* Disable text selection */\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Mobile\n|----------------------------------------------------------------------------*/\n@media only screen and (max-width: 760px) {\n  .jp-InputArea-editor {\n    display: table-row;\n    margin-left: var(--jp-notebook-padding);\n  }\n\n  .jp-InputPrompt {\n    display: table-row;\n    text-align: left;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Placeholder\n|----------------------------------------------------------------------------*/\n\n.jp-Placeholder {\n  display: table;\n  table-layout: fixed;\n  width: 100%;\n}\n\n.jp-Placeholder-prompt {\n  display: table-cell;\n  box-sizing: border-box;\n}\n\n.jp-Placeholder-content {\n  display: table-cell;\n  padding: 4px 6px;\n  border: 1px solid transparent;\n  border-radius: 0;\n  background: none;\n  box-sizing: border-box;\n  cursor: pointer;\n}\n\n.jp-Placeholder-contentContainer {\n  display: flex;\n}\n\n.jp-Placeholder-content:hover,\n.jp-InputPlaceholder > .jp-Placeholder-content:hover {\n  border-color: var(--jp-layout-color3);\n}\n\n.jp-Placeholder-content .jp-MoreHorizIcon {\n  width: 32px;\n  height: 16px;\n  border: 1px solid transparent;\n  border-radius: var(--jp-border-radius);\n}\n\n.jp-Placeholder-content .jp-MoreHorizIcon:hover {\n  border: 1px solid var(--jp-border-color1);\n  box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.25);\n  background-color: var(--jp-layout-color0);\n}\n\n.jp-PlaceholderText {\n  white-space: nowrap;\n  overflow-x: hidden;\n  color: var(--jp-inverse-layout-color3);\n  font-family: var(--jp-code-font-family);\n}\n\n.jp-InputPlaceholder > .jp-Placeholder-content {\n  border-color: var(--jp-cell-editor-border-color);\n  background: var(--jp-cell-editor-background);\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Private CSS variables\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-private-cell-scrolling-output-offset: 5px;\n}\n\n/*-----------------------------------------------------------------------------\n| Cell\n|----------------------------------------------------------------------------*/\n\n.jp-Cell {\n  padding: var(--jp-cell-padding);\n  margin: 0;\n  border: none;\n  outline: none;\n  background: transparent;\n}\n\n/*-----------------------------------------------------------------------------\n| Common input/output\n|----------------------------------------------------------------------------*/\n\n.jp-Cell-inputWrapper,\n.jp-Cell-outputWrapper {\n  display: flex;\n  flex-direction: row;\n  padding: 0;\n  margin: 0;\n\n  /* Added to reveal the box-shadow on the input and output collapsers. */\n  overflow: visible;\n}\n\n/* Only input/output areas inside cells */\n.jp-Cell-inputArea,\n.jp-Cell-outputArea {\n  flex: 1 1 auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Collapser\n|----------------------------------------------------------------------------*/\n\n/* Make the output collapser disappear when there is not output, but do so\n * in a manner that leaves it in the layout and preserves its width.\n */\n.jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser {\n  border: none !important;\n  background: transparent !important;\n}\n\n.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser {\n  min-height: var(--jp-cell-collapser-min-height);\n}\n\n/*-----------------------------------------------------------------------------\n| Output\n|----------------------------------------------------------------------------*/\n\n/* Put a space between input and output when there IS output */\n.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper {\n  margin-top: 5px;\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea {\n  overflow-y: auto;\n  max-height: 24em;\n  margin-left: var(--jp-private-cell-scrolling-output-offset);\n  resize: vertical;\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea[style*='height'] {\n  max-height: unset;\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea::after {\n  content: ' ';\n  box-shadow: inset 0 0 6px 2px rgb(0 0 0 / 30%);\n  width: 100%;\n  height: 100%;\n  position: sticky;\n  bottom: 0;\n  top: 0;\n  margin-top: -50%;\n  float: left;\n  display: block;\n  pointer-events: none;\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child {\n  padding-top: 6px;\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt {\n  width: calc(\n    var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset)\n  );\n}\n\n.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-promptOverlay {\n  left: calc(-1 * var(--jp-private-cell-scrolling-output-offset));\n}\n\n/*-----------------------------------------------------------------------------\n| CodeCell\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| MarkdownCell\n|----------------------------------------------------------------------------*/\n\n.jp-MarkdownOutput {\n  display: table-cell;\n  width: 100%;\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-left: var(--jp-code-padding);\n}\n\n.jp-MarkdownOutput.jp-RenderedHTMLCommon {\n  overflow: auto;\n}\n\n/* collapseHeadingButton (show always if hiddenCellsButton is _not_ shown) */\n.jp-collapseHeadingButton {\n  display: flex;\n  min-height: var(--jp-cell-collapser-min-height);\n  font-size: var(--jp-code-font-size);\n  position: absolute;\n  background-color: transparent;\n  background-size: 25px;\n  background-repeat: no-repeat;\n  background-position-x: center;\n  background-position-y: top;\n  background-image: var(--jp-icon-caret-down);\n  right: 0;\n  top: 0;\n  bottom: 0;\n}\n\n.jp-collapseHeadingButton.jp-mod-collapsed {\n  background-image: var(--jp-icon-caret-right);\n}\n\n/*\n set the container font size to match that of content\n so that the nested collapse buttons have the right size\n*/\n.jp-MarkdownCell .jp-InputPrompt {\n  font-size: var(--jp-content-font-size1);\n}\n\n/*\n  Align collapseHeadingButton with cell top header\n  The font sizes are identical to the ones in packages/rendermime/style/base.css\n*/\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='1'] {\n  font-size: var(--jp-content-font-size5);\n  background-position-y: calc(0.3 * var(--jp-content-font-size5));\n}\n\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='2'] {\n  font-size: var(--jp-content-font-size4);\n  background-position-y: calc(0.3 * var(--jp-content-font-size4));\n}\n\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='3'] {\n  font-size: var(--jp-content-font-size3);\n  background-position-y: calc(0.3 * var(--jp-content-font-size3));\n}\n\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='4'] {\n  font-size: var(--jp-content-font-size2);\n  background-position-y: calc(0.3 * var(--jp-content-font-size2));\n}\n\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='5'] {\n  font-size: var(--jp-content-font-size1);\n  background-position-y: top;\n}\n\n.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='6'] {\n  font-size: var(--jp-content-font-size0);\n  background-position-y: top;\n}\n\n/* collapseHeadingButton (show only on (hover,active) if hiddenCellsButton is shown) */\n.jp-Notebook.jp-mod-showHiddenCellsButton .jp-collapseHeadingButton {\n  display: none;\n}\n\n.jp-Notebook.jp-mod-showHiddenCellsButton\n  :is(.jp-MarkdownCell:hover, .jp-mod-active)\n  .jp-collapseHeadingButton {\n  display: flex;\n}\n\n/* showHiddenCellsButton (only show if jp-mod-showHiddenCellsButton is set, which\nis a consequence of the showHiddenCellsButton option in Notebook Settings)*/\n.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton {\n  margin-left: calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));\n  margin-top: var(--jp-code-padding);\n  border: 1px solid var(--jp-border-color2);\n  background-color: var(--jp-border-color3) !important;\n  color: var(--jp-content-font-color0) !important;\n  display: flex;\n}\n\n.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton:hover {\n  background-color: var(--jp-border-color2) !important;\n}\n\n.jp-showHiddenCellsButton {\n  display: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Printing\n|----------------------------------------------------------------------------*/\n\n/*\nUsing block instead of flex to allow the use of the break-inside CSS property for\ncell outputs.\n*/\n\n@media print {\n  .jp-Cell-inputWrapper,\n  .jp-Cell-outputWrapper {\n    display: block;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Variables\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-notebook-toolbar-padding: 2px 5px 2px 2px;\n}\n\n/*-----------------------------------------------------------------------------\n\n/*-----------------------------------------------------------------------------\n| Styles\n|----------------------------------------------------------------------------*/\n\n.jp-NotebookPanel-toolbar {\n  padding: var(--jp-notebook-toolbar-padding);\n\n  /* disable paint containment from lumino 2.0 default strict CSS containment */\n  contain: style size !important;\n}\n\n.jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused {\n  border: none;\n  box-shadow: none;\n}\n\n.jp-Notebook-toolbarCellTypeDropdown select {\n  height: 24px;\n  font-size: var(--jp-ui-font-size1);\n  line-height: 14px;\n  border-radius: 0;\n  display: block;\n}\n\n.jp-Notebook-toolbarCellTypeDropdown span {\n  top: 5px !important;\n}\n\n.jp-Toolbar-responsive-popup {\n  position: absolute;\n  height: fit-content;\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);\n  box-shadow: var(--jp-toolbar-box-shadow);\n  background: var(--jp-toolbar-background);\n  min-height: var(--jp-toolbar-micro-height);\n  padding: var(--jp-notebook-toolbar-padding);\n  z-index: 1;\n  right: 0;\n  top: 0;\n}\n\n.jp-Toolbar > .jp-Toolbar-responsive-opener {\n  margin-left: auto;\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Variables\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n\n/*-----------------------------------------------------------------------------\n| Styles\n|----------------------------------------------------------------------------*/\n\n.jp-Notebook-ExecutionIndicator {\n  position: relative;\n  display: inline-block;\n  height: 100%;\n  z-index: 9997;\n}\n\n.jp-Notebook-ExecutionIndicator-tooltip {\n  visibility: hidden;\n  height: auto;\n  width: max-content;\n  width: -moz-max-content;\n  background-color: var(--jp-layout-color2);\n  color: var(--jp-ui-font-color1);\n  text-align: justify;\n  border-radius: 6px;\n  padding: 0 5px;\n  position: fixed;\n  display: table;\n}\n\n.jp-Notebook-ExecutionIndicator-tooltip.up {\n  transform: translateX(-50%) translateY(-100%) translateY(-32px);\n}\n\n.jp-Notebook-ExecutionIndicator-tooltip.down {\n  transform: translateX(calc(-100% + 16px)) translateY(5px);\n}\n\n.jp-Notebook-ExecutionIndicator-tooltip.hidden {\n  display: none;\n}\n\n.jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip {\n  visibility: visible;\n}\n\n.jp-Notebook-ExecutionIndicator span {\n  font-size: var(--jp-ui-font-size1);\n  font-family: var(--jp-ui-font-family);\n  color: var(--jp-ui-font-color1);\n  line-height: 24px;\n  display: block;\n}\n\n.jp-Notebook-ExecutionIndicator-progress-bar {\n  display: flex;\n  justify-content: center;\n  height: 100%;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n/*\n * Execution indicator\n */\n.jp-tocItem-content::after {\n  content: '';\n\n  /* Must be identical to form a circle */\n  width: 12px;\n  height: 12px;\n  background: none;\n  border: none;\n  position: absolute;\n  right: 0;\n}\n\n.jp-tocItem-content[data-running='0']::after {\n  border-radius: 50%;\n  border: var(--jp-border-width) solid var(--jp-inverse-layout-color3);\n  background: none;\n}\n\n.jp-tocItem-content[data-running='1']::after {\n  border-radius: 50%;\n  border: var(--jp-border-width) solid var(--jp-inverse-layout-color3);\n  background-color: var(--jp-inverse-layout-color3);\n}\n\n.jp-tocItem-content[data-running='0'],\n.jp-tocItem-content[data-running='1'] {\n  margin-right: 12px;\n}\n\n/*\n * Copyright (c) Jupyter Development Team.\n * Distributed under the terms of the Modified BSD License.\n */\n\n.jp-Notebook-footer {\n  height: 27px;\n  margin-left: calc(\n    var(--jp-cell-prompt-width) + var(--jp-cell-collapser-width) +\n      var(--jp-cell-padding)\n  );\n  width: calc(\n    100% -\n      (\n        var(--jp-cell-prompt-width) + var(--jp-cell-collapser-width) +\n          var(--jp-cell-padding) + var(--jp-cell-padding)\n      )\n  );\n  border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);\n  color: var(--jp-ui-font-color3);\n  margin-top: 6px;\n  background: none;\n  cursor: pointer;\n}\n\n.jp-Notebook-footer:focus {\n  border-color: var(--jp-cell-editor-active-border-color);\n}\n\n/* For devices that support hovering, hide footer until hover */\n@media (hover: hover) {\n  .jp-Notebook-footer {\n    opacity: 0;\n  }\n\n  .jp-Notebook-footer:focus,\n  .jp-Notebook-footer:hover {\n    opacity: 1;\n  }\n}\n\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| Imports\n|----------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------\n| CSS variables\n|----------------------------------------------------------------------------*/\n\n:root {\n  --jp-side-by-side-output-size: 1fr;\n  --jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size);\n  --jp-private-notebook-dragImage-width: 304px;\n  --jp-private-notebook-dragImage-height: 36px;\n  --jp-private-notebook-selected-color: var(--md-blue-400);\n  --jp-private-notebook-active-color: var(--md-green-400);\n}\n\n/*-----------------------------------------------------------------------------\n| Notebook\n|----------------------------------------------------------------------------*/\n\n/* stylelint-disable selector-max-class */\n\n.jp-NotebookPanel {\n  display: block;\n  height: 100%;\n}\n\n.jp-NotebookPanel.jp-Document {\n  min-width: 240px;\n  min-height: 120px;\n}\n\n.jp-Notebook {\n  padding: var(--jp-notebook-padding);\n  outline: none;\n  overflow: auto;\n  background: var(--jp-layout-color0);\n}\n\n.jp-Notebook.jp-mod-scrollPastEnd::after {\n  display: block;\n  content: '';\n  min-height: var(--jp-notebook-scroll-padding);\n}\n\n.jp-MainAreaWidget-ContainStrict .jp-Notebook * {\n  contain: strict;\n}\n\n.jp-Notebook .jp-Cell {\n  overflow: visible;\n}\n\n.jp-Notebook .jp-Cell .jp-InputPrompt {\n  cursor: move;\n}\n\n/*-----------------------------------------------------------------------------\n| Notebook state related styling\n|\n| The notebook and cells each have states, here are the possibilities:\n|\n| - Notebook\n|   - Command\n|   - Edit\n| - Cell\n|   - None\n|   - Active (only one can be active)\n|   - Selected (the cells actions are applied to)\n|   - Multiselected (when multiple selected, the cursor)\n|   - No outputs\n|----------------------------------------------------------------------------*/\n\n/* Command or edit modes */\n\n.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt {\n  opacity: var(--jp-cell-prompt-not-active-opacity);\n  color: var(--jp-cell-prompt-not-active-font-color);\n}\n\n.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt {\n  opacity: var(--jp-cell-prompt-not-active-opacity);\n  color: var(--jp-cell-prompt-not-active-font-color);\n}\n\n/* cell is active */\n.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser {\n  background: var(--jp-brand-color1);\n}\n\n/* cell is dirty */\n.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt {\n  color: var(--jp-warn-color1);\n}\n\n.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt::before {\n  color: var(--jp-warn-color1);\n  content: '•';\n}\n\n.jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser {\n  background: var(--jp-warn-color1);\n}\n\n/* collapser is hovered */\n.jp-Notebook .jp-Cell .jp-Collapser:hover {\n  box-shadow: var(--jp-elevation-z2);\n  background: var(--jp-brand-color1);\n  opacity: var(--jp-cell-collapser-not-active-hover-opacity);\n}\n\n/* cell is active and collapser is hovered */\n.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover {\n  background: var(--jp-brand-color0);\n  opacity: 1;\n}\n\n/* Command mode */\n\n.jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected {\n  background: var(--jp-notebook-multiselected-color);\n}\n\n.jp-Notebook.jp-mod-commandMode\n  .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected) {\n  background: transparent;\n}\n\n/* Edit mode */\n\n.jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor {\n  border: var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);\n  box-shadow: var(--jp-input-box-shadow);\n  background-color: var(--jp-cell-editor-active-background);\n}\n\n/*-----------------------------------------------------------------------------\n| Notebook drag and drop\n|----------------------------------------------------------------------------*/\n\n.jp-Notebook-cell.jp-mod-dropSource {\n  opacity: 0.5;\n}\n\n.jp-Notebook-cell.jp-mod-dropTarget,\n.jp-Notebook.jp-mod-commandMode\n  .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget {\n  border-top-color: var(--jp-private-notebook-selected-color);\n  border-top-style: solid;\n  border-top-width: 2px;\n}\n\n.jp-dragImage {\n  display: block;\n  flex-direction: row;\n  width: var(--jp-private-notebook-dragImage-width);\n  height: var(--jp-private-notebook-dragImage-height);\n  border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);\n  background: var(--jp-cell-editor-background);\n  overflow: visible;\n}\n\n.jp-dragImage-singlePrompt {\n  box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);\n}\n\n.jp-dragImage .jp-dragImage-content {\n  flex: 1 1 auto;\n  z-index: 2;\n  font-size: var(--jp-code-font-size);\n  font-family: var(--jp-code-font-family);\n  line-height: var(--jp-code-line-height);\n  padding: var(--jp-code-padding);\n  border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);\n  background: var(--jp-cell-editor-background-color);\n  color: var(--jp-content-font-color3);\n  text-align: left;\n  margin: 4px 4px 4px 0;\n}\n\n.jp-dragImage .jp-dragImage-prompt {\n  flex: 0 0 auto;\n  min-width: 36px;\n  color: var(--jp-cell-inprompt-font-color);\n  padding: var(--jp-code-padding);\n  padding-left: 12px;\n  font-family: var(--jp-cell-prompt-font-family);\n  letter-spacing: var(--jp-cell-prompt-letter-spacing);\n  line-height: 1.9;\n  font-size: var(--jp-code-font-size);\n  border: var(--jp-border-width) solid transparent;\n}\n\n.jp-dragImage-multipleBack {\n  z-index: -1;\n  position: absolute;\n  height: 32px;\n  width: 300px;\n  top: 8px;\n  left: 8px;\n  background: var(--jp-layout-color2);\n  border: var(--jp-border-width) solid var(--jp-input-border-color);\n  box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);\n}\n\n/*-----------------------------------------------------------------------------\n| Cell toolbar\n|----------------------------------------------------------------------------*/\n\n.jp-NotebookTools {\n  display: block;\n  min-width: var(--jp-sidebar-min-width);\n  color: var(--jp-ui-font-color1);\n  background: var(--jp-layout-color1);\n\n  /* This is needed so that all font sizing of children done in ems is\n    * relative to this base size */\n  font-size: var(--jp-ui-font-size1);\n  overflow: auto;\n}\n\n.jp-ActiveCellTool {\n  padding: 12px 0;\n  display: flex;\n}\n\n.jp-ActiveCellTool-Content {\n  flex: 1 1 auto;\n}\n\n.jp-ActiveCellTool .jp-ActiveCellTool-CellContent {\n  background: var(--jp-cell-editor-background);\n  border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);\n  border-radius: 0;\n  min-height: 29px;\n}\n\n.jp-ActiveCellTool .jp-InputPrompt {\n  min-width: calc(var(--jp-cell-prompt-width) * 0.75);\n}\n\n.jp-ActiveCellTool-CellContent > pre {\n  padding: 5px 4px;\n  margin: 0;\n  white-space: normal;\n}\n\n.jp-MetadataEditorTool {\n  flex-direction: column;\n  padding: 12px 0;\n}\n\n.jp-RankedPanel > :not(:first-child) {\n  margin-top: 12px;\n}\n\n.jp-KeySelector select.jp-mod-styled {\n  font-size: var(--jp-ui-font-size1);\n  color: var(--jp-ui-font-color0);\n  border: var(--jp-border-width) solid var(--jp-border-color1);\n}\n\n.jp-KeySelector label,\n.jp-MetadataEditorTool label,\n.jp-NumberSetter label {\n  line-height: 1.4;\n}\n\n.jp-NotebookTools .jp-select-wrapper {\n  margin-top: 4px;\n  margin-bottom: 0;\n}\n\n.jp-NumberSetter input {\n  width: 100%;\n  margin-top: 4px;\n}\n\n.jp-NotebookTools .jp-Collapse {\n  margin-top: 16px;\n}\n\n/*-----------------------------------------------------------------------------\n| Presentation Mode (.jp-mod-presentationMode)\n|----------------------------------------------------------------------------*/\n\n.jp-mod-presentationMode .jp-Notebook {\n  --jp-content-font-size1: var(--jp-content-presentation-font-size1);\n  --jp-code-font-size: var(--jp-code-presentation-font-size);\n}\n\n.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,\n.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt {\n  flex: 0 0 110px;\n}\n\n/*-----------------------------------------------------------------------------\n| Side-by-side Mode (.jp-mod-sideBySide)\n|----------------------------------------------------------------------------*/\n.jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell {\n  margin-top: 3em;\n  margin-bottom: 3em;\n  margin-left: 5%;\n  margin-right: 5%;\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell {\n  display: grid;\n  grid-template-columns: minmax(0, 1fr) min-content minmax(\n      0,\n      var(--jp-side-by-side-output-size)\n    );\n  grid-template-rows: auto minmax(0, 1fr) auto;\n  grid-template-areas:\n    'header header header'\n    'input handle output'\n    'footer footer footer';\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell {\n  grid-template-columns: minmax(0, 1fr) min-content minmax(\n      0,\n      var(--jp-side-by-side-resized-cell)\n    );\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader {\n  grid-area: header;\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper {\n  grid-area: input;\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper {\n  /* overwrite the default margin (no vertical separation needed in side by side move */\n  margin-top: 0;\n  grid-area: output;\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter {\n  grid-area: footer;\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle {\n  grid-area: handle;\n  user-select: none;\n  display: block;\n  height: 100%;\n  cursor: ew-resize;\n  padding: 0 var(--jp-cell-padding);\n}\n\n.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle::after {\n  content: '';\n  display: block;\n  background: var(--jp-border-color2);\n  height: 100%;\n  width: 5px;\n}\n\n.jp-mod-sideBySide.jp-Notebook\n  .jp-CodeCell.jp-mod-resizedCell\n  .jp-CellResizeHandle::after {\n  background: var(--jp-border-color0);\n}\n\n.jp-CellResizeHandle {\n  display: none;\n}\n\n/*-----------------------------------------------------------------------------\n| Placeholder\n|----------------------------------------------------------------------------*/\n\n.jp-Cell-Placeholder {\n  padding-left: 55px;\n}\n\n.jp-Cell-Placeholder-wrapper {\n  background: #fff;\n  border: 1px solid;\n  border-color: #e5e6e9 #dfe0e4 #d0d1d5;\n  border-radius: 4px;\n  -webkit-border-radius: 4px;\n  margin: 10px 15px;\n}\n\n.jp-Cell-Placeholder-wrapper-inner {\n  padding: 15px;\n  position: relative;\n}\n\n.jp-Cell-Placeholder-wrapper-body {\n  background-repeat: repeat;\n  background-size: 50% auto;\n}\n\n.jp-Cell-Placeholder-wrapper-body div {\n  background: #f6f7f8;\n  background-image: -webkit-linear-gradient(\n    left,\n    #f6f7f8 0%,\n    #edeef1 20%,\n    #f6f7f8 40%,\n    #f6f7f8 100%\n  );\n  background-repeat: no-repeat;\n  background-size: 800px 104px;\n  height: 104px;\n  position: absolute;\n  right: 15px;\n  left: 15px;\n  top: 15px;\n}\n\ndiv.jp-Cell-Placeholder-h1 {\n  top: 20px;\n  height: 20px;\n  left: 15px;\n  width: 150px;\n}\n\ndiv.jp-Cell-Placeholder-h2 {\n  left: 15px;\n  top: 50px;\n  height: 10px;\n  width: 100px;\n}\n\ndiv.jp-Cell-Placeholder-content-1,\ndiv.jp-Cell-Placeholder-content-2,\ndiv.jp-Cell-Placeholder-content-3 {\n  left: 15px;\n  right: 15px;\n  height: 10px;\n}\n\ndiv.jp-Cell-Placeholder-content-1 {\n  top: 100px;\n}\n\ndiv.jp-Cell-Placeholder-content-2 {\n  top: 120px;\n}\n\ndiv.jp-Cell-Placeholder-content-3 {\n  top: 140px;\n}\n\n</style>\n<style type=\"text/css\">\n/*-----------------------------------------------------------------------------\n| Copyright (c) Jupyter Development Team.\n| Distributed under the terms of the Modified BSD License.\n|----------------------------------------------------------------------------*/\n\n/*\nThe following CSS variables define the main, public API for styling JupyterLab.\nThese variables should be used by all plugins wherever possible. In other\nwords, plugins should not define custom colors, sizes, etc unless absolutely\nnecessary. This enables users to change the visual theme of JupyterLab\nby changing these variables.\n\nMany variables appear in an ordered sequence (0,1,2,3). These sequences\nare designed to work well together, so for example, `--jp-border-color1` should\nbe used with `--jp-layout-color1`. The numbers have the following meanings:\n\n* 0: super-primary, reserved for special emphasis\n* 1: primary, most important under normal situations\n* 2: secondary, next most important under normal situations\n* 3: tertiary, next most important under normal situations\n\nThroughout JupyterLab, we are mostly following principles from Google's\nMaterial Design when selecting colors. We are not, however, following\nall of MD as it is not optimized for dense, information rich UIs.\n*/\n\n:root {\n  /* Elevation\n   *\n   * We style box-shadows using Material Design's idea of elevation. These particular numbers are taken from here:\n   *\n   * https://github.com/material-components/material-components-web\n   * https://material-components-web.appspot.com/elevation.html\n   */\n\n  --jp-shadow-base-lightness: 0;\n  --jp-shadow-umbra-color: rgba(\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    0.2\n  );\n  --jp-shadow-penumbra-color: rgba(\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    0.14\n  );\n  --jp-shadow-ambient-color: rgba(\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    var(--jp-shadow-base-lightness),\n    0.12\n  );\n  --jp-elevation-z0: none;\n  --jp-elevation-z1: 0 2px 1px -1px var(--jp-shadow-umbra-color),\n    0 1px 1px 0 var(--jp-shadow-penumbra-color),\n    0 1px 3px 0 var(--jp-shadow-ambient-color);\n  --jp-elevation-z2: 0 3px 1px -2px var(--jp-shadow-umbra-color),\n    0 2px 2px 0 var(--jp-shadow-penumbra-color),\n    0 1px 5px 0 var(--jp-shadow-ambient-color);\n  --jp-elevation-z4: 0 2px 4px -1px var(--jp-shadow-umbra-color),\n    0 4px 5px 0 var(--jp-shadow-penumbra-color),\n    0 1px 10px 0 var(--jp-shadow-ambient-color);\n  --jp-elevation-z6: 0 3px 5px -1px var(--jp-shadow-umbra-color),\n    0 6px 10px 0 var(--jp-shadow-penumbra-color),\n    0 1px 18px 0 var(--jp-shadow-ambient-color);\n  --jp-elevation-z8: 0 5px 5px -3px var(--jp-shadow-umbra-color),\n    0 8px 10px 1px var(--jp-shadow-penumbra-color),\n    0 3px 14px 2px var(--jp-shadow-ambient-color);\n  --jp-elevation-z12: 0 7px 8px -4px var(--jp-shadow-umbra-color),\n    0 12px 17px 2px var(--jp-shadow-penumbra-color),\n    0 5px 22px 4px var(--jp-shadow-ambient-color);\n  --jp-elevation-z16: 0 8px 10px -5px var(--jp-shadow-umbra-color),\n    0 16px 24px 2px var(--jp-shadow-penumbra-color),\n    0 6px 30px 5px var(--jp-shadow-ambient-color);\n  --jp-elevation-z20: 0 10px 13px -6px var(--jp-shadow-umbra-color),\n    0 20px 31px 3px var(--jp-shadow-penumbra-color),\n    0 8px 38px 7px var(--jp-shadow-ambient-color);\n  --jp-elevation-z24: 0 11px 15px -7px var(--jp-shadow-umbra-color),\n    0 24px 38px 3px var(--jp-shadow-penumbra-color),\n    0 9px 46px 8px var(--jp-shadow-ambient-color);\n\n  /* Borders\n   *\n   * The following variables, specify the visual styling of borders in JupyterLab.\n   */\n\n  --jp-border-width: 1px;\n  --jp-border-color0: var(--md-grey-400);\n  --jp-border-color1: var(--md-grey-400);\n  --jp-border-color2: var(--md-grey-300);\n  --jp-border-color3: var(--md-grey-200);\n  --jp-inverse-border-color: var(--md-grey-600);\n  --jp-border-radius: 2px;\n\n  /* UI Fonts\n   *\n   * The UI font CSS variables are used for the typography all of the JupyterLab\n   * user interface elements that are not directly user generated content.\n   *\n   * The font sizing here is done assuming that the body font size of --jp-ui-font-size1\n   * is applied to a parent element. When children elements, such as headings, are sized\n   * in em all things will be computed relative to that body size.\n   */\n\n  --jp-ui-font-scale-factor: 1.2;\n  --jp-ui-font-size0: 0.83333em;\n  --jp-ui-font-size1: 13px; /* Base font size */\n  --jp-ui-font-size2: 1.2em;\n  --jp-ui-font-size3: 1.44em;\n  --jp-ui-font-family: system-ui, -apple-system, blinkmacsystemfont, 'Segoe UI',\n    helvetica, arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',\n    'Segoe UI Symbol';\n\n  /*\n   * Use these font colors against the corresponding main layout colors.\n   * In a light theme, these go from dark to light.\n   */\n\n  /* Defaults use Material Design specification */\n  --jp-ui-font-color0: rgba(0, 0, 0, 1);\n  --jp-ui-font-color1: rgba(0, 0, 0, 0.87);\n  --jp-ui-font-color2: rgba(0, 0, 0, 0.54);\n  --jp-ui-font-color3: rgba(0, 0, 0, 0.38);\n\n  /*\n   * Use these against the brand/accent/warn/error colors.\n   * These will typically go from light to darker, in both a dark and light theme.\n   */\n\n  --jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);\n  --jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);\n  --jp-ui-inverse-font-color2: rgba(255, 255, 255, 0.7);\n  --jp-ui-inverse-font-color3: rgba(255, 255, 255, 0.5);\n\n  /* Content Fonts\n   *\n   * Content font variables are used for typography of user generated content.\n   *\n   * The font sizing here is done assuming that the body font size of --jp-content-font-size1\n   * is applied to a parent element. When children elements, such as headings, are sized\n   * in em all things will be computed relative to that body size.\n   */\n\n  --jp-content-line-height: 1.6;\n  --jp-content-font-scale-factor: 1.2;\n  --jp-content-font-size0: 0.83333em;\n  --jp-content-font-size1: 14px; /* Base font size */\n  --jp-content-font-size2: 1.2em;\n  --jp-content-font-size3: 1.44em;\n  --jp-content-font-size4: 1.728em;\n  --jp-content-font-size5: 2.0736em;\n\n  /* This gives a magnification of about 125% in presentation mode over normal. */\n  --jp-content-presentation-font-size1: 17px;\n  --jp-content-heading-line-height: 1;\n  --jp-content-heading-margin-top: 1.2em;\n  --jp-content-heading-margin-bottom: 0.8em;\n  --jp-content-heading-font-weight: 500;\n\n  /* Defaults use Material Design specification */\n  --jp-content-font-color0: rgba(0, 0, 0, 1);\n  --jp-content-font-color1: rgba(0, 0, 0, 0.87);\n  --jp-content-font-color2: rgba(0, 0, 0, 0.54);\n  --jp-content-font-color3: rgba(0, 0, 0, 0.38);\n  --jp-content-link-color: var(--md-blue-900);\n  --jp-content-font-family: system-ui, -apple-system, blinkmacsystemfont,\n    'Segoe UI', helvetica, arial, sans-serif, 'Apple Color Emoji',\n    'Segoe UI Emoji', 'Segoe UI Symbol';\n\n  /*\n   * Code Fonts\n   *\n   * Code font variables are used for typography of code and other monospaces content.\n   */\n\n  --jp-code-font-size: 13px;\n  --jp-code-line-height: 1.3077; /* 17px for 13px base */\n  --jp-code-padding: 5px; /* 5px for 13px base, codemirror highlighting needs integer px value */\n  --jp-code-font-family-default: menlo, consolas, 'DejaVu Sans Mono', monospace;\n  --jp-code-font-family: var(--jp-code-font-family-default);\n\n  /* This gives a magnification of about 125% in presentation mode over normal. */\n  --jp-code-presentation-font-size: 16px;\n\n  /* may need to tweak cursor width if you change font size */\n  --jp-code-cursor-width0: 1.4px;\n  --jp-code-cursor-width1: 2px;\n  --jp-code-cursor-width2: 4px;\n\n  /* Layout\n   *\n   * The following are the main layout colors use in JupyterLab. In a light\n   * theme these would go from light to dark.\n   */\n\n  --jp-layout-color0: white;\n  --jp-layout-color1: white;\n  --jp-layout-color2: var(--md-grey-200);\n  --jp-layout-color3: var(--md-grey-400);\n  --jp-layout-color4: var(--md-grey-600);\n\n  /* Inverse Layout\n   *\n   * The following are the inverse layout colors use in JupyterLab. In a light\n   * theme these would go from dark to light.\n   */\n\n  --jp-inverse-layout-color0: #111;\n  --jp-inverse-layout-color1: var(--md-grey-900);\n  --jp-inverse-layout-color2: var(--md-grey-800);\n  --jp-inverse-layout-color3: var(--md-grey-700);\n  --jp-inverse-layout-color4: var(--md-grey-600);\n\n  /* Brand/accent */\n\n  --jp-brand-color0: var(--md-blue-900);\n  --jp-brand-color1: var(--md-blue-700);\n  --jp-brand-color2: var(--md-blue-300);\n  --jp-brand-color3: var(--md-blue-100);\n  --jp-brand-color4: var(--md-blue-50);\n  --jp-accent-color0: var(--md-green-900);\n  --jp-accent-color1: var(--md-green-700);\n  --jp-accent-color2: var(--md-green-300);\n  --jp-accent-color3: var(--md-green-100);\n\n  /* State colors (warn, error, success, info) */\n\n  --jp-warn-color0: var(--md-orange-900);\n  --jp-warn-color1: var(--md-orange-700);\n  --jp-warn-color2: var(--md-orange-300);\n  --jp-warn-color3: var(--md-orange-100);\n  --jp-error-color0: var(--md-red-900);\n  --jp-error-color1: var(--md-red-700);\n  --jp-error-color2: var(--md-red-300);\n  --jp-error-color3: var(--md-red-100);\n  --jp-success-color0: var(--md-green-900);\n  --jp-success-color1: var(--md-green-700);\n  --jp-success-color2: var(--md-green-300);\n  --jp-success-color3: var(--md-green-100);\n  --jp-info-color0: var(--md-cyan-900);\n  --jp-info-color1: var(--md-cyan-700);\n  --jp-info-color2: var(--md-cyan-300);\n  --jp-info-color3: var(--md-cyan-100);\n\n  /* Cell specific styles */\n\n  --jp-cell-padding: 5px;\n  --jp-cell-collapser-width: 8px;\n  --jp-cell-collapser-min-height: 20px;\n  --jp-cell-collapser-not-active-hover-opacity: 0.6;\n  --jp-cell-editor-background: var(--md-grey-100);\n  --jp-cell-editor-border-color: var(--md-grey-300);\n  --jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);\n  --jp-cell-editor-active-background: var(--jp-layout-color0);\n  --jp-cell-editor-active-border-color: var(--jp-brand-color1);\n  --jp-cell-prompt-width: 64px;\n  --jp-cell-prompt-font-family: var(--jp-code-font-family-default);\n  --jp-cell-prompt-letter-spacing: 0;\n  --jp-cell-prompt-opacity: 1;\n  --jp-cell-prompt-not-active-opacity: 0.5;\n  --jp-cell-prompt-not-active-font-color: var(--md-grey-700);\n\n  /* A custom blend of MD grey and blue 600\n   * See https://meyerweb.com/eric/tools/color-blend/#546E7A:1E88E5:5:hex */\n  --jp-cell-inprompt-font-color: #307fc1;\n\n  /* A custom blend of MD grey and orange 600\n   * https://meyerweb.com/eric/tools/color-blend/#546E7A:F4511E:5:hex */\n  --jp-cell-outprompt-font-color: #bf5b3d;\n\n  /* Notebook specific styles */\n\n  --jp-notebook-padding: 10px;\n  --jp-notebook-select-background: var(--jp-layout-color1);\n  --jp-notebook-multiselected-color: var(--md-blue-50);\n\n  /* The scroll padding is calculated to fill enough space at the bottom of the\n  notebook to show one single-line cell (with appropriate padding) at the top\n  when the notebook is scrolled all the way to the bottom. We also subtract one\n  pixel so that no scrollbar appears if we have just one single-line cell in the\n  notebook. This padding is to enable a 'scroll past end' feature in a notebook.\n  */\n  --jp-notebook-scroll-padding: calc(\n    100% - var(--jp-code-font-size) * var(--jp-code-line-height) -\n      var(--jp-code-padding) - var(--jp-cell-padding) - 1px\n  );\n\n  /* Rendermime styles */\n\n  --jp-rendermime-error-background: #fdd;\n  --jp-rendermime-table-row-background: var(--md-grey-100);\n  --jp-rendermime-table-row-hover-background: var(--md-light-blue-50);\n\n  /* Dialog specific styles */\n\n  --jp-dialog-background: rgba(0, 0, 0, 0.25);\n\n  /* Console specific styles */\n\n  --jp-console-padding: 10px;\n\n  /* Toolbar specific styles */\n\n  --jp-toolbar-border-color: var(--jp-border-color1);\n  --jp-toolbar-micro-height: 8px;\n  --jp-toolbar-background: var(--jp-layout-color1);\n  --jp-toolbar-box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.24);\n  --jp-toolbar-header-margin: 4px 4px 0 4px;\n  --jp-toolbar-active-background: var(--md-grey-300);\n\n  /* Statusbar specific styles */\n\n  --jp-statusbar-height: 24px;\n\n  /* Input field styles */\n\n  --jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);\n  --jp-input-active-background: var(--jp-layout-color1);\n  --jp-input-hover-background: var(--jp-layout-color1);\n  --jp-input-background: var(--md-grey-100);\n  --jp-input-border-color: var(--jp-inverse-border-color);\n  --jp-input-active-border-color: var(--jp-brand-color1);\n  --jp-input-active-box-shadow-color: rgba(19, 124, 189, 0.3);\n\n  /* General editor styles */\n\n  --jp-editor-selected-background: #d9d9d9;\n  --jp-editor-selected-focused-background: #d7d4f0;\n  --jp-editor-cursor-color: var(--jp-ui-font-color0);\n\n  /* Code mirror specific styles */\n\n  --jp-mirror-editor-keyword-color: #008000;\n  --jp-mirror-editor-atom-color: #88f;\n  --jp-mirror-editor-number-color: #080;\n  --jp-mirror-editor-def-color: #00f;\n  --jp-mirror-editor-variable-color: var(--md-grey-900);\n  --jp-mirror-editor-variable-2-color: rgb(0, 54, 109);\n  --jp-mirror-editor-variable-3-color: #085;\n  --jp-mirror-editor-punctuation-color: #05a;\n  --jp-mirror-editor-property-color: #05a;\n  --jp-mirror-editor-operator-color: #a2f;\n  --jp-mirror-editor-comment-color: #408080;\n  --jp-mirror-editor-string-color: #ba2121;\n  --jp-mirror-editor-string-2-color: #708;\n  --jp-mirror-editor-meta-color: #a2f;\n  --jp-mirror-editor-qualifier-color: #555;\n  --jp-mirror-editor-builtin-color: #008000;\n  --jp-mirror-editor-bracket-color: #997;\n  --jp-mirror-editor-tag-color: #170;\n  --jp-mirror-editor-attribute-color: #00c;\n  --jp-mirror-editor-header-color: blue;\n  --jp-mirror-editor-quote-color: #090;\n  --jp-mirror-editor-link-color: #00c;\n  --jp-mirror-editor-error-color: #f00;\n  --jp-mirror-editor-hr-color: #999;\n\n  /*\n    RTC user specific colors.\n    These colors are used for the cursor, username in the editor,\n    and the icon of the user.\n  */\n\n  --jp-collaborator-color1: #ffad8e;\n  --jp-collaborator-color2: #dac83d;\n  --jp-collaborator-color3: #72dd76;\n  --jp-collaborator-color4: #00e4d0;\n  --jp-collaborator-color5: #45d4ff;\n  --jp-collaborator-color6: #e2b1ff;\n  --jp-collaborator-color7: #ff9de6;\n\n  /* Vega extension styles */\n\n  --jp-vega-background: white;\n\n  /* Sidebar-related styles */\n\n  --jp-sidebar-min-width: 250px;\n\n  /* Search-related styles */\n\n  --jp-search-toggle-off-opacity: 0.5;\n  --jp-search-toggle-hover-opacity: 0.8;\n  --jp-search-toggle-on-opacity: 1;\n  --jp-search-selected-match-background-color: rgb(245, 200, 0);\n  --jp-search-selected-match-color: black;\n  --jp-search-unselected-match-background-color: var(\n    --jp-inverse-layout-color0\n  );\n  --jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);\n\n  /* Icon colors that work well with light or dark backgrounds */\n  --jp-icon-contrast-color0: var(--md-purple-600);\n  --jp-icon-contrast-color1: var(--md-green-600);\n  --jp-icon-contrast-color2: var(--md-pink-600);\n  --jp-icon-contrast-color3: var(--md-blue-600);\n\n  /* Button colors */\n  --jp-accept-color-normal: var(--md-blue-700);\n  --jp-accept-color-hover: var(--md-blue-800);\n  --jp-accept-color-active: var(--md-blue-900);\n  --jp-warn-color-normal: var(--md-red-700);\n  --jp-warn-color-hover: var(--md-red-800);\n  --jp-warn-color-active: var(--md-red-900);\n  --jp-reject-color-normal: var(--md-grey-600);\n  --jp-reject-color-hover: var(--md-grey-700);\n  --jp-reject-color-active: var(--md-grey-800);\n\n  /* File or activity icons and switch semantic variables */\n  --jp-jupyter-icon-color: #f37626;\n  --jp-notebook-icon-color: #f37626;\n  --jp-json-icon-color: var(--md-orange-700);\n  --jp-console-icon-background-color: var(--md-blue-700);\n  --jp-console-icon-color: white;\n  --jp-terminal-icon-background-color: var(--md-grey-800);\n  --jp-terminal-icon-color: var(--md-grey-200);\n  --jp-text-editor-icon-color: var(--md-grey-700);\n  --jp-inspector-icon-color: var(--md-grey-700);\n  --jp-switch-color: var(--md-grey-400);\n  --jp-switch-true-position-color: var(--md-orange-900);\n}\n</style>\n<style type=\"text/css\">\n/* Force rendering true colors when outputing to pdf */\n* {\n  -webkit-print-color-adjust: exact;\n}\n\n/* Misc */\na.anchor-link {\n  display: none;\n}\n\n/* Input area styling */\n.jp-InputArea {\n  overflow: hidden;\n}\n\n.jp-InputArea-editor {\n  overflow: hidden;\n}\n\n.cm-editor.cm-s-jupyter .highlight pre {\n/* weird, but --jp-code-padding defined to be 5px but 4px horizontal padding is hardcoded for pre.cm-line */\n  padding: var(--jp-code-padding) 4px;\n  margin: 0;\n\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n  color: inherit;\n\n}\n\n.jp-OutputArea-output pre {\n  line-height: inherit;\n  font-family: inherit;\n}\n\n.jp-RenderedText pre {\n  color: var(--jp-content-font-color1);\n  font-size: var(--jp-code-font-size);\n}\n\n/* Hiding the collapser by default */\n.jp-Collapser {\n  display: none;\n}\n\n@page {\n    margin: 0.5in; /* Margin for each printed piece of paper */\n}\n\n@media print {\n  .jp-Cell-inputWrapper,\n  .jp-Cell-outputWrapper {\n    display: block;\n  }\n}\n</style>\n<!-- Load mathjax -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS_CHTML-full,Safe\"> </script>\n<!-- MathJax configuration -->\n<script type=\"text/x-mathjax-config\">\n    init_mathjax = function() {\n        if (window.MathJax) {\n        // MathJax loaded\n            MathJax.Hub.Config({\n                TeX: {\n                    equationNumbers: {\n                    autoNumber: \"AMS\",\n                    useLabelIds: true\n                    }\n                },\n                tex2jax: {\n                    inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n                    displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ],\n                    processEscapes: true,\n                    processEnvironments: true\n                },\n                displayAlign: 'center',\n                messageStyle: 'none',\n                CommonHTML: {\n                    linebreaks: {\n                    automatic: true\n                    }\n                }\n            });\n\n            MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n        }\n    }\n    init_mathjax();\n    </script>\n<!-- End of mathjax configuration --><script type=\"module\">\n  document.addEventListener(\"DOMContentLoaded\", async () => {\n    const diagrams = document.querySelectorAll(\".jp-Mermaid > pre.mermaid\");\n    // do not load mermaidjs if not needed\n    if (!diagrams.length) {\n      return;\n    }\n    const mermaid = (await import(\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs\")).default;\n    const parser = new DOMParser();\n\n    mermaid.initialize({\n      maxTextSize: 100000,\n      maxEdges: 100000,\n      startOnLoad: false,\n      fontFamily: window\n        .getComputedStyle(document.body)\n        .getPropertyValue(\"--jp-ui-font-family\"),\n      theme: document.querySelector(\"body[data-jp-theme-light='true']\")\n        ? \"default\"\n        : \"dark\",\n    });\n\n    let _nextMermaidId = 0;\n\n    function makeMermaidImage(svg) {\n      const img = document.createElement(\"img\");\n      const doc = parser.parseFromString(svg, \"image/svg+xml\");\n      const svgEl = doc.querySelector(\"svg\");\n      const { maxWidth } = svgEl?.style || {};\n      const firstTitle = doc.querySelector(\"title\");\n      const firstDesc = doc.querySelector(\"desc\");\n\n      img.setAttribute(\"src\", `data:image/svg+xml,${encodeURIComponent(svg)}`);\n      if (maxWidth) {\n        img.width = parseInt(maxWidth);\n      }\n      if (firstTitle) {\n        img.setAttribute(\"alt\", firstTitle.textContent);\n      }\n      if (firstDesc) {\n        const caption = document.createElement(\"figcaption\");\n        caption.className = \"sr-only\";\n        caption.textContent = firstDesc.textContent;\n        return [img, caption];\n      }\n      return [img];\n    }\n\n    async function makeMermaidError(text) {\n      let errorMessage = \"\";\n      try {\n        await mermaid.parse(text);\n      } catch (err) {\n        errorMessage = `${err}`;\n      }\n\n      const result = document.createElement(\"details\");\n      result.className = 'jp-RenderedMermaid-Details';\n      const summary = document.createElement(\"summary\");\n      summary.className = 'jp-RenderedMermaid-Summary';\n      const pre = document.createElement(\"pre\");\n      const code = document.createElement(\"code\");\n      code.innerText = text;\n      pre.appendChild(code);\n      summary.appendChild(pre);\n      result.appendChild(summary);\n\n      const warning = document.createElement(\"pre\");\n      warning.innerText = errorMessage;\n      result.appendChild(warning);\n      return [result];\n    }\n\n    async function renderOneMarmaid(src) {\n      const id = `jp-mermaid-${_nextMermaidId++}`;\n      const parent = src.parentNode;\n      let raw = src.textContent.trim();\n      const el = document.createElement(\"div\");\n      el.style.visibility = \"hidden\";\n      document.body.appendChild(el);\n      let results = null;\n      let output = null;\n      try {\n        let { svg } = await mermaid.render(id, raw, el);\n        svg = cleanMermaidSvg(svg);\n        results = makeMermaidImage(svg);\n        output = document.createElement(\"figure\");\n        results.map(output.appendChild, output);\n      } catch (err) {\n        parent.classList.add(\"jp-mod-warning\");\n        results = await makeMermaidError(raw);\n        output = results[0];\n      } finally {\n        el.remove();\n      }\n      parent.classList.add(\"jp-RenderedMermaid\");\n      parent.appendChild(output);\n    }\n\n\n    /**\n     * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML.\n     */\n    function cleanMermaidSvg(svg) {\n      return svg.replace(RE_VOID_ELEMENT, replaceVoidElement);\n    }\n\n\n    /**\n     * A regular expression for all void elements, which may include attributes and\n     * a slash.\n     *\n     * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element\n     *\n     * Of these, only `<br>` is generated by Mermaid in place of `\\n`,\n     * but _any_ \"malformed\" tag will break the SVG rendering entirely.\n     */\n    const RE_VOID_ELEMENT =\n      /<\\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\\s*([^>]*?)\\s*>/gi;\n\n    /**\n     * Ensure a void element is closed with a slash, preserving any attributes.\n     */\n    function replaceVoidElement(match, tag, rest) {\n      rest = rest.trim();\n      if (!rest.endsWith('/')) {\n        rest = `${rest} /`;\n      }\n      return `<${tag} ${rest}>`;\n    }\n\n    void Promise.all([...diagrams].map(renderOneMarmaid));\n  });\n</script>\n<style>\n  .jp-Mermaid:not(.jp-RenderedMermaid) {\n    display: none;\n  }\n\n  .jp-RenderedMermaid {\n    overflow: auto;\n    display: flex;\n  }\n\n  .jp-RenderedMermaid.jp-mod-warning {\n    width: auto;\n    padding: 0.5em;\n    margin-top: 0.5em;\n    border: var(--jp-border-width) solid var(--jp-warn-color2);\n    border-radius: var(--jp-border-radius);\n    color: var(--jp-ui-font-color1);\n    font-size: var(--jp-ui-font-size1);\n    white-space: pre-wrap;\n    word-wrap: break-word;\n  }\n\n  .jp-RenderedMermaid figure {\n    margin: 0;\n    overflow: auto;\n    max-width: 100%;\n  }\n\n  .jp-RenderedMermaid img {\n    max-width: 100%;\n  }\n\n  .jp-RenderedMermaid-Details > pre {\n    margin-top: 1em;\n  }\n\n  .jp-RenderedMermaid-Summary {\n    color: var(--jp-warn-color2);\n  }\n\n  .jp-RenderedMermaid:not(.jp-mod-warning) pre {\n    display: none;\n  }\n\n  .jp-RenderedMermaid-Summary > pre {\n    display: inline-block;\n    white-space: normal;\n  }\n</style>\n<!-- End of mermaid configuration --></head>\n<body class=\"jp-Notebook\" data-jp-theme-light=\"true\" data-jp-theme-name=\"JupyterLab Light\">\n<main>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1>Mocodo<span class=\"tocSkip\"></span></h1>\n<div class=\"toc\"><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Introduction-1\" href=\"#Introduction\"><span class=\"toc-item-num\">1  </span>Introduction</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Tracé-du-modèle-conceptuel-1.1\" href=\"#Tracé-du-modèle-conceptuel\"><span class=\"toc-item-num\">1.1  </span>Tracé du modèle conceptuel</a></span></li><li><span><a data-toc-modified-id=\"Opérations-de-conversion-1.2\" href=\"#Opérations-de-conversion\"><span class=\"toc-item-num\">1.2  </span>Opérations de conversion</a></span></li><li><span><a data-toc-modified-id=\"Opérations-de-réécriture-1.3\" href=\"#Opérations-de-réécriture\"><span class=\"toc-item-num\">1.3  </span>Opérations de réécriture</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Installation-et-lancement-du-programme-2\" href=\"#Installation-et-lancement-du-programme\"><span class=\"toc-item-num\">2  </span>Installation et lancement du programme</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Installation-minimale-2.1\" href=\"#Installation-minimale\"><span class=\"toc-item-num\">2.1  </span>Installation minimale</a></span></li><li><span><a data-toc-modified-id=\"Installation-complète-(recommandé)-2.2\" href=\"#Installation-complète-(recommandé)\"><span class=\"toc-item-num\">2.2  </span>Installation complète (recommandé)</a></span></li><li><span><a data-toc-modified-id=\"Utilisation-par-importation-2.3\" href=\"#Utilisation-par-importation\"><span class=\"toc-item-num\">2.3  </span>Utilisation par importation</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Syntaxe-de-description-d'un-MCD-3\" href=\"#Syntaxe-de-description-d'un-MCD\"><span class=\"toc-item-num\">3  </span>Syntaxe de description d'un MCD</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Notions-élémentaires-3.1\" href=\"#Notions-élémentaires\"><span class=\"toc-item-num\">3.1  </span>Notions élémentaires</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Entités,-associations,-attributs,-identifiants,-cardinalités-3.1.1\" href=\"#Entités,-associations,-attributs,-identifiants,-cardinalités\"><span class=\"toc-item-num\">3.1.1  </span>Entités, associations, attributs, identifiants, cardinalités</a></span></li><li><span><a data-toc-modified-id=\"Dépendances-fonctionnelles-entre-entités-3.1.2\" href=\"#Dépendances-fonctionnelles-entre-entités\"><span class=\"toc-item-num\">3.1.2  </span>Dépendances fonctionnelles entre entités</a></span></li><li><span><a data-toc-modified-id=\"Associations-réflexives-3.1.3\" href=\"#Associations-réflexives\"><span class=\"toc-item-num\">3.1.3  </span>Associations réflexives</a></span></li><li><span><a data-toc-modified-id=\"Identifiants-composites-3.1.4\" href=\"#Identifiants-composites\"><span class=\"toc-item-num\">3.1.4  </span>Identifiants composites</a></span></li><li><span><a data-toc-modified-id=\"Flèches-sur-les-pattes-3.1.5\" href=\"#Flèches-sur-les-pattes\"><span class=\"toc-item-num\">3.1.5  </span>Flèches sur les pattes</a></span></li><li><span><a data-toc-modified-id=\"Types-de-données-3.1.6\" href=\"#Types-de-données\"><span class=\"toc-item-num\">3.1.6  </span>Types de données</a></span></li><li><span><a data-toc-modified-id=\"Tracé-d'un-MCD :-principes-3.1.7\" href=\"#Tracé-d'un-MCD :-principes\"><span class=\"toc-item-num\">3.1.7  </span>Tracé d'un MCD : principes</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Extensions-du-modèle-3.2\" href=\"#Extensions-du-modèle\"><span class=\"toc-item-num\">3.2  </span>Extensions du modèle</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Entité-faible-(ou-identification-relative)-3.2.1\" href=\"#Entité-faible-(ou-identification-relative)\"><span class=\"toc-item-num\">3.2.1  </span>Entité faible (ou identification relative)</a></span></li><li><span><a data-toc-modified-id=\"Héritage-(généralisation-/-spécialisation)-3.2.2\" href=\"#Héritage-(généralisation-/-spécialisation)\"><span class=\"toc-item-num\">3.2.2  </span>Héritage (généralisation / spécialisation)</a></span></li><li><span><a data-toc-modified-id=\"Contrainte-inter-associations-3.2.3\" href=\"#Contrainte-inter-associations\"><span class=\"toc-item-num\">3.2.3  </span>Contrainte inter-associations</a></span></li><li><span><a data-toc-modified-id=\"Agrégat-(ou-pseudo-entité)-3.2.4\" href=\"#Agrégat-(ou-pseudo-entité)\"><span class=\"toc-item-num\">3.2.4  </span>Agrégat (ou pseudo-entité)</a></span></li><li><span><a data-toc-modified-id=\"CIF-à-unicité-complète-3.2.5\" href=\"#CIF-à-unicité-complète\"><span class=\"toc-item-num\">3.2.5  </span>CIF à unicité complète</a></span></li><li><span><a data-toc-modified-id=\"Identifiants-explicites-dans-les-associations-3.2.6\" href=\"#Identifiants-explicites-dans-les-associations\"><span class=\"toc-item-num\">3.2.6  </span>Identifiants explicites dans les associations</a></span></li></ul></li></ul></li><li><span><a data-toc-modified-id=\"Conversion-d'un-MCD-4\" href=\"#Conversion-d'un-MCD\"><span class=\"toc-item-num\">4  </span>Conversion d'un MCD</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Passage-au-relationnel-4.1\" href=\"#Passage-au-relationnel\"><span class=\"toc-item-num\">4.1  </span>Passage au relationnel</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Niveau-logique-4.1.1\" href=\"#Niveau-logique\"><span class=\"toc-item-num\">4.1.1  </span>Niveau logique</a></span></li><li><span><a data-toc-modified-id=\"Niveau-physique :-DDL-4.1.2\" href=\"#Niveau-physique :-DDL\"><span class=\"toc-item-num\">4.1.2  </span>Niveau physique : DDL</a></span></li><li><span><a data-toc-modified-id=\"Notes-sur-les-règles-de-passage-4.1.3\" href=\"#Notes-sur-les-règles-de-passage\"><span class=\"toc-item-num\">4.1.3  </span>Notes sur les règles de passage</a></span></li><li><span><a data-toc-modified-id=\"Ajustement-des-règles-de-passage-4.1.4\" href=\"#Ajustement-des-règles-de-passage\"><span class=\"toc-item-num\">4.1.4  </span>Ajustement des règles de passage</a></span></li><li><span><a data-toc-modified-id=\"Autres-sorties-relationnelles-4.1.5\" href=\"#Autres-sorties-relationnelles\"><span class=\"toc-item-num\">4.1.5  </span>Autres sorties relationnelles</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Autres-conversions-4.2\" href=\"#Autres-conversions\"><span class=\"toc-item-num\">4.2  </span>Autres conversions</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Diagramme-de-classes-UML-4.2.1\" href=\"#Diagramme-de-classes-UML\"><span class=\"toc-item-num\">4.2.1  </span>Diagramme de classes UML</a></span></li><li><span><a data-toc-modified-id=\"ERD-avec-la-convention-Look-across-4.2.2\" href=\"#ERD-avec-la-convention-Look-across\"><span class=\"toc-item-num\">4.2.2  </span>ERD avec la convention <em>Look across</em></a></span></li><li><span><a data-toc-modified-id=\"Dictionnaire-des-données-4.2.3\" href=\"#Dictionnaire-des-données\"><span class=\"toc-item-num\">4.2.3  </span>Dictionnaire des données</a></span></li><li><span><a data-toc-modified-id=\"URL-de-partage-4.2.4\" href=\"#URL-de-partage\"><span class=\"toc-item-num\">4.2.4  </span>URL de partage</a></span></li></ul></li></ul></li><li><span><a data-toc-modified-id=\"Mocodo-pour-la-pédagogie-5\" href=\"#Mocodo-pour-la-pédagogie\"><span class=\"toc-item-num\">5  </span>Mocodo pour la pédagogie</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Vue-en-extension-5.1\" href=\"#Vue-en-extension\"><span class=\"toc-item-num\">5.1  </span>Vue en extension</a></span></li><li><span><a data-toc-modified-id=\"MCD-interactif-5.2\" href=\"#MCD-interactif\"><span class=\"toc-item-num\">5.2  </span>MCD interactif</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Afficher-des-explications-au-survol-5.2.1\" href=\"#Afficher-des-explications-au-survol\"><span class=\"toc-item-num\">5.2.1  </span>Afficher des explications au survol</a></span></li><li><span><a data-toc-modified-id=\"Dévoiler-un-MCD-par-étapes-5.2.2\" href=\"#Dévoiler-un-MCD-par-étapes\"><span class=\"toc-item-num\">5.2.2  </span>Dévoiler un MCD par étapes</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Explications-du-passage-au-relationnel-5.3\" href=\"#Explications-du-passage-au-relationnel\"><span class=\"toc-item-num\">5.3  </span>Explications du passage au relationnel</a></span></li><li><span><a data-toc-modified-id=\"MCD-à-compléter-5.4\" href=\"#MCD-à-compléter\"><span class=\"toc-item-num\">5.4  </span>MCD à compléter</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Supprimer-le-marquage-d'un-identifiant-5.4.1\" href=\"#Supprimer-le-marquage-d'un-identifiant\"><span class=\"toc-item-num\">5.4.1  </span>Supprimer le marquage d'un identifiant</a></span></li><li><span><a data-toc-modified-id=\"Masquer-un-couple-de-cardinalités-5.4.2\" href=\"#Masquer-un-couple-de-cardinalités\"><span class=\"toc-item-num\">5.4.2  </span>Masquer un couple de cardinalités</a></span></li><li><span><a data-toc-modified-id=\"Masquer-un-attribut-5.4.3\" href=\"#Masquer-un-attribut\"><span class=\"toc-item-num\">5.4.3  </span>Masquer un attribut</a></span></li><li><span><a data-toc-modified-id=\"Ne-faire-apparaître-que-le-squelette-du-schéma-conceptuel-5.4.4\" href=\"#Ne-faire-apparaître-que-le-squelette-du-schéma-conceptuel\"><span class=\"toc-item-num\">5.4.4  </span>Ne faire apparaître que le squelette du schéma conceptuel</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Obfuscation-d'un-MCD-donné-5.5\" href=\"#Obfuscation-d'un-MCD-donné\"><span class=\"toc-item-num\">5.5  </span>Obfuscation d'un MCD donné</a></span></li><li><span><a data-toc-modified-id=\"Croissance-stochastique-5.6\" href=\"#Croissance-stochastique\"><span class=\"toc-item-num\">5.6  </span>Croissance stochastique</a></span></li><li><span><a data-toc-modified-id=\"Génération-d'un-QR-code-5.7\" href=\"#Génération-d'un-QR-code\"><span class=\"toc-item-num\">5.7  </span>Génération d'un QR code</a></span></li><li><span><a data-toc-modified-id=\"Bibliothèque-de-MCD-en-ligne-5.8\" href=\"#Bibliothèque-de-MCD-en-ligne\"><span class=\"toc-item-num\">5.8  </span>Bibliothèque de MCD en ligne</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Accès-sous-Mocodo-online-5.8.1\" href=\"#Accès-sous-Mocodo-online\"><span class=\"toc-item-num\">5.8.1  </span>Accès sous Mocodo online</a></span></li><li><span><a data-toc-modified-id=\"Accès-sous-terminal-ou-Jupyter-Notebook-5.8.2\" href=\"#Accès-sous-terminal-ou-Jupyter-Notebook\"><span class=\"toc-item-num\">5.8.2  </span>Accès sous terminal ou Jupyter Notebook</a></span></li></ul></li></ul></li><li><span><a data-toc-modified-id=\"Compléments-sur-l'aspect-visuel-6\" href=\"#Compléments-sur-l'aspect-visuel\"><span class=\"toc-item-num\">6  </span>Compléments sur l'aspect visuel</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Styles-6.1\" href=\"#Styles\"><span class=\"toc-item-num\">6.1  </span>Styles</a></span></li><li><span><a data-toc-modified-id=\"Paramétrage-du-réarrangement-automatique-6.2\" href=\"#Paramétrage-du-réarrangement-automatique\"><span class=\"toc-item-num\">6.2  </span>Paramétrage du réarrangement automatique</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Méthode-exacte-(branch-&amp;-bound)-6.2.1\" href=\"#Méthode-exacte-(branch-&amp;-bound)\"><span class=\"toc-item-num\">6.2.1  </span>Méthode exacte (<em>branch &amp; bound</em>)</a></span></li><li><span><a data-toc-modified-id=\"Méthode-heuristique-(algorithme-génétique)-6.2.2\" href=\"#Méthode-heuristique-(algorithme-génétique)\"><span class=\"toc-item-num\">6.2.2  </span>Méthode heuristique (algorithme génétique)</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Amélioration-du-plongement-6.3\" href=\"#Amélioration-du-plongement\"><span class=\"toc-item-num\">6.3  </span>Amélioration du plongement</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Par-duplication-d'entités-réduites-à-leur-identifiant-6.3.1\" href=\"#Par-duplication-d'entités-réduites-à-leur-identifiant\"><span class=\"toc-item-num\">6.3.1  </span>Par duplication d'entités réduites à leur identifiant</a></span></li><li><span><a data-toc-modified-id=\"Par-suppression-de-ces-mêmes-entités-6.3.2\" href=\"#Par-suppression-de-ces-mêmes-entités\"><span class=\"toc-item-num\">6.3.2  </span>Par suppression de ces mêmes entités</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Ajustement-de-l'aspect-de-certains-éléments-6.4\" href=\"#Ajustement-de-l'aspect-de-certains-éléments\"><span class=\"toc-item-num\">6.4  </span>Ajustement de l'aspect de certains éléments</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Format-des-cardinalités-6.4.1\" href=\"#Format-des-cardinalités\"><span class=\"toc-item-num\">6.4.1  </span>Format des cardinalités</a></span></li><li><span><a data-toc-modified-id=\"Format-des-clés-étrangères-6.4.2\" href=\"#Format-des-clés-étrangères\"><span class=\"toc-item-num\">6.4.2  </span>Format des clés étrangères</a></span></li><li><span><a data-toc-modified-id=\"Symbole-de-dépendance-fonctionnelle-6.4.3\" href=\"#Symbole-de-dépendance-fonctionnelle\"><span class=\"toc-item-num\">6.4.3  </span>Symbole de dépendance fonctionnelle</a></span></li><li><span><a data-toc-modified-id=\"Basculement-des-cardinalités-et-inflexion-des-pattes-rectilignes-6.4.4\" href=\"#Basculement-des-cardinalités-et-inflexion-des-pattes-rectilignes\"><span class=\"toc-item-num\">6.4.4  </span>Basculement des cardinalités et inflexion des pattes rectilignes</a></span></li><li><span><a data-toc-modified-id=\"Positionnement-des-contraintes-6.4.5\" href=\"#Positionnement-des-contraintes\"><span class=\"toc-item-num\">6.4.5  </span>Positionnement des contraintes</a></span></li><li><span><a data-toc-modified-id=\"Gouttière-d'identifiants-6.4.6\" href=\"#Gouttière-d'identifiants\"><span class=\"toc-item-num\">6.4.6  </span>Gouttière d'identifiants</a></span></li><li><span><a data-toc-modified-id=\"Style-et-direction-des-pattes-de-l'héritage-6.4.7\" href=\"#Style-et-direction-des-pattes-de-l'héritage\"><span class=\"toc-item-num\">6.4.7  </span>Style et direction des pattes de l'héritage</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Retouches-fines-6.5\" href=\"#Retouches-fines\"><span class=\"toc-item-num\">6.5  </span>Retouches fines</a></span></li><li><span><a data-toc-modified-id=\"Conversion-dans-d'autres-formats-graphiques-6.6\" href=\"#Conversion-dans-d'autres-formats-graphiques\"><span class=\"toc-item-num\">6.6  </span>Conversion dans d'autres formats graphiques</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Annexe-A :-Miscellanées-académiques-7\" href=\"#Annexe-A :-Miscellanées-académiques\"><span class=\"toc-item-num\">7  </span>Annexe A : Miscellanées académiques</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Décompositions-d'un-MCD-7.1\" href=\"#Décompositions-d'un-MCD\"><span class=\"toc-item-num\">7.1  </span>Décompositions d'un MCD</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Vider-les-DF-de-leurs-attributs-7.1.1\" href=\"#Vider-les-DF-de-leurs-attributs\"><span class=\"toc-item-num\">7.1.1  </span>Vider les DF de leurs attributs</a></span></li><li><span><a data-toc-modified-id=\"Décomposer-les-DF-n-aires-7.1.2\" href=\"#Décomposer-les-DF-n-aires\"><span class=\"toc-item-num\">7.1.2  </span>Décomposer les DF n-aires</a></span></li><li><span><a data-toc-modified-id=\"Décomposer-les-associations-n-aires-non-DF-7.1.3\" href=\"#Décomposer-les-associations-n-aires-non-DF\"><span class=\"toc-item-num\">7.1.3  </span>Décomposer les associations n-aires non DF</a></span></li><li><span><a data-toc-modified-id=\"Décomposer-les-associations-binaires-non-DF-7.1.4\" href=\"#Décomposer-les-associations-binaires-non-DF\"><span class=\"toc-item-num\">7.1.4  </span>Décomposer les associations binaires non DF</a></span></li><li><span><a data-toc-modified-id=\"Décomposer-en-créant-des-entités-faibles-7.1.5\" href=\"#Décomposer-en-créant-des-entités-faibles\"><span class=\"toc-item-num\">7.1.5  </span>Décomposer en créant des entités faibles</a></span></li><li><span><a data-toc-modified-id=\"Conclusion-sur-ces-décompositions-7.1.6\" href=\"#Conclusion-sur-ces-décompositions\"><span class=\"toc-item-num\">7.1.6  </span>Conclusion sur ces décompositions</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Équivalences-avec-la-convention-Look-Across-7.2\" href=\"#Équivalences-avec-la-convention-Look-Across\"><span class=\"toc-item-num\">7.2  </span>Équivalences avec la convention <em>Look Across</em></a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Associations-binaires-en-Look-Across-7.2.1\" href=\"#Associations-binaires-en-Look-Across\"><span class=\"toc-item-num\">7.2.1  </span>Associations binaires en <em>Look Across</em></a></span></li><li><span><a data-toc-modified-id=\"Associations-n-aires-en-Look-Across-7.2.2\" href=\"#Associations-n-aires-en-Look-Across\"><span class=\"toc-item-num\">7.2.2  </span>Associations n-aires en <em>Look Across</em></a></span></li></ul></li></ul></li><li><span><a data-toc-modified-id=\"Annexe-B :-La-commande-mocodo-8\" href=\"#Annexe-B :-La-commande-mocodo\"><span class=\"toc-item-num\">8  </span>Annexe B : La commande <code>mocodo</code></a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Paramétrage-8.1\" href=\"#Paramétrage\"><span class=\"toc-item-num\">8.1  </span>Paramétrage</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"mocodo---help-8.1.1\" href=\"#mocodo---help\"><span class=\"toc-item-num\">8.1.1  </span><code>mocodo --help</code></a></span></li><li><span><a data-toc-modified-id=\"Paramétrage-à-long-terme-8.1.2\" href=\"#Paramétrage-à-long-terme\"><span class=\"toc-item-num\">8.1.2  </span>Paramétrage à long terme</a></span></li><li><span><a data-toc-modified-id=\"Dissection-de-la-commande-8.1.3\" href=\"#Dissection-de-la-commande\"><span class=\"toc-item-num\">8.1.3  </span>Dissection de la commande</a></span></li></ul></li><li><span><a data-toc-modified-id=\"L'option---transform-et-ses-arguments-8.2\" href=\"#L'option---transform-et-ses-arguments\"><span class=\"toc-item-num\">8.2  </span>L'option <code>--transform</code> et ses arguments</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Triage-et-exécution-des-transformations-8.2.1\" href=\"#Triage-et-exécution-des-transformations\"><span class=\"toc-item-num\">8.2.1  </span>Triage et exécution des transformations</a></span></li><li><span><a data-toc-modified-id=\"Aide-mémoire-des-transformations-8.2.2\" href=\"#Aide-mémoire-des-transformations\"><span class=\"toc-item-num\">8.2.2  </span>Aide-mémoire des transformations</a></span></li><li><span><a data-toc-modified-id=\"Réécriture-d'éléments-donnés-8.2.3\" href=\"#Réécriture-d'éléments-donnés\"><span class=\"toc-item-num\">8.2.3  </span>Réécriture d'éléments donnés</a></span></li></ul></li><li><span><a data-toc-modified-id=\"Fonctionnement-de-la-commande-magique-8.3\" href=\"#Fonctionnement-de-la-commande-magique\"><span class=\"toc-item-num\">8.3  </span>Fonctionnement de la commande magique</a></span></li><li><span><a data-toc-modified-id=\"Gabarits-de-passage-au-relationnel-8.4\" href=\"#Gabarits-de-passage-au-relationnel\"><span class=\"toc-item-num\">8.4  </span>Gabarits de passage au relationnel</a></span><ul class=\"toc-item\"><li><span><a data-toc-modified-id=\"Format-des-gabarits-8.4.1\" href=\"#Format-des-gabarits\"><span class=\"toc-item-num\">8.4.1  </span>Format des gabarits</a></span></li><li><span><a data-toc-modified-id=\"Dérivation-de-gabarits-8.4.2\" href=\"#Dérivation-de-gabarits\"><span class=\"toc-item-num\">8.4.2  </span>Dérivation de gabarits</a></span></li><li><span><a data-toc-modified-id=\"Exemples-de-création-de-gabarit-dérivé--8.4.3\" href=\"#Exemples-de-création-de-gabarit-dérivé-\"><span class=\"toc-item-num\">8.4.3  </span>Exemples de création de gabarit dérivé <a rel=\"nofollow\"></a></a></span></li><li><span><a data-toc-modified-id=\"Mécanisme-de-mise-à-jour-8.4.4\" href=\"#Mécanisme-de-mise-à-jour\"><span class=\"toc-item-num\">8.4.4  </span>Mécanisme de mise à jour</a></span></li></ul></li></ul></li><li><span><a data-toc-modified-id=\"Annexe-C :-Crédits-9\" href=\"#Annexe-C :-Crédits\"><span class=\"toc-item-num\">9  </span>Annexe C : Crédits</a></span></li></ul></div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [1]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">reload_ext</span> mocodo\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>Mocodo 4.3.2 loaded.\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [2]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">IPython</span> <span class=\"kn\">import</span> <span class=\"n\">display</span>\n<span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n<span class=\"kn\">import</span> <span class=\"nn\">os</span>\n<span class=\"k\">if</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">!=</span> <span class=\"s2\">\"mocodo_notebook\"</span><span class=\"p\">:</span>\n    <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s2\">\"mocodo_notebook\"</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">mkdir</span><span class=\"p\">(</span><span class=\"n\">parents</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span> <span class=\"n\">exist_ok</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n    <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">chdir</span><span class=\"p\">(</span><span class=\"s2\">\"mocodo_notebook\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><img alt=\"\" src=\"https://cdn.rawgit.com/laowantong/mocodo/master/logos/banner.svg\"/></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Introduction\">Introduction<a class=\"anchor-link\" href=\"#Introduction\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo est un logiciel d'aide à l'enseignement et à l'apprentissage des <a href=\"https://fr.wikipedia.org/wiki/Base_de_donn%C3%A9es_relationnelle\">bases de données relationnelles</a>.</p>\n<ul>\n<li>En entrée, il prend un <a href=\"https://fr.wikipedia.org/wiki/Mod%C3%A8le_entit%C3%A9-association\">MCD</a> (modèle conceptuel de données) décrit dans un langage dédié minimaliste.</li>\n<li>En sortie, il produit un diagramme entité-association et, à la demande, un <a href=\"https://fr.wikipedia.org/wiki/Merise_%28informatique%29%23MLD_%3A_mod%C3%A8le_logique_des_donn%C3%A9es\">MLD</a> (schéma relationnel, sous forme graphique ou textuelle), un <a href=\"https://fr.wikipedia.org/wiki/Langage_de_d%C3%A9finition_de_donn%C3%A9es\">DDL</a> (script SQL de création de la base), un <a href=\"https://fr.wikipedia.org/wiki/Diagramme_de_classes\">diagramme de classes UML</a>, etc.</li>\n<li>En bonus, il est capable de réarranger automatiquement votre MCD de façon esthétique, et de lui appliquer des opérations de réécriture qui vont du mondain (typographie) à l'académique (décomposition d'associations), en passant par le merveilleux (inférence de types, génération d'exercices et d'exemples).</li>\n</ul>\n<p>Vous pouvez utiliser Mocodo :</p>\n<ul>\n<li>à distance, sans rien installer, avec <a href=\"https://www.mocodo.net\">Mocodo <em>online</em></a> ;</li>\n<li>en local, comme n'importe quel programme Python ;</li>\n<li>dans un document <a href=\"https://jupyter.org\">Jupyter Notebook</a> (à l'instar de cette documentation).</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Trac%C3%A9-du-mod%C3%A8le-conceptuel\">Tracé du modèle conceptuel<a class=\"anchor-link\" href=\"#Trac%C3%A9-du-mod%C3%A8le-conceptuel\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ci-dessous, un exemple d'utilisation sous Jupyter Notebook. L'appel du programme est en première ligne ; le texte-source proprement dit, lignes suivantes. En sortie, le diagramme conceptuel, égayé au passage par l'option <code>--colors</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [3]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --colors ocean\nClient: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPasser, 0N Client, 11 Commande\nCommande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nInclure, 1N Commande, 0N Produit: Quantité [INTEGER]\nProduit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTk0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMyNzM2MGMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjQiIHgyPSI0MTkiIHkyPSI2NCIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzgiIHkxPSI2NCIgeDI9IjQxOSIgeTI9IjY0IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg2IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDYyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzkwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg2IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3NiIgeT0iMzUiIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM3NiIgeTE9IjYzIiB4Mj0iNDYyIiB5Mj0iNjMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjU2LjMiIGZpbGw9IiMyNzM2MGMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIzODMiIHk9IjgxLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2NyIgeT0iODAiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iODciIHkyPSIzOSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzQ3IiB5Mj0iNDciIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzOCIgeT0iMzguMyIgZmlsbD0iIzEzMTExNCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iNjQuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzEiIHkxPSI2NyIgeDI9IjMzOSIgeTI9IjY3IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjMxIiB5PSI4MS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI5OCIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDkxIiB5PSI0NyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5MSIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTEiIHkxPSI0NyIgeDI9IjU4NSIgeTI9IjQ3IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDIiIHk9IjM4LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iNjQuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0OTkiIHkxPSI2NyIgeDI9IjU3NCIgeTI9IjY3IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDk5IiB5PSI4MS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iOTgiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Op%C3%A9rations-de-conversion\">Opérations de conversion<a class=\"anchor-link\" href=\"#Op%C3%A9rations-de-conversion\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'appel précédent a automatiquement enregistré le texte-source sous le nom de <code>sandbox.mcd</code>. Renommons-le <code>ccp.mcd</code> pour y avoir accès tout au long de ce document.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [4]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s2\">\"sandbox.mcd\"</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">rename</span><span class=\"p\">(</span><span class=\"s2\">\"ccp.mcd\"</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>On peut le récupérer avec <code>--input</code> pour lui appliquer diverses opérations. Ainsi, l'appel suivant génère et affiche son MLD, son diagramme relationnel et son DDL :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [5]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> --input ccp --transform mld diagram ddl --colors mondrian\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Client</strong> (<u>Réf. client</u>, Nom, Prénom, Adresse)</li>\n<li><strong>Commande</strong> (<u>Num. commande</u>, Date, Montant, <em>#Réf. client</em>)</li>\n<li><strong>Inclure</strong> (<u><em>#Num. commande</em></u>, <u><em>#Réf. produit</em></u>, Quantité)</li>\n<li><strong>Produit</strong> (<u>Réf. produit</u>, Libellé, Prix unitaire)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2ODAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjgwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY4MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjZmVmZWVjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gY2xpZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkNMVVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSI0NyIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjE3IiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM1NiIgeTE9IjQ3IiB4Mj0iNDkwIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM4NyIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJPHRleHQgeD0iMzY0IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jTnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI2NyIgeDI9IjQ4MSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQ0OCIgeTI9Ijg0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU0OCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTQ4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU0OCIgeTE9IjQ3IiB4Mj0iNjQyIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU1OSIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU1NiIgeTE9IjY3IiB4Mj0iNjMxIiB5Mj0iNjciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NTYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDkwIDc4LjUgQzUxOSA3MCA1MDkuMzMgNjEuNSA1NDggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1NDggNjEuNSA1MzYgNjcuNSA1NDAgNjEuNSA1MzYgNTUuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ5MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Client</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_client</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Nom</span><span class=\"w\">        </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Prenom</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Adresse</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Num_commande</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"nb\">Date</span><span class=\"w\">         </span><span class=\"nb\">DATE</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Montant</span><span class=\"w\">      </span><span class=\"nb\">DECIMAL</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_client</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">Ref_produit</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Num_commande</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_produit</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Quantite</span><span class=\"w\">     </span><span class=\"nb\">INTEGER</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Produit</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_produit</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Libelle</span><span class=\"w\">       </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">50</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Prix_unitaire</span><span class=\"w\"> </span><span class=\"nb\">DECIMAL</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Client</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Produit</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">);</span>\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans la suite, pour épargner la frappe, les options <code>--input</code> et <code>--transform</code> seront respectivement abrégées en <code>-i</code> et <code>-t</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les opérations de conversion ne se limitent pas forcément au schéma relationnel. En voici une qui extrait un dictionnaire des données, par défaut sous la forme d'un tableau Markdown à trois colonnes :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [6]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t data_dict\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_data_dict_3.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Entité ou association</th>\n<th style=\"text-align:left\">Libellé de l'attribut</th>\n<th style=\"text-align:left\">Type</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">Client</td>\n<td style=\"text-align:left\">Adresse</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Nom</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Prénom</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Réf. client</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">Commande</td>\n<td style=\"text-align:left\">Date</td>\n<td style=\"text-align:left\">DATE</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Montant</td>\n<td style=\"text-align:left\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Num. commande</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">Inclure</td>\n<td style=\"text-align:left\">Quantité</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">Produit</td>\n<td style=\"text-align:left\">Libellé</td>\n<td style=\"text-align:left\">VARCHAR(50)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Prix unitaire</td>\n<td style=\"text-align:left\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Réf. produit</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Une autre qui transcrit le MCD dans la notation <em>crow's foot</em> (<code>crow</code>) pour <a href=\"http://mermaid.js.org\">Mermaid</a> (<code>mmd</code>) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [7]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t crow:mmd\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_erd_crow.mmd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<pre><code class=\"language-mmd\">mmd\nerDiagram\n  Client {\n    VARCHAR(8) Ref_client PK\n    VARCHAR(255) Nom\n    VARCHAR(255) Prenom\n    VARCHAR(255) Adresse\n  }\n  Commande {\n    VARCHAR(8) Num_commande PK\n    DATE Date\n    DECIMAL(10-2) Montant\n  }\n  Inclure {\n    INTEGER Quantite PK\n  }\n  Produit {\n    VARCHAR(8) Ref_produit PK\n    VARCHAR(50) Libelle\n    DECIMAL(10-2) Prix_unitaire\n  }\n  Client ||--o{ Commande: Passer\n  Inclure }|..|| Commande: DF\n  Inclure }o..|| Produit: DF\n\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le rendu des diagrammes décrits dans des langages-tiers (comme Mermaid, PlantUML, etc.) n'est pas directement pris en charge, mais peut être délégué (<code>--defer</code>) de façon transparente au service web approprié. Dans ce cas, c'est la sortie graphique qui est affichée :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [8]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t crow:plantuml --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_erd_crow.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjYyNHB0IiBoZWlnaHQ9IjMzMnB0Igogdmlld0JveD0iMC4wMCAwLjAwIDYyNC4wMCAzMzEuNTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMzI3LjUpIj4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTMyNy41IDYyMCwtMzI3LjUgNjIwLDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzOSwtMTc2LjUgMzksLTMxOS41IDI2OSwtMzE5LjUgMjY5LC0xNzYuNSAzOSwtMTc2LjUiLz4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjM5LC0yODguNSAzOSwtMzE5LjUgMjY5LC0zMTkuNSAyNjksLTI4OC41IDM5LC0yODguNSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTI4OC41IDM5LC0zMTkuNSAyNjksLTMxOS41IDI2OSwtMjg4LjUgMzksLTI4OC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI3Ljc1IiB5PSItMjk3LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+Q2xpZW50PC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTI2MC41IDM5LC0yODguNSA2NywtMjg4LjUgNjcsLTI2MC41IDM5LC0yNjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQzLjYyIiB5PSItMjY5LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlBLPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjg4LjUgNjcsLTI4OC41IDY3LC0yNjAuNSAxNTEsLTI2MC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzEuODgiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gY2xpZW50PC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjYwLjUgMjY5LC0yNjAuNSAyNjksLTI4OC41IDE1MSwtMjg4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzQiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM5LC0yMzIuNSAzOSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAzOSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MC43NSIgeT0iLTI0MS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAxNTEsLTIzMi41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzIiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+Tm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjMyLjUgMjY5LC0yMzIuNSAyNjksLTI2MC41IDE1MSwtMjYwLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTIwNC41IDM5LC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDM5LC0yMDQuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMjEzLjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTUxLC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTIxMy4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QcsOpbm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjA0LjUgMjY5LC0yMDQuNSAyNjksLTIzMi41IDE1MSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yMTMuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTE3Ni41IDM5LC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDM5LC0xNzYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMTg1LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTUxLC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDE1MSwtMTc2LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTE4NS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5BZHJlc3NlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMTc2LjUgMjY5LC0xNzYuNSAyNjksLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0xODUuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjgsLTQgOCwtMTE5IDMwMCwtMTE5IDMwMCwtNCA4LC00Ii8+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSI4LC04OCA4LC0xMTkgMzAwLC0xMTkgMzAwLC04OCA4LC04OCIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtODggOCwtMTE5IDMwMCwtMTE5IDMwMCwtODggOCwtODgiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxMDIuMjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPkNvbW1hbmRlPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtNjAgOCwtODggMzYsLTg4IDM2LC02MCA4LC02MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjEyLjYyIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC04OCAzNiwtODggMzYsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MC43NSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk51bS4gY29tbWFuZGU8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC02MCAzMDAsLTYwIDMwMCwtODggMTczLC04OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIwNSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlZBUkNIQVIoOCk8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI4LC0zMiA4LC02MCAzNiwtNjAgMzYsLTMyIDgsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTkuNzUiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE3MywtNjAgMzYsLTYwIDM2LC0zMiAxNzMsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDEiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EYXRlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE3MywtMzIgMzAwLC0zMiAzMDAsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIyNTkiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EQVRFPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtNCA4LC0zMiAzNiwtMzIgMzYsLTQgOCwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE5Ljc1IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+IDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNzMsLTMyIDM2LC0zMiAzNiwtNCAxNzMsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk1vbnRhbnQ8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC00IDMwMCwtNCAzMDAsLTMyIDE3MywtMzIiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzgiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5ERUNJTUFMKDEwLDIpPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7Jmd0OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7Jmd0OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNTQsLTE2Mi45NEMxNTQsLTE1NS45NSAxNTQsLTE0OC44OSAxNTQsLTE0MS45MyIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU5LC0xNzEuNzUgMTQ5LC0xNzEuNzUgMTQ5LC0xNjkuNzUgMTU5LC0xNjkuNzUgMTU5LC0xNzEuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNTQsLTE3Mi43NSAxNTQsLTE2Ny43NSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU5LC0xNjYuNzUgMTQ5LC0xNjYuNzUgMTQ5LC0xNjQuNzUgMTU5LC0xNjQuNzUgMTU5LC0xNjYuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNTQsLTE2Ny43NSAxNTQsLTE2Mi43NSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU0LC0xMzMuMDYgMTU4LjUsLTEyMy4wNiAxNTQsLTEyNy43MyAxNTQsLTEyMy40IDE1NCwtMTIzLjQgMTU0LC0xMjMuNCAxNTQsLTEyNy43MyAxNDkuNSwtMTIzLjA2IDE1NCwtMTMzLjA2Ii8+CjxlbGxpcHNlIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgY3g9IjE1NCIgY3k9Ii0xMzguNzgiIHJ4PSI0IiByeT0iNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIiIHk9Ii0xNDQuMDUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEuMDAiIGZpbGw9IiMwMDAwMDAiPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjE4LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjE4LjUgMzU2LjUsLTIxOC41Ii8+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDE0LjYyIiB5PSItMjU1LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+SW5jbHVyZTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1Ni41LC0yMTguNSAzNTYuNSwtMjQ2LjUgMzg0LjUsLTI0Ni41IDM4NC41LC0yMTguNSAzNTYuNSwtMjE4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNjEuMTIiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDYwLjUsLTI0Ni41IDM4NC41LC0yNDYuNSAzODQuNSwtMjE4LjUgNDYwLjUsLTIxOC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg5LjUiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UXVhbnRpdMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2MC41LC0yMTguNSA1MzMuNSwtMjE4LjUgNTMzLjUsLTI0Ni41IDQ2MC41LC0yNDYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ2NS41IiB5PSItMjI3LjI1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPklOVEVHRVI8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmZ3Q7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmZ3Q7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWRhc2hhcnJheT0iMSw1IiBkPSJNMzgxLjA3LC0yMDYuNDdDMzQ0Ljg5LC0xODMuNTMgMjk4Ljc4LC0xNTQuMyAyNTcuNTgsLTEyOC4xNyIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzg1LjI1LC0yMDkuMTIgMzkxLjI5LC0yMTguMjcgMzg5Ljc2LC0yMTEuOTcgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzg5Ljc2LC0yMTEuOTcgMzk2LjExLC0yMTAuNjcgMzg1LjI1LC0yMDkuMTIiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM4Ni4wNSwtMjAzLjcxIDM4MC43LC0yMTIuMTUgMzc5LjAxLC0yMTEuMDggMzg0LjM3LC0yMDIuNjQgMzg2LjA1LC0yMDMuNzEiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzODQuMjIsLTIwOC40NyAzODAsLTIwNS43OSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMjQ3LjMsLTEyNy41OCAyNTIuNjYsLTExOS4xMyAyNTQuMzUsLTEyMC4yIDI0OC45OSwtMTI4LjY1IDI0Ny4zLC0xMjcuNTgiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIyNDkuMTQsLTEyMi44MiAyNTMuMzYsLTEyNS41Ii8+Cjxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIyNTEuNTMsLTEzMC4yNSAyNTYuODgsLTEyMS44MSAyNTguNTcsLTEyMi44OCAyNTMuMjIsLTEzMS4zMyAyNTEuNTMsLTEzMC4yNSIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjI1My4zNiwtMTI1LjUgMjU3LjU4LC0xMjguMTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjk4LjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMDAwMDAwIj5ERjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTIsLTQgMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC00IDM1MiwtNCIvPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iMzUyLC04OCAzNTIsLTExOSA2MDgsLTExOSA2MDgsLTg4IDM1MiwtODgiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtODggMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC04OCAzNTIsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDQ4LjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPlByb2R1aXQ8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzNTIsLTYwIDM1MiwtODggMzgwLC04OCAzODAsLTYwIDM1MiwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTYuNjIiIHk9Ii02OC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QSzwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0ODEsLTg4IDM4MCwtODggMzgwLC02MCA0ODEsLTYwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg1IiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0ODEsLTYwIDYwOCwtNjAgNjA4LC04OCA0ODEsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNTEzIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtMzIgMzUyLC02MCAzODAsLTYwIDM4MCwtMzIgMzUyLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDgxLC02MCAzODAsLTYwIDM4MCwtMzIgNDgxLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM4NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPkxpYmVsbMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ4MSwtMzIgNjA4LC0zMiA2MDgsLTYwIDQ4MSwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MDQiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5WQVJDSEFSKDUwKTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtNCAzNTIsLTMyIDM4MCwtMzIgMzgwLC00IDM1MiwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDgxLC0zMiAzODAsLTMyIDM4MCwtNCA0ODEsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzODQuNzUiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ4MSwtNCA2MDgsLTQgNjA4LC0zMiA0ODEsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDg2IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+REVDSU1BTCgxMCwyKTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyZndDs0IC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyZndDs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtZGFzaGFycmF5PSIxLDUiIGQ9Ik00NTQuNywtMTk1Ljg3QzQ1OC40MiwtMTc2LjI3IDQ2Mi43MywtMTUzLjU2IDQ2Ni43MiwtMTMyLjUiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ1My4wMiwtMjA0LjcxIDQ0Ni43NCwtMjEzLjcgNDUyLjAzLC0yMDkuOTUgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUyLjAzLC0yMDkuOTUgNDU1LjU4LC0yMTUuMzcgNDUzLjAyLC0yMDQuNzEiLz4KPGVsbGlwc2UgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBjeD0iNDU0LjA5IiBjeT0iLTE5OS4wOSIgcng9IjQiIHJ5PSI0Ii8+Cjxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0NjMuNDMsLTEyMyA0NzMuMjYsLTEyNC44NyA0NzIuODksLTEyNi44MyA0NjMuMDYsLTEyNC45NyA0NjMuNDMsLTEyMyIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2OC41MywtMTIyLjk1IDQ2Ny42LC0xMjcuODYiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2Mi41LC0xMjcuOTIgNDcyLjMzLC0xMjkuNzggNDcxLjk1LC0xMzEuNzQgNDYyLjEzLC0xMjkuODggNDYyLjUsLTEyNy45MiIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2Ny42LC0xMjcuODYgNDY2LjY3LC0xMzIuNzgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDcyLjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMDAwMDAwIj5ERjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Op%C3%A9rations-de-r%C3%A9%C3%A9criture\">Opérations de réécriture<a class=\"anchor-link\" href=\"#Op%C3%A9rations-de-r%C3%A9%C3%A9criture\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Une <strong>réécriture</strong> transforme un MCD Mocodo en un autre MCD Mocodo (au contraire d'une <strong>conversion</strong>, qui produit un animal d'une espèce différente).</p>\n<p>Heureusement, l'utilisateur n'a pas à réfléchir si la transformation qu'il souhaite appliquer est une réécriture ou une conversion : dans les deux cas, il invoque <code>-t</code> (c'est-à-dire <code>--transform</code>), et Mocodo se débrouille.</p>\n<p>En guise de premier exemple de réécriture, mettons les noms des entités et associations (<code>boxes</code>) en majuscules, et les libellés (<code>labels</code>) en ASCII et <em>snake case</em> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [9]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t upper:boxes ascii:labels snake:labels --colors brewer+3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjMwIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiBmaWxsPSIjZjdmN2Y3IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSIxNjYiIHkyPSI2NCIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDIiIHkxPSI2NCIgeDI9IjE2NiIgeTI9IjY0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5NiAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2MyYTVjZiIgc3Ryb2tlPSIjYzJhNWNmIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjEwIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg4IiBmaWxsPSIjZTdkNGU4IiBzdHJva2U9IiNlN2Q0ZTgiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iMzUiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjYzIiB4Mj0iMjEwIiB5Mj0iNjMiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjkiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMWI3ODM3IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTYiIHk9IjgwIiBmaWxsPSIjMWI3ODM3IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMzAyIiB5MT0iNjQiIHgyPSI0NDMiIHkyPSI2NCIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NzEiIHkxPSI2NCIgeDI9IjQ0MyIgeTI9IjY0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ3OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTk4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2MyYTVjZiIgc3Ryb2tlPSIjYzJhNWNmIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDkyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDA4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk4IiBmaWxsPSIjZTdkNGU4IiBzdHJva2U9IiNlN2Q0ZTgiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM5NCIgeT0iMzUiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM5NCIgeTE9IjYzIiB4Mj0iNDkyIiB5Mj0iNjMiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0MDIiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSI0MDEiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXRlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzcwIiB5PSI4MCIgZmlsbD0iIzFiNzgzNyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNDk3IiB5PSI4MCIgZmlsbD0iIzFiNzgzNyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZkYmEwIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iODQiIGhlaWdodD0iODAiIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI5MyIgeTI9IjM5IiBzdHJva2U9IiM1YWFlNjEiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UmVmX2NsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iODAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJlbm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjM5IiB5PSIxNyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzkiIHk9IjQ3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjY0IiBmaWxsPSIjZDlmMGQzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIzOSIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjM5IiB5MT0iNDciIHgyPSIzNjUiIHkyPSI0NyIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjQ4IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTU1BTkRFPC90ZXh0PgoJPHRleHQgeD0iMjQ3IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW1fY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMjQ3IiB5MT0iNjciIHgyPSIzNTYiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI0NyIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk1vbnRhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0RVSVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNTIxIiB5PSIxNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MjEiIHk9IjQ3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjZDlmMGQzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUyMSIgeT0iMTciIHdpZHRoPSIxMDAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTIxIiB5MT0iNDciIHgyPSI2MjEiIHkyPSI0NyIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTMwIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0RVSVQ8L3RleHQ+Cgk8dGV4dCB4PSI1MjkiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlJlZl9wcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjUyOSIgeTE9IjY3IiB4Mj0iNjA1IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1MjkiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbGU8L3RleHQ+Cgk8dGV4dCB4PSI1MjkiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4X3VuaXRhaXJlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --colors brewer+3\nCLIENT: Ref_client [VARCHAR(8)], Nom [VARCHAR(255)], Prenom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num_commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantite [INTEGER]\nPRODUIT: Ref_produit [VARCHAR(8)], Libelle [VARCHAR(50)], Prix_unitaire [DECIMAL(10,2)]\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Remarquez que l'exécution d'une réécriture affiche, au-dessous du diagramme, le code-source résultant. Celui-ci est précédé de la commande magique originale, <em>privée de l'option <code>-i</code> et de toute opération de réécriture</em>. Ces dispositions permettent de continuer à travailler directement dessus si on le copie-colle dans une autre cellule.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Plusieurs opérations de réécriture de nature sémantique sont également offertes. Par exemple, on peut décomposer un MCD quelconque en un MCD équivalent, mais n'employant que des dépendances fonctionnelles et des entités faibles :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [10]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t explode:weak,arity=2 arrange:wide --seed=3 --colors brewer+3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3MzQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNzM0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3MzQiIGhlaWdodD0iMTI4IiBmaWxsPSIjZjdmN2Y3IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2MyYTVjZiIgc3Ryb2tlPSIjYzJhNWNmIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjZTdkNGU4IiBzdHJva2U9IiNlN2Q0ZTgiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjMWI3ODM3IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSIjMWI3ODM3IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8Zz4KCTxsaW5lIHgxPSI0ODkiIHkxPSI2NCIgeDI9IjM5NiIgeTI9IjY0IiBzdHJva2U9IiM5OTcwYWIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI4NSIgeTE9IjY0IiB4Mj0iMzk2IiB5Mj0iNjQiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzOTYiIGN5PSI2NCIgcj0iMjAiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNjMmE1Y2YiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjY4LjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0MjIiIHk9IjgwIiBmaWxsPSIjMWI3ODM3IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iNDIyIiB5MT0iODIiIHgyPSI0NDAiIHkyPSI4MiIgc3Ryb2tlPSIjMWI3ODM3IiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9IiMxYjc4MzciIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjEgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4OSIgeTE9IjY0IiB4Mj0iNTgyIiB5Mj0iNjQiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjc4IiB5MT0iNjQiIHgyPSI1ODIiIHkyPSI2NCIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjU4MiIgY3k9IjY0IiByPSIyMCIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI2MyYTVjZiIvPgoJCTx0ZXh0IHg9IjU2OSIgeT0iNjguOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUzOCIgeT0iODAiIGZpbGw9IiMxYjc4MzciIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSI1MzgiIHkxPSI4MiIgeDI9IjU1NiIgeTI9IjgyIiBzdHJva2U9IiMxYjc4MzciIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNjA3IiB5PSI4MCIgZmlsbD0iIzFiNzgzNyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZkYmEwIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNzgiIGhlaWdodD0iODAiIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI4NyIgeTI9IjM5IiBzdHJva2U9IiM1YWFlNjEiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI3OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjIzIiB5PSIxNyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjQ3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjZDlmMGQzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjIzIiB5MT0iNDciIHgyPSIzNDciIHkyPSI0NyIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjM4IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbW1hbmRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjIzMSIgeTE9IjY3IiB4Mj0iMzM5IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMzEiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyMzEiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Nb250YW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkNMVVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQ0NSIgeT0iMzQiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NDUiIHk9IjY0IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDQ1IiB5PSIzNCIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ0NSIgeTE9IjY0IiB4Mj0iNTMzIiB5Mj0iNjQiIHN0cm9rZT0iIzVhYWU2MSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ1MyIgeT0iNTUuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJPHRleHQgeD0iNDUzIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5RdWFudGl0w6k8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0RVSVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNjMxIiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZkYmEwIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjYzMSIgeT0iNDciIHdpZHRoPSI5NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2Q5ZjBkMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI2MzEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNjMxIiB5MT0iNDciIHgyPSI3MjUiIHkyPSI0NyIgc3Ryb2tlPSIjNWFhZTYxIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNjQyIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2R1aXQ8L3RleHQ+Cgk8dGV4dCB4PSI2MzkiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIHByb2R1aXQ8L3RleHQ+Cgk8bGluZSB4MT0iNjM5IiB5MT0iNjciIHgyPSI3MTQiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjYzOSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TGliZWxsw6k8L3RleHQ+Cgk8dGV4dCB4PSI2MzkiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --seed=3 --colors brewer+3\nClient: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPasser, 0N Client, 11 Commande\nCommande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nDF, _11 Inclure, 1N Commande\nInclure: _Quantité [INTEGER]\nDF, _11 Inclure, 0N Produit\nProduit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez l'argument <code>arrange:wide</code>. Il a procédé à une réorganisation aléatoire des boîtes, ce que l'insertion de deux nouvelles associations de dépendance fonctionnelles avait rendu nécessaire. Quant à l'option <code>--seed=3</code>, elle garantit que le résultat sera le même à chaque exécution.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Après cet aperçu de quelques-unes des fonctionnalités de Mocodo, entrons dans les détails.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Installation-et-lancement-du-programme\">Installation et lancement du programme<a class=\"anchor-link\" href=\"#Installation-et-lancement-du-programme\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme nous l'avons dit, vous pouvez utiliser Mocodo sans rien installer. Il vous suffit d'aller sur <a href=\"https://www.mocodo.net\">mocodo.net</a> et de commencer à taper votre MCD. Appuyez à tout moment sur le ventilateur pour rafraîchir les diagrammes conceptuel et relationnel. Quand le résultat vous convient, appuyez sur le bouton de téléchargement pour récupérer une archive ZIP contenant tous les fichiers d'entrée et de sortie spécifiés.</p>\n<p>Mocodo <em>online</em> est conçu pour une utilisation occasionnelle et/ou interactive, et son interface vise avant tout à la simplicité. Vous n'avez donc accès qu'aux options essentielles du programme. Si vous en voulez davantage, tant en termes de paramétrage que de calcul ou de fonctionnalités, nous vous conseillons d'installer Mocodo sur votre machine.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Installation-minimale\">Installation minimale<a class=\"anchor-link\" href=\"#Installation-minimale\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo est un programme écrit en <a href=\"https://www.python.org\">Python 3</a>. Si vous êtes sous macOS ou Linux, il est déjà installé. Dans le cas contraire, vous devrez peut-être <a href=\"https://www.python.org/downloads/\">le faire</a>.</p>\n<p>Une fois Python présent sur votre machine, tapez sous un terminal:</p>\n<pre><code>    python -m pip install mocodo</code></pre>\n<p>Puis testez-le :</p>\n<pre><code>    mocodo</code></pre>\n<p>Invoqué sous cette forme, Mocodo récupère le texte d'entrée du MCD dans le répertoire courant sous le nom de <code>sandbox.mcd</code>. Si ce fichier n'existe pas, il y sera automatiquement créé avec un MCD d'exemple. Par la suite, vous n'aurez qu'à le garder ouvert sous un éditeur de texte, afin de le modifier à votre fantaisie avant de relancer la commande.</p>\n<p>Si votre système se plaint que cette commande n'existe pas, localisez le fichier <code>mocodo</code> et ajoutez à votre <code>PATH</code> le chemin du répertoire contenant:</p>\n<ul>\n<li><a href=\"http://www.commentcamarche.net/faq/3585-bash-la-variable-d-environnement-path#v-ajouter-un-repertoire-a-la-variable-path\">sous Linux ou macOS</a> ;</li>\n<li><a href=\"http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/\">sous Windows</a>.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Installation-compl%C3%A8te-(recommand%C3%A9)\">Installation complète (recommandé)<a class=\"anchor-link\" href=\"#Installation-compl%C3%A8te-(recommand%C3%A9)\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<ul>\n<li><p>Installez la <a href=\"https://www.anaconda.com/download\">distribution Anaconda</a>, qui contient Python 3, Jupyter Notebook et bien plus encore.</p>\n</li>\n<li><p>La ligne donnée précédemment installe en fait, en plus de Mocodo, sa « commande magique » pour <a href=\"https://jupyter.org\">Jupyter Notebook</a>. Nous l'avons déjà invoquée plusieurs fois dans ce document :</p>\n<pre><code>  python -m pip install mocodo</code></pre>\n</li>\n<li><p>Mocodo fonctionne parfaitement sans aucune dépendance. Cependant, si vous souhaitez :</p>\n<ul>\n<li>utiliser l'option <code>--svg_to</code> pour générer des figures en PDF ou en PNG ;</li>\n<li>copier directement dans le presse-papier le résultat d'une réécriture ;</li>\n</ul>\n<p>... vous pouvez installer les dépendances optionnelles aux bibliothèques <a href=\"https://cairosvg.org\">CairoSVG</a> et <a href=\"https://github.com/asweigart/pyperclip\">Pyperclip</a> ainsi :</p>\n<pre><code>  python -m pip install 'mocodo[svg,clipboard]'</code></pre>\n</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour mettre la « commande magique » <code>mocodo</code> à disposition d'un <em>notebook</em> donné, évaluez dans celui-ci la cellule suivante:</p>\n<pre><code>%reload_ext mocodo</code></pre>\n<p>Techniquement, <code>%load_ext mocodo</code> suffit, mais cette forme vous épargnera un message d'erreur si vous réévaluez ultérieurement la cellule.</p>\n<p>Pour tester la commande :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [11]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nMISSION: accomplie\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTQiIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCAxMTQgNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTE0IiBoZWlnaHQ9Ijc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgTUlTU0lPTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI5NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTA1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk1JU1NJT048L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWNjb21wbGllPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI4MCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour charger automatiquement <code>mocodo</code> à chaque ouverture d'un notebook (ce qui dispense d'évaluer <code>%load_ext mocodo</code>) :</p>\n<ul>\n<li>exécutez sous un terminal :</li>\n</ul>\n<pre><code>ipython profile create\n</code></pre>\n<ul>\n<li>éditez le fichier créé (p. ex.: <code>~/.ipython/profile_default/ipython_config.py</code>) en remplaçant la ligne suivante :</li>\n</ul>\n<pre><code># c.TerminalIPythonApp.extensions = []\n</code></pre>\n<p>par celle-ci :</p>\n<pre><code>c.InteractiveShellApp.extensions = [\"mocodo\"]\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Utilisation-par-importation\">Utilisation par importation<a class=\"anchor-link\" href=\"#Utilisation-par-importation\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.1.3.</strong> Un <em>wrapper</em> minimaliste permet de simuler programmatiquement l'appel à la commande <code>mocodo</code>.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [12]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">mocodo.api</span> <span class=\"kn\">import</span> <span class=\"n\">mocodo</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ainsi, l'équivalent de :</p>\n<pre><code>mocodo -i ccp --colors mondrian\n</code></pre>\n<p>... s'écrira :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [13]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">messages</span> <span class=\"o\">=</span> <span class=\"n\">mocodo</span><span class=\"p\">(</span><span class=\"s2\">\"-i ccp --colors mondrian\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Par défaut (second argument <code>quiet=True</code>), la fonction n'affiche pas les messages de succès, mais renvoie leur concaténation :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [14]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">messages</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>Fichier de sortie « ~/Dropbox/Sites/mocodo/doc/mocodo_notebook/ccp.svg » généré avec succès.\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Plus important, les fichiers de sortie sont bel bien créés :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [15]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">SVG</span><span class=\"p\">(</span><span class=\"s2\">\"ccp.svg\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[15]:</div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTk0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiBmaWxsPSIjZmVmZWVjIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iIzA4MWE4NCIgc3Ryb2tlPSIjMDgxYTg0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjZmVmZWVjIiBzdHJva2U9IiNmZWZlZWMiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjQiIHgyPSI0MTkiIHkyPSI2NCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzgiIHkxPSI2NCIgeDI9IjQxOSIgeTI9IjY0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg2IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iIzA4MWE4NCIgc3Ryb2tlPSIjMDgxYTg0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDYyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzkwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg2IiBmaWxsPSIjZmVmZWVjIiBzdHJva2U9IiNmZWZlZWMiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3NiIgeT0iMzUiIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM3NiIgeTE9IjYzIiB4Mj0iNDYyIiB5Mj0iNjMiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjU2LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIzODMiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2NyIgeT0iODAiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iODciIHkyPSIzOSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzQ3IiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzOCIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iNjQuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzEiIHkxPSI2NyIgeDI9IjMzOSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjMxIiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDkxIiB5PSI0NyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5MSIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTEiIHkxPSI0NyIgeDI9IjU4NSIgeTI9IjQ3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDIiIHk9IjM4LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iNjQuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0OTkiIHkxPSI2NyIgeDI9IjU3NCIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDk5IiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iOTgiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Si vous travaillez sous une implantation de Jupyter Notebook qui ne prend pas en charge les commandes magiques, l'importation conseillée est :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [16]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">mocodo.magic</span> <span class=\"kn\">import</span> <span class=\"n\">mocodo</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Elle permet de simuler les commandes magiques, aussi bien celles qui sont réduites à une ligne :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [17]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">mocodo</span><span class=\"p\">(</span><span class=\"s2\">\"%mocodo -i ccp --colors ocean\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTk0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMyNzM2MGMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjQiIHgyPSI0MTkiIHkyPSI2NCIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzgiIHkxPSI2NCIgeDI9IjQxOSIgeTI9IjY0IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg2IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDYyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzkwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg2IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3NiIgeT0iMzUiIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM3NiIgeTE9IjYzIiB4Mj0iNDYyIiB5Mj0iNjMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjU2LjMiIGZpbGw9IiMyNzM2MGMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIzODMiIHk9IjgxLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2NyIgeT0iODAiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iODciIHkyPSIzOSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzQ3IiB5Mj0iNDciIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzOCIgeT0iMzguMyIgZmlsbD0iIzEzMTExNCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iNjQuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzEiIHkxPSI2NyIgeDI9IjMzOSIgeTI9IjY3IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjMxIiB5PSI4MS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI5OCIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDkxIiB5PSI0NyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5MSIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTEiIHkxPSI0NyIgeDI9IjU4NSIgeTI9IjQ3IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDIiIHk9IjM4LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iNjQuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0OTkiIHkxPSI2NyIgeDI9IjU3NCIgeTI9IjY3IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDk5IiB5PSI4MS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iOTgiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>... que celles qui portent sur toute une cellule :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [18]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">mocodo</span><span class=\"p\">(</span><span class=\"s2\">\"\"\"</span>\n<span class=\"si\">%%</span><span class=\"s2\">mocodo --colors pond</span>\n<span class=\"s2\">Mission: accomplie</span>\n<span class=\"s2\">\"\"\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDYiIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCAxMDYgNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTA2IiBoZWlnaHQ9Ijc4IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgTUlTU0lPTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTciIHkyPSIzOSIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TWlzc2lvbjwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hY2NvbXBsaWU8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjgwIiB5Mj0iNTkiIHN0cm9rZT0iIzFiNTM0MyIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le préfixe <code>\"%mocodo\"</code> ou <code>\"%%mocodo\"</code> est ignoré, mais l'autoriser permet de copier toute une ligne ou toute une cellule (vraiment) magique, et de la coller directement comme argument de la fonction.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.2.</strong> Avec cette technique, Mocodo peut être utilisé sous <a href=\"https://basthon.fr\">Basthon</a> v. 0.62.12 ou ultérieure. Basthon est une plateforme permettant de travailler sous Jupyter Notebook sans avoir à rien installer. Son auteur, Romain Casati, a ajouté un exemple d'utilisation de Mocodo dans la <a href=\"https://basthon.fr/galerie.html\">galerie</a> du logiciel, à tester <a href=\"https://notebook.basthon.fr/?from=examples/python3-mocodo.ipynb\">ici</a>. Sous Mocodo <em>online</em>, cliquez sur le symbole de lecture de Basthon (dans le pied de page) pour ouvrir un notebook avec le MCD en cours d'édition.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Syntaxe-de-description-d'un-MCD\">Syntaxe de description d'un MCD<a class=\"anchor-link\" href=\"#Syntaxe-de-description-d'un-MCD\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Notions-%C3%A9l%C3%A9mentaires\">Notions élémentaires<a class=\"anchor-link\" href=\"#Notions-%C3%A9l%C3%A9mentaires\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Entit%C3%A9s,-associations,-attributs,-identifiants,-cardinalit%C3%A9s\">Entités, associations, attributs, identifiants, cardinalités<a class=\"anchor-link\" href=\"#Entit%C3%A9s,-associations,-attributs,-identifiants,-cardinalit%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [19]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: Réf. client, Nom, Prénom, Adresse\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjMwIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSIxNjYiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDIiIHkxPSI2NCIgeDI9IjE2NiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5NiAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjEwIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iMzUiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjYzIiB4Mj0iMjEwIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjkiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTYiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMzAyIiB5MT0iNjQiIHgyPSI0NDMiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NzEiIHkxPSI2NCIgeDI9IjQ0MyIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ3OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTk4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDkyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDA4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM5NCIgeT0iMzUiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM5NCIgeTE9IjYzIiB4Mj0iNDkyIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0MDIiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSI0MDEiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM3MCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ5NyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0xJRU5UPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIzOSIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjM5IiB5PSI0NyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzkiIHk9IjE3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIzOSIgeTE9IjQ3IiB4Mj0iMzY1IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI0OCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01NQU5ERTwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyNDciIHkxPSI2NyIgeDI9IjM1NSIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjQ3IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjQ3IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1MjEiIHk9IjE3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUyMSIgeT0iNDciIHdpZHRoPSIxMDAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTIxIiB5PSIxNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1MjEiIHkxPSI0NyIgeDI9IjYyMSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MzAiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPRFVJVDwvdGV4dD4KCTx0ZXh0IHg9IjUyOSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI1MjkiIHkxPSI2NyIgeDI9IjYwNCIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTI5IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjUyOSIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Passons en revue les principes de la syntaxe. Ils ne devraient pas poser trop de problèmes.</p>\n<p><strong>La première ligne</strong> ne fait pas partie de la définition du MCD. Sous Jupyter Notebook, elle dénote l'appel à une « commande magique », qui lance Mocodo sur le reste de la cellule. En dehors d'un notebook, vous n'en avez pas besoin, et toute ligne commençant par un pourcentage (<code>%</code>) sera considérée comme un commentaire.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Une entité</strong> est définie par :</p>\n<p>$$\n\\overbrace{\\texttt{COMMANDE}}^{\\text{son nom}}\n\\quad\n\\overbrace{\\texttt{:}}^{\\text{deux-points}}\n\\quad\n\\overbrace{\\texttt{Num. commande, Date, Montant}}^{\\text{ses attributs séparés par des virgules}}\n$$</p>\n<p>Notez que le premier attribut d'une entité est considéré par défaut comme son identifiant, et donc souligné.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Une association</strong> est définie par :</p>\n<p>$$\n\\overbrace{\\texttt{INCLURE}}^{\\text{son nom}}\n\\quad\n\\overbrace{\\texttt{,}}^{\\text{une virgule}}\n\\quad\n\\overbrace{\n    \\underbrace{\\texttt{1N}}_{\\text{cardinalités}}\n    \\underbrace{\\texttt{COMMANDE}}_{\\text{entité}}\n    \\quad\n    ,\n    \\quad\n    \\underbrace{\\texttt{0N}}_{\\text{cardinalités}}\n    \\underbrace{\\texttt{PRODUIT}}_{\\text{entité}}\n}^{\\text{ses pattes séparées par des virgules}}\n\\quad\n\\overbrace{\\texttt{:}}^{\\text{deux-points}}\n\\quad\n\\overbrace{\\texttt{Quantité}}^{\\text{ses attributs séparés par des virgules}}\n$$</p>\n<p>Notez que pour les associations sans attributs (comme PASSER), le deux-points est facultatif.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Astuce.</strong> Si vous recopiez un MCD ou que vous l'avez bien en tête, commencez par les associations et, à tout moment, faites apparaître les entités manquantes (double clic sur le lapin magique sous Mocodo online). Elles auront comme identifiant le nom de l'entité en minuscules, par défaut précédé de « id. » (sauf pour les entités DATE et PÉRIODE). Vous n'aurez plus qu'à remplir les autres attributs :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [20]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t guess:entities\nRéserver, 1N Client, 1N Chambre, 0N Date: Durée\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTIiIGhlaWdodD0iMTc2IiB2aWV3Qm94PSIwIDAgMzEyIDE3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTIiIGhlaWdodD0iMTc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNDgiIHkxPSIxMjkiIHgyPSIxNjUiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNjUiIHkxPSIxMjkiIHgyPSIxNjUiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNzMiIHkxPSIxMjkiIHgyPSIxNjUiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMDEgOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzNyBoLTEwMCBWMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIxNSAzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDEyOSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjM3IEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTE1IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTE1IiB5MT0iMzciIHgyPSIyMTUiIHkyPSIzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEyMiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6lzZXJ2ZXI8L3RleHQ+CgkJPHRleHQgeD0iMTIyIiB5PSI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EdXLDqWU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI5MiIgeT0iMTA4Ljg0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIxNzAiIHk9IjgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTkiIHk9IjExMy41IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5MSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjEyMSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkxIiB3aWR0aD0iNzgiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjEyMSIgeDI9Ijg3IiB5Mj0iMTIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMTEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMTQxIiB4Mj0iNzAiIHkyPSIxNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IENIQU1CUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTE2IiB5PSI5MSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMTIxIiB3aWR0aD0iOTgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTE2IiB5PSI5MSIgd2lkdGg9Ijk4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjEyMSIgeDI9IjIxNCIgeTI9IjEyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTI1IiB5PSIxMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DaGFtYnJlPC90ZXh0PgoJPHRleHQgeD0iMTI0IiB5PSIxMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGNoYW1icmU8L3RleHQ+Cgk8bGluZSB4MT0iMTI0IiB5MT0iMTQxIiB4Mj0iMTk3IiB5Mj0iMTQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBEQVRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI0MyIgeT0iOTkiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNDMiIHk9IjEyOSIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0MyIgeT0iOTkiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNDMiIHkxPSIxMjkiIHgyPSIzMDMiIHkyPSIxMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI1MiIgeT0iMTIwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjI1MSIgeT0iMTQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8bGluZSB4MT0iMjUxIiB5MT0iMTQ5IiB4Mj0iMjc5IiB5Mj0iMTQ5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo \nRéserver, 1N Client, 1N Chambre, 0N Date: Durée\n\nClient: id. client, \nChambre: id. chambre, \nDate: date\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9pendances-fonctionnelles-entre-entit%C3%A9s\">Dépendances fonctionnelles entre entités<a class=\"anchor-link\" href=\"#D%C3%A9pendances-fonctionnelles-entre-entit%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Lorsque l'une des cardinalités maximales d'une association binaire est 1 (ou quelquefois 0), on désigne cette association sous le nom de <strong>dépendance fonctionnelle</strong>. On la figure souvent par un cercle portant le symbole DF : cela évite de se creuser la tête pour trouver un nom à une association qui (<em>spoiler</em>) disparaîtra corps et biens au moment du passage au relationnel.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [21]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: Réf. client, Nom, Prénom, Adresse\nDF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1ODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTgyIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1ODIiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSIxNDIiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNTQiIHkxPSI2NCIgeDI9IjE0MiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTQyIiBjeT0iNjQiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTI5IiB5PSI2OC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxNjgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjU0IiB5MT0iNjQiIHgyPSIzOTUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MjMiIHkxPSI2NCIgeDI9IjM5NSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQzMCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTk4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDQ0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzYwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM0NiIgeT0iMzUiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM0NiIgeTE9IjYzIiB4Mj0iNDQ0IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzNTQiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSIzNTMiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMyMiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ0OSIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0xJRU5UPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE5MSIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTkxIiB5PSI0NyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOTEiIHk9IjE3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE5MSIgeTE9IjQ3IiB4Mj0iMzE3IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIwMCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01NQU5ERTwvdGV4dD4KCTx0ZXh0IHg9IjE5OSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIxOTkiIHkxPSI2NyIgeDI9IjMwNyIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTk5IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMTk5IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0NzMiIHk9IjE3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ3MyIgeT0iNDciIHdpZHRoPSIxMDAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDczIiB5PSIxNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0NzMiIHkxPSI0NyIgeDI9IjU3MyIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0ODIiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPRFVJVDwvdGV4dD4KCTx0ZXh0IHg9IjQ4MSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0ODEiIHkxPSI2NyIgeDI9IjU1NiIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDgxIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ4MSIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Associations-r%C3%A9flexives\">Associations réflexives<a class=\"anchor-link\" href=\"#Associations-r%C3%A9flexives\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Quelquefois appelées <strong>circulaires</strong>, <strong>unaires</strong> ou <strong>récursives</strong>, elles associent une entité à elle-même. Voici par exemple une représentation des filiations patrilinéaires (le 01 permet d'« arrêter » la remontée des ancêtres) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [22]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nHOMME: Num. SS, Nom, Prénom\nENGENDRER, 0N HOMME, 01 HOMME\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNjciIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMjY3IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyNjciIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTkdFTkRSRVIgLS0+CjxnPgoJPHBhdGggZD0iTTUzIDU2IEM4NC42NyAyNCAxMzEgMjQgMTkyIDU2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTUzIDU2IEM4NCA4OCAxMzAuMzMgODggMTkyIDU2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI0NCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTEzMiBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI1OCA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE0MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxMzIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTI2IiB5PSIyNyIgd2lkdGg9IjEzMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyNiIgeTE9IjU1IiB4Mj0iMjU4IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMzQiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RU5HRU5EUkVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTAyIiB5PSI0OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMTAyIiB5PSI3MSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBIT01NRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SE9NTUU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBTUzwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByw6lub208L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Identifiants-composites\">Identifiants composites<a class=\"anchor-link\" href=\"#Identifiants-composites\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Préfixez d'un tiret bas (<code>_</code>) les second, troisième, etc. attributs pour les inclure dans l'identifiant.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [23]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nGRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNzQiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgMTc0IDE0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNzQiIGhlaWdodD0iMTQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgR1JBVFRFX0NJRUwgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjE1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjE1NiIgaGVpZ2h0PSI5OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTU2IiBoZWlnaHQ9IjEyOCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxNjUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+R1JBVFRFLUNJRUw8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGF0aXR1ZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjY0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bG9uZ2l0dWRlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNzYiIHgyPSI3NSIgeTI9Ijc2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhhdXRldXI8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTI0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hbm7DqWUgZGUgY29uc3RydWN0aW9uPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Fl%C3%A8ches-sur-les-pattes\">Flèches sur les pattes<a class=\"anchor-link\" href=\"#Fl%C3%A8ches-sur-les-pattes\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Suffixez d'un chevron (<code>&lt;</code> ou <code>&gt;</code>) les cardinalités de la patte concernée. La direction indiquée se lit en partant de l'association et en allant vers l'entité.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [24]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nPeut recevoir, 1N&gt; Groupe sanguin, 1N&lt; Groupe sanguin\nGroupe sanguin: type de sang\nAppartient, 11&gt; Personne, 0N Groupe sanguin\nPersonne: Num. SS, Nom, Prénom, Sexe\nEngendre, 0N&lt; Personne, 22&gt; Personne\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NjIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNzYyIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3NjIiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQRVVUX1JFQ0VWT0lSIC0tPgo8Zz4KCTxwYXRoIGQ9Ik0yNjEgNjQgQzE5NCA5NiAxMzMuNjcgOTYgODAgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjE4MC4wIDg3LjM5IDE2OC41MyA5NC4zNiAxNzIuMDMgODguMDUgMTY3LjU0IDgyLjQxIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxwYXRoIGQ9Ik0yNjEgNjQgQzE5NCAzMiAxMzMuNjcgMzIgODAgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjE1MC45OSA0MC42MyAxNjIuNDMgMzMuNjEgMTU4Ljk2IDM5LjkzIDE2My40NyA0NS41NiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTM3IDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtMTQyIFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTUxIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjMgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIMTQyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjkiIHk9IjM1IiB3aWR0aD0iMTQyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjYzIiB4Mj0iMTUxIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNiIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QZXV0IHJlY2V2b2lyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTU2IiB5PSI3OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTU2IiB5PSI1NyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEFQUEFSVElFTlQgLS0+CjxnPgoJPGxpbmUgeDE9IjU2NyIgeTE9IjY0IiB4Mj0iNDI4IiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjUxNCA2NCA1MDIgNzAgNTA2IDY0IDUwMiA1OCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMjYxIiB5MT0iNjQiIHgyPSI0MjgiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NzEgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC0xMTQgVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik00ODUgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzODUgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIMTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3MSIgeT0iMzUiIHdpZHRoPSIxMTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzNzEiIHkxPSI2MyIgeDI9IjQ4NSIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzc4IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFwcGFydGllbnQ8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0OTEiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIzNDciIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRU5HRU5EUkUgLS0+CjxnPgoJPHBhdGggZD0iTTU2NyA2NCBDNjEyLjMzIDMyIDY1NyAzMiA3MDEgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjY0OC45OSA0MS4xMyA2MzYuMjEgNDUuMjEgNjQxLjA5IDM5LjkgNjM4LjA2IDMzLjM1IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxwYXRoIGQ9Ik01NjcgNjQgQzYxMS42NyA5NiA2NTYuMzMgOTYgNzAxIDY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSI2MjAuMDEgODYuOTUgNjMyLjc2IDgyLjc5IDYyNy45MiA4OC4xNCA2MzAuOTkgOTQuNjYiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGc+CgkJPHBhdGggZD0iTTczOSAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTEwNCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTc1MyA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDY2MyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNjQ5IiB5PSIzNSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjY0OSIgeTE9IjYzIiB4Mj0iNzUzIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI2NTYiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW5nZW5kcmU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2MjUiIHk9IjU3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSI2MjUiIHk9Ijc5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4yLDI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEdST1VQRV9TQU5HVUlOIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE4MCIgeT0iMzQiIHdpZHRoPSIxNjIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgwIiB5PSI2NCIgd2lkdGg9IjE2MiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxODAiIHk9IjM0IiB3aWR0aD0iMTYyIiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE4MCIgeTE9IjY0IiB4Mj0iMzQyIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4OCIgeT0iNTUuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Hcm91cGUgc2FuZ3VpbjwvdGV4dD4KCTx0ZXh0IHg9IjE4OCIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dHlwZSBkZSBzYW5nPC90ZXh0PgoJPGxpbmUgeDE9IjE4OCIgeTE9Ijg0IiB4Mj0iMjY2IiB5Mj0iODQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFBFUlNPTk5FIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUxNCIgeT0iOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MTQiIHk9IjM5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUxNCIgeT0iOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTE0IiB5MT0iMzkiIHgyPSI2MjAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTIzIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBlcnNvbm5lPC90ZXh0PgoJPHRleHQgeD0iNTIyIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIFNTPC90ZXh0PgoJPGxpbmUgeDE9IjUyMiIgeTE9IjU5IiB4Mj0iNTc2IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1MjIiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjUyMiIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjUyMiIgeT0iMTA3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5TZXhlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Types-de-donn%C3%A9es\">Types de données<a class=\"anchor-link\" href=\"#Types-de-donn%C3%A9es\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme on l'a vu dans l'introduction, chaque attribut peut être assorti d'un type entre crochets, qui servira lors de la conversion en SQL. À partir de la version 4.0, Mocodo est capable de deviner le type des attributs usuels à partir de leur nom :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [25]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t guess:types data_dict --select cv\nCLIENT: Réf. client, Nom, Prénom, Adresse\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_data_dict_3.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Entité ou association</th>\n<th style=\"text-align:left\">Libellé de l'attribut</th>\n<th style=\"text-align:left\">Type</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">CLIENT</td>\n<td style=\"text-align:left\">Adresse</td>\n<td style=\"text-align:left\">VARCHAR(30)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Nom</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Prénom</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Réf. client</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">COMMANDE</td>\n<td style=\"text-align:left\">Date</td>\n<td style=\"text-align:left\">DATE</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Montant</td>\n<td style=\"text-align:left\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Num. commande</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">INCLURE</td>\n<td style=\"text-align:left\">Quantité</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PRODUIT</td>\n<td style=\"text-align:left\">Libellé</td>\n<td style=\"text-align:left\">VARCHAR(50)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Prix unitaire</td>\n<td style=\"text-align:left\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">Réf. produit</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.3.</strong> Avec l'option <code>-t prompt:types</code>, Mocodo compose un <em>prompt</em> à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec les types manquants. Ce <em>prompt</em> est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les types générés par <a href=\"https://claude.ai/chat/d4fb8fa7-fb68-43ae-b255-fa10dcc5cb84\">Claude 3.5 Haiku</a> pour le MCD de la page d'accueil de Mocodo online :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [26]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t data_dict\nAYANT-DROIT: nom ayant-droit [VARCHAR(100)], lien [VARCHAR(50)]\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise [INTEGER]\nPIÈCE: réf. pièce [VARCHAR(20)], libellé pièce [VARCHAR(255)]\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité [INTEGER]\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule [VARCHAR(20)], nom employé [VARCHAR(100)]\nPROJET: num. projet [VARCHAR(20)], nom projet [VARCHAR(255)]\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie [INTEGER]\n\nDÉPARTEMENT: num. département [VARCHAR(20)], nom département [VARCHAR(100)]\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société [VARCHAR(20)], raison sociale [VARCHAR(255)]\nCONTRÔLER, 0N&lt; [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_data_dict_3.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Entité ou association</th>\n<th style=\"text-align:left\">Libellé de l'attribut</th>\n<th style=\"text-align:left\">Type</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">AYANT-DROIT</td>\n<td style=\"text-align:left\">lien</td>\n<td style=\"text-align:left\">VARCHAR(50)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">nom ayant-droit</td>\n<td style=\"text-align:left\">VARCHAR(100)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">COMPOSER</td>\n<td style=\"text-align:left\">quantité</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">DÉPARTEMENT</td>\n<td style=\"text-align:left\">nom département</td>\n<td style=\"text-align:left\">VARCHAR(100)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">num. département</td>\n<td style=\"text-align:left\">VARCHAR(20)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">EMPLOYÉ</td>\n<td style=\"text-align:left\">matricule</td>\n<td style=\"text-align:left\">VARCHAR(20)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">nom employé</td>\n<td style=\"text-align:left\">VARCHAR(100)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">FOURNIR</td>\n<td style=\"text-align:left\">qté fournie</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PIÈCE</td>\n<td style=\"text-align:left\">libellé pièce</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">réf. pièce</td>\n<td style=\"text-align:left\">VARCHAR(20)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PROJET</td>\n<td style=\"text-align:left\">nom projet</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">num. projet</td>\n<td style=\"text-align:left\">VARCHAR(20)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">REQUÉRIR</td>\n<td style=\"text-align:left\">qté requise</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">SOCIÉTÉ</td>\n<td style=\"text-align:left\">num. société</td>\n<td style=\"text-align:left\">VARCHAR(20)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">raison sociale</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ce problème d'inférence n'est pas très difficile pour une IA. Les résultats devraient être très bons, surtout en comparaison de ceux de la version purement algorithmique, qui sont généralement incomplets :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [27]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t guess:types data_dict --select cv\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N&lt; [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_data_dict_3.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Entité ou association</th>\n<th style=\"text-align:left\">Libellé de l'attribut</th>\n<th style=\"text-align:left\">Type</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">AYANT-DROIT</td>\n<td style=\"text-align:left\">lien</td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">nom ayant-droit</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">COMPOSER</td>\n<td style=\"text-align:left\">quantité</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">DÉPARTEMENT</td>\n<td style=\"text-align:left\">nom département</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">num. département</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">EMPLOYÉ</td>\n<td style=\"text-align:left\">matricule</td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">nom employé</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">FOURNIR</td>\n<td style=\"text-align:left\">qté fournie</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PIÈCE</td>\n<td style=\"text-align:left\">libellé pièce</td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">réf. pièce</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PROJET</td>\n<td style=\"text-align:left\">nom projet</td>\n<td style=\"text-align:left\">VARCHAR(255)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">num. projet</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">REQUÉRIR</td>\n<td style=\"text-align:left\">qté requise</td>\n<td style=\"text-align:left\">INTEGER</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">SOCIÉTÉ</td>\n<td style=\"text-align:left\">num. société</td>\n<td style=\"text-align:left\">VARCHAR(8)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">\"</td>\n<td style=\"text-align:left\">raison sociale</td>\n<td style=\"text-align:left\"></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Trac%C3%A9-d'un-MCD%C2%A0:-principes\">Tracé d'un MCD : principes<a class=\"anchor-link\" href=\"#Trac%C3%A9-d'un-MCD%C2%A0:-principes\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo combine les avantages de l'approche <em>diagram as code</em> (comme PlantUML, Mermaid ou Graphviz), avec la liberté de positionnement offerte par les logiciels WYSIWYG (<em>what you see is what you get</em>).</p>\n<p>Sa grande originalité est de se baser sur l'ordre et la séparation des lignes de la description pour définir une mise en page qui se révèle suffisante dans la majorité des cas.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Le-pont-aux-%C3%A2nes-du-langage-Mocodo\">Le pont aux ânes du langage Mocodo<a class=\"anchor-link\" href=\"#Le-pont-aux-%C3%A2nes-du-langage-Mocodo\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Premier principe : les boîtes (entités et associations) définies sur des <strong>lignes consécutives</strong> sont tracées sur <strong>une seule rangée</strong>.</p>\n<p>Si l'on écrit les définitions sur des lignes consécutives, on se retrouve donc vite avec des chevauchements qui ne sautent pas forcément aux yeux :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [28]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: Réf. client, Nom, Prénom, Adresse\nCOMMANDE: Num. commande, Date, Montant\nPRODUIT: Réf. produit, Libellé, Prix unitaire\nPASSER, 0N CLIENT, 11 COMMANDE\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjMwIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSI0NTAiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxODUiIHkxPSI2NCIgeDI9IjQ1MCIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDIwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQwNiIgeT0iMzUiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQwNiIgeTE9IjYzIiB4Mj0iNDk0IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0MTMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyNTMiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMTg1IiB5MT0iNjQiIHgyPSI1NzIiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMjciIHkxPSI2NCIgeDI9IjU3MiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTYwNyAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTk4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNjIxIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINTM3IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjUyMyIgeT0iMzUiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjUyMyIgeTE9IjYzIiB4Mj0iNjIxIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI1MzEiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSI1MzAiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI1MyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM4MiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0xJRU5UPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEyMiIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTIyIiB5PSI0NyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMjIiIHk9IjE3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjQ3IiB4Mj0iMjQ4IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEzMSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01NQU5ERTwvdGV4dD4KCTx0ZXh0IHg9IjEzMCIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIxMzAiIHkxPSI2NyIgeDI9IjIzOCIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTMwIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMTMwIiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNzciIHk9IjE3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI3NyIgeT0iNDciIHdpZHRoPSIxMDAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc3IiB5PSIxNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNzciIHkxPSI0NyIgeDI9IjM3NyIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyODYiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPRFVJVDwvdGV4dD4KCTx0ZXh0IHg9IjI4NSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NyIgeDI9IjM2MCIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjg1IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjI4NSIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'option <code>--detect_overlaps</code> (active par défaut sous Mocodo online) signale le problème et donne la solution :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [29]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --detect_overlaps\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.29 - Mauvaise disposition des boîtes :\n  - La patte « INCLURE — COMMANDE » chevauche « PRODUIT ».\n  - La patte « INCLURE — PRODUIT » chevauche « PASSER ».\n  - La patte « PASSER — CLIENT » chevauche « COMMANDE ».\n  - Les pattes  « PASSER — COMMANDE » et « INCLURE — COMMANDE » se chevauchent.\nPour corriger cela, réordonnez et/ou sautez des lignes dans le texte-source, soit à la\nmain, soit à l'aide de l'option -t arrange (tablette de chocolat sous Mocodo online).</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Limitation.</strong> Seuls les chevauchements mettant en jeu des pattes horizontales ou verticales sont détectés.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"MCD-sur-plusieurs-lignes\">MCD sur plusieurs lignes<a class=\"anchor-link\" href=\"#MCD-sur-plusieurs-lignes\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Deuxième principe : pour commencer une nouvelle rangée, il faut sauter une ligne :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [30]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nSCELERISQUE LOREM: blandit, elit, ligula\nEROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue\n\nNIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM\nPELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTUiIGhlaWdodD0iMjQ2IiB2aWV3Qm94PSIwIDAgNDE1IDI0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTUiIGhlaWdodD0iMjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFUk9TIC0tPgo8Zz4KCTxsaW5lIHgxPSIxMTgiIHkxPSI1NiIgeDI9IjI5MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI5MiIgeTE9IjE4MiIgeDI9IjI5MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTMxMSAxOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY0NyBoLTY2IFYzMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzI1IDQ3IHYzMiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjczIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDcgSDY2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI1OSIgeT0iMTkiIHdpZHRoPSI2NiIgaGVpZ2h0PSI3NCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI1OSIgeTE9IjQ3IiB4Mj0iMzI1IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyNjYiIHk9IjQwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RVJPUzwvdGV4dD4KCQk8dGV4dCB4PSIyNjYiIHk9IjY1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm1ldHVzPC90ZXh0PgoJCTx0ZXh0IHg9IjI2NiIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y29uZ3VlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjMyIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMjk3IiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBOSUJIIC0tPgo8Zz4KCTxsaW5lIHgxPSIxMTgiIHkxPSI1NiIgeDI9IjExOCIgeTI9IjE4MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyOTIiIHkxPSIxODIiIHgyPSIxMTgiIHkyPSIxODIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTM1IDE1MyBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxODEgaC02MiBWMTY3IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0xNDkgMTgxIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTAxIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTgxIEg2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI4NyIgeT0iMTUzIiB3aWR0aD0iNjIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI4NyIgeTE9IjE4MSIgeDI9IjE0OSIgeTI9IjE4MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9Ijk0IiB5PSIxNzQuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5OSUJIPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTIzIiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjE1NSIgeT0iMTk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNDRUxFUklTUVVFX0xPUkVNIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIyMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIyMTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjIxOCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIyMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U0NFTEVSSVNRVUUgTE9SRU08L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YmxhbmRpdDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNTkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5lbGl0PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWd1bGE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBFTExFTlRFU1FVRV9JUFNVTSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNzgiIHk9IjEyNyIgd2lkdGg9IjIyOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNzgiIHk9IjE1NyIgd2lkdGg9IjIyOCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNzgiIHk9IjEyNyIgd2lkdGg9IjIyOCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTc4IiB5MT0iMTU3IiB4Mj0iNDA2IiB5Mj0iMTU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODciIHk9IjE0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBFTExFTlRFU1FVRSBJUFNVTTwvdGV4dD4KCTx0ZXh0IHg9IjE4NiIgeT0iMTc0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnRpbmNpZHVudDwvdGV4dD4KCTxsaW5lIHgxPSIxODYiIHkxPSIxNzciIHgyPSIyNDEiIHkyPSIxNzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxODYiIHk9IjE5MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5iaWJlbmR1bTwvdGV4dD4KCTx0ZXh0IHg9IjE4NiIgeT0iMjA4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbnNlcXVhdDwvdGV4dD4KCTx0ZXh0IHg9IjE4NiIgeT0iMjI1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pbnRlZ2VyPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les centres des boîtes sont placés aux intersections d'une grille invisible. Ils sont donc alignés aussi bien horizontalement que verticalement. De plus, dans un but esthétique, le dessin fait l'objet d'une compression dans les deux dimensions. Par exemple, ci-dessus, un espace horizontal négatif a été créé entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Mise-en-miroir\">Mise en miroir<a class=\"anchor-link\" href=\"#Mise-en-miroir\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo permet de calculer facilement les symétriques d'un MCD :</p>\n<ul>\n<li>verticalement : <code>-t flip:v</code> ;</li>\n<li>horizontalement : <code>-t flip:h</code> ;</li>\n<li>selon la seconde diagonale (transposition) : <code>-t flip:d</code>.</li>\n<li>selon la première diagonale (transposition) : <code>-t flip:vhd</code>.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [31]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --select mcd -t flip:h\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTUiIGhlaWdodD0iMjQ2IiB2aWV3Qm94PSIwIDAgNDE1IDI0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTUiIGhlaWdodD0iMjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFUk9TIC0tPgo8Zz4KCTxsaW5lIHgxPSIyOTciIHkxPSI1NiIgeDI9IjEyMyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjEyMyIgeTE9IjE4MiIgeDI9IjEyMyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE0MiAxOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY0NyBoLTY2IFYzMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTU2IDQ3IHYzMiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTA0IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDcgSDY2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjkwIiB5PSIxOSIgd2lkdGg9IjY2IiBoZWlnaHQ9Ijc0IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOTAiIHkxPSI0NyIgeDI9IjE1NiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iOTciIHk9IjQwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RVJPUzwvdGV4dD4KCQk8dGV4dCB4PSI5NyIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bWV0dXM8L3RleHQ+CgkJPHRleHQgeD0iOTciIHk9IjgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbmd1ZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE2NSIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjEyOCIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gTklCSCAtLT4KPGc+Cgk8bGluZSB4MT0iMjk3IiB5MT0iNTYiIHgyPSIyOTciIHkyPSIxODIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMTIzIiB5MT0iMTgyIiB4Mj0iMjk3IiB5Mj0iMTgyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTMxNCAxNTMgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTgxIGgtNjIgVjE2NyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzI4IDE4MSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDI4MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE4MSBINjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjY2IiB5PSIxNTMiIHdpZHRoPSI2MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI2NiIgeTE9IjE4MSIgeDI9IjMyOCIgeTI9IjE4MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjI3MyIgeT0iMTc0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TklCSDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMwMiIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDIiIHk9IjE5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTQ0VMRVJJU1FVRV9MT1JFTSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxODgiIHk9IjkiIHdpZHRoPSIyMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTg4IiB5PSIzOSIgd2lkdGg9IjIxOCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxODgiIHk9IjkiIHdpZHRoPSIyMTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTg4IiB5MT0iMzkiIHgyPSI0MDYiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTk2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNDRUxFUklTUVVFIExPUkVNPC90ZXh0PgoJPHRleHQgeD0iMTk2IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ibGFuZGl0PC90ZXh0PgoJPGxpbmUgeDE9IjE5NiIgeTE9IjU5IiB4Mj0iMjM4IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxOTYiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmVsaXQ8L3RleHQ+Cgk8dGV4dCB4PSIxOTYiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWd1bGE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBFTExFTlRFU1FVRV9JUFNVTSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIxMjciIHdpZHRoPSIyMjgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTU3IiB3aWR0aD0iMjI4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjEyNyIgd2lkdGg9IjIyOCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjE1NyIgeDI9IjIzNyIgeTI9IjE1NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjE0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBFTExFTlRFU1FVRSBJUFNVTTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGluY2lkdW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMTc3IiB4Mj0iNzIiIHkyPSIxNzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMTkxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmJpYmVuZHVtPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjIwOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb25zZXF1YXQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMjI1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pbnRlZ2VyPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Corrections de la version 4.0.</strong></p>\n<ul>\n<li>Les sens de « horizontal » et « vertical » sont permutés pour être plus conformes à l'intuition.</li>\n<li>La documentation parlait de première diagonale, c'était la seconde, et vice-versa.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Astuce.</strong> Transposez le MCD  temporairement pour réaliser plus facilement certaines opérations d'édition en colonne, en particulier sous Mocodo online.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Insertion-d'espacements\">Insertion d'espacements<a class=\"anchor-link\" href=\"#Insertion-d'espacements\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Ce comportement n'est pas toujours idéal :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [32]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> \nUltrices, 01 Aliquet, 0N Aliquet\nAliquet: hendrerit, metus, lacus, quis\nRisus, 1N Aliquet, 0N Massa\nMassa: metus, posuere\nEuismod, 0N Massa, 0N Massa\n\nConvallis, 0N Aliquet, 0N Ante: vestibulum\nTincidunt, 11 Ante, 0N Massa\n\nGravida: ornare\nRutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae\nAnte: vitae, tempor\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1NzkiIGhlaWdodD0iMzEwIiB2aWV3Qm94PSIwIDAgNTc5IDMxMCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1NzkiIGhlaWdodD0iMzEwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBVTFRSSUNFUyAtLT4KPGc+Cgk8cGF0aCBkPSJNMTc2IDY0IEMxMzguNjcgOTYgOTguNjcgOTYgNTYgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cGF0aCBkPSJNMTc2IDY0IEMxMzggMzIgOTggMzIgNTYgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNODkgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05NCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTEwMyA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIzIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjkiIHk9IjM1IiB3aWR0aD0iOTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iNjMiIHgyPSIxMDMiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE2IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlVsdHJpY2VzPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA5IiB5PSI3OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCwxPC90ZXh0PgoJPHRleHQgeD0iMTA4IiB5PSI1NyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJJU1VTIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNzYiIHkxPSI2NCIgeDI9IjMxMSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQxNSIgeTE9IjY0IiB4Mj0iMzExIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMzMwIDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtNjYgVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zNDQgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyOTIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBINjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjc4IiB5PSIzNSIgd2lkdGg9IjY2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMjc4IiB5MT0iNjMiIHgyPSIzNDQiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjI4NSIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SaXN1czwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIyNSIgeT0iNTYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM1NSIgeT0iNTYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBFVUlTTU9EIC0tPgo8Zz4KCTxwYXRoIGQ9Ik00MTUgNjQgQzQ0NS42NyAzMiA0ODIuMzMgMzIgNTI1IDY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTQxNSA2NCBDNDQ1LjY3IDk2IDQ4Mi4zMyA5NiA1MjUgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNTU2IDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtOTAgVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01NzAgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0OTQgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIOTAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDgwIiB5PSIzNSIgd2lkdGg9IjkwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNDgwIiB5MT0iNjMiIHgyPSI1NzAiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQ4NyIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FdWlzbW9kPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDU2IiB5PSI1OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDU2IiB5PSI3OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlZBTExJUyAtLT4KPGc+Cgk8bGluZSB4MT0iMTc2IiB5MT0iNjQiIHgyPSIxNzYiIHkyPSIxNzIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNDE1IiB5MT0iMjYzIiB4Mj0iMTc2IiB5Mj0iMTcyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIxNiAxNDMgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTcxIGgtMTA4IFYxNTcgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIzMCAxNzEgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMzYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNzEgSDEwOCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMjIiIHk9IjE0MyIgd2lkdGg9IjEwOCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjE3MSIgeDI9IjIzMCIgeTI9IjE3MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEzMCIgeT0iMTY0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29udmFsbGlzPC90ZXh0PgoJCTx0ZXh0IHg9IjEyOSIgeT0iMTg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnZlc3RpYnVsdW08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNTIiIHk9IjEzNSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMzU5IiB5PSIyNjMuODQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBUSU5DSURVTlQgLS0+CjxnPgoJPGxpbmUgeDE9IjQxNSIgeTE9IjI2MyIgeDI9IjMxMSIgeTI9IjE3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0MTUiIHkxPSI2NCIgeDI9IjMxMSIgeTI9IjE3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zNDkgMTQzIGExNCAxNCA5MCAwIDEgMTQgMTQgVjE3MSBoLTEwNCBWMTU3IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zNjMgMTcxIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjczIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTcxIEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjU5IiB5PSIxNDMiIHdpZHRoPSIxMDQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyNTkiIHkxPSIxNzEiIHgyPSIzNjMiIHkyPSIxNzEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyNjYiIHk9IjE2NC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRpbmNpZHVudDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM2MCIgeT0iMjQ0LjU5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIzNTUiIHk9IjEwMC4yNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJVVFJVTSAtLT4KPGc+Cgk8bGluZSB4MT0iMTc2IiB5MT0iMjYzIiB4Mj0iMzExIiB5Mj0iMjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQxNSIgeTE9IjI2MyIgeDI9IjMxMSIgeTI9IjI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNzYiIHkxPSI2NCIgeDI9IjMxMSIgeTI9IjI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zNDAgMjI2IGExNCAxNCA5MCAwIDEgMTQgMTQgVjI1NCBoLTg2IFYyNDAgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTM1NCAyNTQgdjMyIGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyODIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYyNTQgSDg2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI2OCIgeT0iMjI2IiB3aWR0aD0iODYiIGhlaWdodD0iNzQiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyNjgiIHkxPSIyNTQiIHgyPSIzNTQiIHkyPSIyNTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyNzYiIHk9IjI0Ny4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJ1dHJ1bTwvdGV4dD4KCQk8dGV4dCB4PSIyNzUiIHk9IjI3Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5mYXVjaWJ1czwvdGV4dD4KCQk8dGV4dCB4PSIyNzUiIHk9IjI4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jdXJhZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIyNSIgeT0iMjc5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIzNTkiIHk9IjI3OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMTk0LjUiIHk9IjEzNSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBTElRVUVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzMiIgeT0iOSIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEzMiIgeT0iMzkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzIiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTMyIiB5MT0iMzkiIHgyPSIyMjAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQxIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFsaXF1ZXQ8L3RleHQ+Cgk8dGV4dCB4PSIxNDAiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhlbmRyZXJpdDwvdGV4dD4KCTxsaW5lIHgxPSIxNDAiIHkxPSI1OSIgeDI9IjE5OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTQwIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tZXR1czwvdGV4dD4KCTx0ZXh0IHg9IjE0MCIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGFjdXM8L3RleHQ+Cgk8dGV4dCB4PSIxNDAiIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVpczwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTUFTU0EgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzc5IiB5PSIyNiIgd2lkdGg9IjcyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM3OSIgeT0iNTYiIHdpZHRoPSI3MiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNzkiIHk9IjI2IiB3aWR0aD0iNzIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzc5IiB5MT0iNTYiIHgyPSI0NTEiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzg3IiB5PSI0Ny4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk1hc3NhPC90ZXh0PgoJPHRleHQgeD0iMzg3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tZXR1czwvdGV4dD4KCTxsaW5lIHgxPSIzODciIHkxPSI3NiIgeDI9IjQyNiIgeTI9Ijc2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzg3IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wb3N1ZXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBHUkFWSURBIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzMiIgeT0iMjMzIiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTMyIiB5PSIyNjMiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzIiIHk9IjIzMyIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEzMiIgeTE9IjI2MyIgeDI9IjIyMCIgeTI9IjI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQwIiB5PSIyNTQuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5HcmF2aWRhPC90ZXh0PgoJPHRleHQgeD0iMTQwIiB5PSIyODAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+b3JuYXJlPC90ZXh0PgoJPGxpbmUgeDE9IjE0MCIgeTE9IjI4MyIgeDI9IjE4MyIgeTI9IjI4MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgQU5URSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzODMiIHk9IjIyNSIgd2lkdGg9IjY0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4MyIgeT0iMjU1IiB3aWR0aD0iNjQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgzIiB5PSIyMjUiIHdpZHRoPSI2NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzODMiIHkxPSIyNTUiIHgyPSI0NDciIHkyPSIyNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM5MyIgeT0iMjQ2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QW50ZTwvdGV4dD4KCTx0ZXh0IHg9IjM5MSIgeT0iMjcyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnZpdGFlPC90ZXh0PgoJPGxpbmUgeDE9IjM5MSIgeTE9IjI3NSIgeDI9IjQyMSIgeTI9IjI3NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM5MSIgeT0iMjg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnRlbXBvcjwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'utilisateur peut alors spécifier les espacements qu'il désire en complétant les rangées par des boîtes invisibles dont le seul rôle est de « pousser » les autres à l'emplacement voulu. Cela se fait en insérant manuellement des lignes réduites au caractère deux-points :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [33]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nUltrices, 01 Aliquet, 0N Aliquet\nAliquet: hendrerit, metus, lacus, quis\nRisus, 1N Aliquet, 0N Massa\nMassa: metus, posuere\nEuismod, 0N Massa, 0N Massa\n\n:\n:\nConvallis, 0N Aliquet, 0N Ante: vestibulum\nTincidunt, 11 Ante, 0N Massa\n\nGravida: ornare\nRutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae\n:\nAnte: vitae, tempor\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1ODEiIGhlaWdodD0iMzEwIiB2aWV3Qm94PSIwIDAgNTgxIDMxMCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1ODEiIGhlaWdodD0iMzEwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBVTFRSSUNFUyAtLT4KPGc+Cgk8cGF0aCBkPSJNMTc2IDY0IEMxMzguNjcgOTYgOTguNjcgOTYgNTYgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cGF0aCBkPSJNMTc2IDY0IEMxMzggMzIgOTggMzIgNTYgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNODkgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05NCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTEwMyA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIzIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjkiIHk9IjM1IiB3aWR0aD0iOTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iNjMiIHgyPSIxMDMiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE2IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlVsdHJpY2VzPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA5IiB5PSI3OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCwxPC90ZXh0PgoJPHRleHQgeD0iMTA4IiB5PSI1NyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJJU1VTIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNzYiIHkxPSI2NCIgeDI9IjI4MiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQxNyIgeTE9IjY0IiB4Mj0iMjgyIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMzAxIDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtNjYgVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zMTUgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyNjMgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBINjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjQ5IiB5PSIzNSIgd2lkdGg9IjY2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMjQ5IiB5MT0iNjMiIHgyPSIzMTUiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjI1NiIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SaXN1czwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIyNSIgeT0iNTYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM1NyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBFVUlTTU9EIC0tPgo8Zz4KCTxwYXRoIGQ9Ik00MTcgNjQgQzQ0Ny42NyAzMiA0ODQuMzMgMzIgNTI3IDY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTQxNyA2NCBDNDQ3LjY3IDk2IDQ4NC4zMyA5NiA1MjcgNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNTU4IDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtOTAgVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01NzIgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0OTYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIOTAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDgyIiB5PSIzNSIgd2lkdGg9IjkwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNDgyIiB5MT0iNjMiIHgyPSI1NzIiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQ4OSIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FdWlzbW9kPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDU4IiB5PSI1OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDU4IiB5PSI3OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlZBTExJUyAtLT4KPGc+Cgk8bGluZSB4MT0iMTc2IiB5MT0iNjQiIHgyPSIyODIiIHkyPSIxNzIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNDE3IiB5MT0iMjYzIiB4Mj0iMjgyIiB5Mj0iMTcyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTMyMiAxNDMgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTcxIGgtMTA4IFYxNTcgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTMzNiAxNzEgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyNDIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNzEgSDEwOCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyMjgiIHk9IjE0MyIgd2lkdGg9IjEwOCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjIyOCIgeTE9IjE3MSIgeDI9IjMzNiIgeTI9IjE3MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIzNiIgeT0iMTY0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29udmFsbGlzPC90ZXh0PgoJCTx0ZXh0IHg9IjIzNSIgeT0iMTg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnZlc3RpYnVsdW08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyMjUiIHk9IjEwNy44MSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMzYxIiB5PSIyNTIuMjciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBUSU5DSURVTlQgLS0+CjxnPgoJPGxpbmUgeDE9IjQxNyIgeTE9IjI2MyIgeDI9IjQxNyIgeTI9IjE3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0MTciIHkxPSI2NCIgeDI9IjQxNyIgeTI9IjE3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NTUgMTQzIGExNCAxNCA5MCAwIDEgMTQgMTQgVjE3MSBoLTEwNCBWMTU3IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik00NjkgMTcxIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzc5IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTcxIEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzY1IiB5PSIxNDMiIHdpZHRoPSIxMDQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzNjUiIHkxPSIxNzEiIHgyPSI0NjkiIHkyPSIxNzEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzNzIiIHk9IjE2NC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRpbmNpZHVudDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQyMiIgeT0iMjE3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI0MjIiIHk9IjExOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJVVFJVTSAtLT4KPGc+Cgk8bGluZSB4MT0iNTYiIHkxPSIyNjMiIHgyPSIxNzYiIHkyPSIyNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNDE3IiB5MT0iMjYzIiB4Mj0iMTc2IiB5Mj0iMjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjE3NiIgeTE9IjY0IiB4Mj0iMTc2IiB5Mj0iMjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIwNSAyMjYgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjU0IGgtODYgVjI0MCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjE5IDI1NCB2MzIgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE0NyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI1NCBIODYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTMzIiB5PSIyMjYiIHdpZHRoPSI4NiIgaGVpZ2h0PSI3NCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEzMyIgeTE9IjI1NCIgeDI9IjIxOSIgeTI9IjI1NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE0MSIgeT0iMjQ3LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UnV0cnVtPC90ZXh0PgoJCTx0ZXh0IHg9IjE0MCIgeT0iMjcyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmZhdWNpYnVzPC90ZXh0PgoJCTx0ZXh0IHg9IjE0MCIgeT0iMjg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmN1cmFlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA1IiB5PSIyNzkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM2MSIgeT0iMjc5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxNTIiIHk9IjEzNSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBTElRVUVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzMiIgeT0iOSIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEzMiIgeT0iMzkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzIiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTMyIiB5MT0iMzkiIHgyPSIyMjAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQxIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFsaXF1ZXQ8L3RleHQ+Cgk8dGV4dCB4PSIxNDAiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhlbmRyZXJpdDwvdGV4dD4KCTxsaW5lIHgxPSIxNDAiIHkxPSI1OSIgeDI9IjE5OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTQwIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tZXR1czwvdGV4dD4KCTx0ZXh0IHg9IjE0MCIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGFjdXM8L3RleHQ+Cgk8dGV4dCB4PSIxNDAiIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVpczwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTUFTU0EgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgxIiB5PSIyNiIgd2lkdGg9IjcyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4MSIgeT0iNTYiIHdpZHRoPSI3MiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzODEiIHk9IjI2IiB3aWR0aD0iNzIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzgxIiB5MT0iNTYiIHgyPSI0NTMiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzg5IiB5PSI0Ny4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk1hc3NhPC90ZXh0PgoJPHRleHQgeD0iMzg5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tZXR1czwvdGV4dD4KCTxsaW5lIHgxPSIzODkiIHkxPSI3NiIgeDI9IjQyOCIgeTI9Ijc2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzg5IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wb3N1ZXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBHUkFWSURBIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEyIiB5PSIyMzMiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMiIgeT0iMjYzIiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTIiIHk9IjIzMyIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEyIiB5MT0iMjYzIiB4Mj0iMTAwIiB5Mj0iMjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMCIgeT0iMjU0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+R3JhdmlkYTwvdGV4dD4KCTx0ZXh0IHg9IjIwIiB5PSIyODAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+b3JuYXJlPC90ZXh0PgoJPGxpbmUgeDE9IjIwIiB5MT0iMjgzIiB4Mj0iNjMiIHkyPSIyODMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IEFOVEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzg1IiB5PSIyMjUiIHdpZHRoPSI2NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzODUiIHk9IjI1NSIgd2lkdGg9IjY0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4NSIgeT0iMjI1IiB3aWR0aD0iNjQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzg1IiB5MT0iMjU1IiB4Mj0iNDQ5IiB5Mj0iMjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzOTUiIHk9IjI0Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFudGU8L3RleHQ+Cgk8dGV4dCB4PSIzOTMiIHk9IjI3Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij52aXRhZTwvdGV4dD4KCTxsaW5lIHgxPSIzOTMiIHkxPSIyNzUiIHgyPSI0MjMiIHkyPSIyNzUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzOTMiIHk9IjI4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50ZW1wb3I8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"R%C3%A9arrangement-automatique\">Réarrangement automatique<a class=\"anchor-link\" href=\"#R%C3%A9arrangement-automatique\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cependant, en général, ces manipulations sont inutiles : Mocodo est capable de calculer tout seul des plongements à la fois compacts et esthétiques. Voici une compilation des réarrangements automatiques du MCD précédent produits par :</p>\n<pre><code>%mocodo -i sandbox -t arrange --seed 1\n%mocodo -i sandbox -t arrange --seed 2\n%mocodo -i sandbox -t arrange --seed 3\n%mocodo -i sandbox -t arrange --seed 4\n</code></pre>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [34]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ../examples/four_random_layouts --scale 0.8\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzQiIGhlaWdodD0iNTgyIiB2aWV3Qm94PSIwIDAgOTM0IDU4MiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI5MzQiIGhlaWdodD0iNTgyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBUSU5DSURVTlQxIC0tPgo8Zz4KCTxsaW5lIHgxPSIzMzYiIHkxPSI5OCIgeDI9IjI0MyIgeTI9IjMxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iMTQ3IiB5MT0iOTgiIHgyPSIyNDMiIHkyPSIzMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTI3My44IDcgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYzMCBoLTg0IFYxOC4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI4NSAzMCB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgyMTIuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMzAgSDg0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjIwMSIgeT0iNyIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSIyMDEiIHkxPSIzMCIgeDI9IjI4NSIgeTI9IjMwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iMjA3IiB5PSIyNC43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlRpbmNpZHVudDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI5MiIgeT0iODguMjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIxODAiIHk9Ijg2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRVVJU01PRDEgLS0+CjxnPgoJPHBhdGggZD0iTTE0NyA5OCBDMTI3IDEyMy4zMyA5MyAxMjMuMzMgNDUgOTgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwYXRoIGQ9Ik0xNDcgOTggQzEyNyA3Mi42NyA5MyA3Mi42NyA0NSA5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTcwLjggNzQgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFY5NyBoLTc0IFY4NS4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTgyIDk3IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDE5LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjk3IEg3NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI4IiB5PSI3NCIgd2lkdGg9Ijc0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI4IiB5MT0iOTciIHgyPSI4MiIgeTI9Ijk3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iMTUiIHk9IjkxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+RXVpc21vZDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9Ijk5IiB5PSIxMDkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9Ijk5IiB5PSI5Mi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlZBTExJUzEgLS0+CjxnPgoJPGxpbmUgeDE9IjI0MyIgeTE9IjE4NyIgeDI9IjI0MyIgeTI9Ijk4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iMzM2IiB5MT0iOTgiIHgyPSIyNDMiIHkyPSI5OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTI3NS44IDc0IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWOTcgaC04OCBWODUuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yODcgOTcgdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIMjEwLjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjk3IEg4OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxOTkiIHk9Ijc0IiB3aWR0aD0iODgiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjE5OSIgeTE9Ijk3IiB4Mj0iMjg3IiB5Mj0iOTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIyMDYiIHk9IjkxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+Q29udmFsbGlzPC90ZXh0PgoJCTx0ZXh0IHg9IjIwNSIgeT0iMTEyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnZlc3RpYnVsdW08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNDciIHk9IjEzNC42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMjkyIiB5PSIxMTAuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSSVNVUzIgLS0+CjxnPgoJPGxpbmUgeDE9IjY3NCIgeTE9IjE4NyIgeDI9IjY3NCIgeTI9Ijk4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iNzc2IiB5MT0iOTgiIHgyPSI2NzQiIHkyPSI5OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTY4OS44IDc0IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWOTcgaC01NCBWODUuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03MDEgOTcgdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBINjU4LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjk3IEg1NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI2NDciIHk9Ijc0IiB3aWR0aD0iNTQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjY0NyIgeTE9Ijk3IiB4Mj0iNzAxIiB5Mj0iOTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI2NTMiIHk9IjkxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+UmlzdXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2NzgiIHk9IjEzNC42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNzI4IiB5PSIxMTAuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBFVUlTTU9EMiAtLT4KPGc+Cgk8cGF0aCBkPSJNNzc2IDk4IEM3OTMuNjcgNzIuNjcgODMwIDcyLjY3IDg4NSA5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHBhdGggZD0iTTc3NiA5OCBDNzkzLjY3IDEyMy4zMyA4MzAgMTIzLjMzIDg4NSA5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTkxMC44IDc0IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWOTcgaC03NCBWODUuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik05MjIgOTcgdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIODU5LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjk3IEg3NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI4NDgiIHk9Ijc0IiB3aWR0aD0iNzQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9Ijg0OCIgeTE9Ijk3IiB4Mj0iOTIyIiB5Mj0iOTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI4NTUiIHk9IjkxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+RXVpc21vZDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjgwOSIgeT0iOTIuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjgwOSIgeT0iMTA5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUklTVVMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNDMiIHkxPSIxODciIHgyPSIxNDciIHkyPSIxODciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIxNDciIHkxPSI5OCIgeDI9IjE0NyIgeTI9IjE4NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTE2Mi44IDE2MyBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjE4NiBoLTU0IFYxNzQuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0xNzQgMTg2IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDEzMS4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxODYgSDU0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMCIgeT0iMTYzIiB3aWR0aD0iNTQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjEyMCIgeTE9IjE4NiIgeDI9IjE3NCIgeTI9IjE4NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjEyNiIgeT0iMTgwLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+UmlzdXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjE5OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTUxIiB5PSIxNDIuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSVVRSVU0xIC0tPgo8Zz4KCTxsaW5lIHgxPSI0MjkiIHkxPSIxODciIHgyPSIzMzYiIHkyPSIxODciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIzMzYiIHkxPSI5OCIgeDI9IjMzNiIgeTI9IjE4NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGxpbmUgeDE9IjI0MyIgeTE9IjE4NyIgeDI9IjMzNiIgeTI9IjE4NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTM1OS44IDE1NiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjE3OSBoLTcwIFYxNjcuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zNzEgMTc5IHYyNy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDMxMi4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxNzkgSDcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMwMSIgeT0iMTU2IiB3aWR0aD0iNzAiIGhlaWdodD0iNjIiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjMwMSIgeTE9IjE3OSIgeDI9IjM3MSIgeTI9IjE3OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjMwOCIgeT0iMTczLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+UnV0cnVtPC90ZXh0PgoJCTx0ZXh0IHg9IjMwNyIgeT0iMTk0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmZhdWNpYnVzPC90ZXh0PgoJCTx0ZXh0IHg9IjMwNyIgeT0iMjA4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmN1cmFlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzc1IiB5PSIxOTkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM0MCIgeT0iMTQyLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyODIiIHk9IjE5OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFVMVFJJQ0VTMiAtLT4KPGc+Cgk8cGF0aCBkPSJNNjc0IDE4NyBDNjQ0IDIxMi4zMyA2MTIgMjEyLjMzIDU3OCAxODciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwYXRoIGQ9Ik02NzQgMTg3IEM2NDQgMTYxLjY3IDYxMiAxNjEuNjcgNTc4IDE4NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTYwNC44IDE2MyBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjE4NiBoLTc2IFYxNzQuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik02MTYgMTg2IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDU1MS4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxODYgSDc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjU0MCIgeT0iMTYzIiB3aWR0aD0iNzYiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjU0MCIgeTE9IjE4NiIgeDI9IjYxNiIgeTI9IjE4NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjU0NiIgeT0iMTgwLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+VWx0cmljZXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2MjAiIHk9IjE5OC42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCwxPC90ZXh0PgoJPHRleHQgeD0iNjIwIiB5PSIxODEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDT05WQUxMSVMyIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NzQiIHkxPSIxODciIHgyPSI3NzYiIHkyPSIxODciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI3NzYiIHkxPSIyODMiIHgyPSI3NzYiIHkyPSIxODciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik04MDguOCAxNjMgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYxODYgaC04OCBWMTc0LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNODIwIDE4NiB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEg3NDMuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMTg2IEg4OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI3MzIiIHk9IjE2MyIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI3MzIiIHkxPSIxODYiIHgyPSI4MjAiIHkyPSIxODYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI3MzkiIHk9IjE4MC43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkNvbnZhbGxpczwvdGV4dD4KCQk8dGV4dCB4PSI3MzgiIHk9IjIwMS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj52ZXN0aWJ1bHVtPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNzEzIiB5PSIxOTkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9Ijc1NyIgeT0iMjQ0LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVElOQ0lEVU5UMiAtLT4KPGc+Cgk8bGluZSB4MT0iNzc2IiB5MT0iMjgzIiB4Mj0iODg1IiB5Mj0iMTg3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8cGF0aCBkPSJNNzc2IDk4IEM3NzUuMTYgMTM1LjA5IDgxMS40OSAxNjQuNzYgODg1IDE4NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTkxNS44IDE2MyBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjE4NiBoLTg0IFYxNzQuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik05MjcgMTg2IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDg1NC4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxODYgSDg0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9Ijg0MyIgeT0iMTYzIiB3aWR0aD0iODQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9Ijg0MyIgeTE9IjE4NiIgeDI9IjkyNyIgeTI9IjE4NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9Ijg0OSIgeT0iMTgwLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+VGluY2lkdW50PC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iODA1IiB5PSIyNjguNDMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI4MDMuMTUiIHk9IjE0Mi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFVMVFJJQ0VTMSAtLT4KPGc+Cgk8cGF0aCBkPSJNMjQzIDE4NyBDMjczLjY3IDIyOSAyNzMuNjcgMjYxIDI0MyAyODMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwYXRoIGQ9Ik0yNDMgMTg3IEMyMTIuMzMgMjI5IDIxMi4zMyAyNjEgMjQzIDI4MyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTI2OS44IDI1OSBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjI4MiBoLTc2IFYyNzAuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yODEgMjgyIHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDIxNi4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYyODIgSDc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjIwNSIgeT0iMjU5IiB3aWR0aD0iNzYiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjIwNSIgeTE9IjI4MiIgeDI9IjI4MSIgeTI9IjI4MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjIxMSIgeT0iMjc2Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+VWx0cmljZXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNDYiIHk9IjI0NS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCwxPC90ZXh0PgoJPHRleHQgeD0iMjI1IiB5PSIyNDUuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSVVRSVU0yIC0tPgo8Zz4KCTxsaW5lIHgxPSI1NzgiIHkxPSIyODMiIHgyPSI2NzQiIHkyPSIyODMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI3NzYiIHkxPSIyODMiIHgyPSI2NzQiIHkyPSIyODMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI2NzQiIHkxPSIxODciIHgyPSI2NzQiIHkyPSIyODMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik02OTcuOCAyNTIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYyNzUgaC03MCBWMjYzLjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNzA5IDI3NSB2MjcuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEg2NTAuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMjc1IEg3MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI2MzkiIHk9IjI1MiIgd2lkdGg9IjcwIiBoZWlnaHQ9IjYyIiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI2MzkiIHkxPSIyNzUiIHgyPSI3MDkiIHkyPSIyNzUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI2NDYiIHk9IjI2OS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlJ1dHJ1bTwvdGV4dD4KCQk8dGV4dCB4PSI2NDUiIHk9IjI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5mYXVjaWJ1czwvdGV4dD4KCQk8dGV4dCB4PSI2NDUiIHk9IjMwNC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5jdXJhZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjYxNyIgeT0iMjk1LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI3MzIiIHk9IjI5NS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNjc4IiB5PSIyNDUuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBVTFRSSUNFUzMgLS0+CjxnPgoJPHBhdGggZD0iTTE0NyAzNzkgQzExOSA0MDQuMzMgODUgNDA0LjMzIDQ1IDM3OSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHBhdGggZD0iTTE0NyAzNzkgQzExOSAzNTMuNjcgODUgMzUzLjY3IDQ1IDM3OSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTcxLjggMzU1IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWMzc4IGgtNzYgVjM2Ni4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTgzIDM3OCB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgxOC4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYzNzggSDc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjciIHk9IjM1NSIgd2lkdGg9Ijc2IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI3IiB5MT0iMzc4IiB4Mj0iODMiIHkyPSIzNzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIxMyIgeT0iMzcyLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+VWx0cmljZXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI5MyIgeT0iMzkwLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLDE8L3RleHQ+Cgk8dGV4dCB4PSI5MyIgeT0iMzczLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUklTVVMzIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNDciIHkxPSIzNzkiIHgyPSIyNDMiIHkyPSIzNzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIyNDMiIHkxPSI0NjgiIHgyPSIyNDMiIHkyPSIzNzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNTguOCAzNTUgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYzNzggaC01NCBWMzY2LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjcwIDM3OCB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgyMjcuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMzc4IEg1NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyMTYiIHk9IjM1NSIgd2lkdGg9IjU0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSIyMTYiIHkxPSIzNzgiIHgyPSIyNzAiIHkyPSIzNzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIyMjIiIHk9IjM3Mi43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlJpc3VzPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTg2IiB5PSIzOTEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iNDI5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUklTVVM0IC0tPgo8Zz4KCTxsaW5lIHgxPSI2NzQiIHkxPSIzNzkiIHgyPSI1NzgiIHkyPSIzNzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI1NzgiIHkxPSI0NjgiIHgyPSI1NzgiIHkyPSIzNzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik01OTMuOCAzNTUgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYzNzggaC01NCBWMzY2LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNjA1IDM3OCB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEg1NjIuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMzc4IEg1NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI1NTEiIHk9IjM1NSIgd2lkdGg9IjU0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI1NTEiIHkxPSIzNzgiIHgyPSI2MDUiIHkyPSIzNzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI1NTciIHk9IjM3Mi43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlJpc3VzPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNjIwIiB5PSIzOTEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjU4MiIgeT0iNDI5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVUxUUklDRVM0IC0tPgo8Zz4KCTxwYXRoIGQ9Ik02NzQgMzc5IEM3MDIgMzUzLjY3IDczNiAzNTMuNjcgNzc2IDM3OSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHBhdGggZD0iTTY3NCAzNzkgQzcwMiA0MDQuMzMgNzM2IDQwNC4zMyA3NzYgMzc5IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8Zz4KCQk8cGF0aCBkPSJNODAyLjggMzU1IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWMzc4IGgtNzYgVjM2Ni4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTgxNCAzNzggdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBINzQ5LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjM3OCBINzYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNzM4IiB5PSIzNTUiIHdpZHRoPSI3NiIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iNzM4IiB5MT0iMzc4IiB4Mj0iODE0IiB5Mj0iMzc4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iNzQ0IiB5PSIzNzIuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5VbHRyaWNlczwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjcxMyIgeT0iMzczLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLDE8L3RleHQ+Cgk8dGV4dCB4PSI3MTMiIHk9IjM5MC42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJVVFJVTTMgLS0+CjxnPgoJPGxpbmUgeDE9IjQ1IiB5MT0iNTQzIiB4Mj0iNDUiIHkyPSI0NjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIxNDciIHkxPSI1NDMiIHgyPSI0NSIgeTI9IjQ2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHBhdGggZD0iTTE0NyAzNzkgQzEzOC4zNSA0MjUuNjEgMTA0LjM1IDQ1NS4yOCA0NSA0NjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik02OC44IDQzNyBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjQ2MCBoLTcwIFY0NDguMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik04MCA0NjAgdjI3LjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIMjEuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWNDYwIEg3MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMCIgeT0iNDM3IiB3aWR0aD0iNzAiIGhlaWdodD0iNjIiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjEwIiB5MT0iNDYwIiB4Mj0iODAiIHkyPSI0NjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIxNyIgeT0iNDU0Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+UnV0cnVtPC90ZXh0PgoJCTx0ZXh0IHg9IjE2IiB5PSI0NzUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+ZmF1Y2lidXM8L3RleHQ+CgkJPHRleHQgeD0iMTYiIHk9IjQ4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5jdXJhZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQ5IiB5PSI1MTEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjEwMyIgeT0iNTMyLjc3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iOTMiIHk9IjQzNy43MSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDT05WQUxMSVMzIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNDciIHkxPSIzNzkiIHgyPSIxNDciIHkyPSI0NjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIxNDciIHkxPSI1NDMiIHgyPSIxNDciIHkyPSI0NjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0xNzkuOCA0NDQgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFY0NjcgaC04OCBWNDU1LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTkxIDQ2NyB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgxMTQuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWNDY3IEg4OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMDMiIHk9IjQ0NCIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSIxMDMiIHkxPSI0NjciIHgyPSIxOTEiIHkyPSI0NjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIxMTAiIHk9IjQ2MS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkNvbnZhbGxpczwvdGV4dD4KCQk8dGV4dCB4PSIxMDkiIHk9IjQ4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj52ZXN0aWJ1bHVtPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTUxIiB5PSI0MzcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjE1MSIgeT0iNTA0LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRVVJU01PRDMgLS0+CjxnPgoJPHBhdGggZD0iTTI0MyA0NjggQzI2NiA0NDIuNjcgMjk3IDQ0Mi42NyAzMzYgNDY4IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8cGF0aCBkPSJNMjQzIDQ2OCBDMjY2IDQ5My4zMyAyOTcgNDkzLjMzIDMzNiA0NjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zNjEuOCA0NDQgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFY0NjcgaC03NCBWNDU1LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzczIDQ2NyB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgzMTAuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWNDY3IEg3NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyOTkiIHk9IjQ0NCIgd2lkdGg9Ijc0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSIyOTkiIHkxPSI0NjciIHgyPSIzNzMiIHkyPSI0NjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIzMDYiIHk9IjQ2MS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkV1aXNtb2Q8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNzYiIHk9IjQ2Mi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMjc2IiB5PSI0NzkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBFVUlTTU9ENCAtLT4KPGc+Cgk8cGF0aCBkPSJNNTc4IDQ2OCBDNTUzLjY3IDQ5My4zMyA1MjQgNDkzLjMzIDQ4OSA0NjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwYXRoIGQ9Ik01NzggNDY4IEM1NTMuNjcgNDQyLjY3IDUyNCA0NDIuNjcgNDg5IDQ2OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTUxNC44IDQ0NCBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjQ2NyBoLTc0IFY0NTUuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01MjYgNDY3IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDQ2My4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFY0NjcgSDc0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQ1MiIgeT0iNDQ0IiB3aWR0aD0iNzQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjQ1MiIgeTE9IjQ2NyIgeDI9IjUyNiIgeTI9IjQ2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjQ1OSIgeT0iNDYxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+RXVpc21vZDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUzMCIgeT0iNDc5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI1MzAiIHk9IjQ2Mi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlZBTExJUzQgLS0+CjxnPgoJPGxpbmUgeDE9IjY3NCIgeTE9IjM3OSIgeDI9IjY3NCIgeTI9IjQ2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGxpbmUgeDE9IjY3NCIgeTE9IjU0MyIgeDI9IjY3NCIgeTI9IjQ2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTcwNi44IDQ0NCBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjQ2NyBoLTg4IFY0NTUuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03MTggNDY3IHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDY0MS4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFY0NjcgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjYzMCIgeT0iNDQ0IiB3aWR0aD0iODgiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjYzMCIgeTE9IjQ2NyIgeDI9IjcxOCIgeTI9IjQ2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjYzNyIgeT0iNDYxLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+Q29udmFsbGlzPC90ZXh0PgoJCTx0ZXh0IHg9IjYzNiIgeT0iNDgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnZlc3RpYnVsdW08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2NTUiIHk9IjQzNy42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNjU1IiB5PSI1MDQuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSVVRSVU00IC0tPgo8Zz4KCTxsaW5lIHgxPSI4ODUiIHkxPSI0NjgiIHgyPSI3NzYiIHkyPSI0NjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI2NzQiIHkxPSI1NDMiIHgyPSI3NzYiIHkyPSI0NjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwYXRoIGQ9Ik02NzQgMzc5IEM2ODIuNjUgNDI1LjYxIDcxNi42NSA0NTUuMjggNzc2IDQ2OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTc5OS44IDQzNyBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjQ2MCBoLTcwIFY0NDguMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik04MTEgNDYwIHYyNy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDc1Mi4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFY0NjAgSDcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9Ijc0MSIgeT0iNDM3IiB3aWR0aD0iNzAiIGhlaWdodD0iNjIiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9Ijc0MSIgeTE9IjQ2MCIgeDI9IjgxMSIgeTI9IjQ2MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9Ijc0OCIgeT0iNDU0Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+UnV0cnVtPC90ZXh0PgoJCTx0ZXh0IHg9Ijc0NyIgeT0iNDc1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmZhdWNpYnVzPC90ZXh0PgoJCTx0ZXh0IHg9Ijc0NyIgeT0iNDg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmN1cmFlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iODMxIiB5PSI0ODAuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjcwMyIgeT0iNTMyLjc3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNzEzIiB5PSI0MzcuNzEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVElOQ0lEVU5UMyAtLT4KPGc+Cgk8bGluZSB4MT0iMTQ3IiB5MT0iNTQzIiB4Mj0iMjQzIiB5Mj0iNTQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iMjQzIiB5MT0iNDY4IiB4Mj0iMjQzIiB5Mj0iNTQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjczLjggNTE5IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWNTQyIGgtODQgVjUzMC4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI4NSA1NDIgdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIMjEyLjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjU0MiBIODQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjAxIiB5PSI1MTkiIHdpZHRoPSI4NCIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iMjAxIiB5MT0iNTQyIiB4Mj0iMjg1IiB5Mj0iNTQyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iMjA3IiB5PSI1MzYuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5UaW5jaWR1bnQ8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNzYiIHk9IjU1NS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMjQ3IiB5PSI1MTIuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBUSU5DSURVTlQ0IC0tPgo8Zz4KCTxsaW5lIHgxPSI2NzQiIHkxPSI1NDMiIHgyPSI1NzgiIHkyPSI1NDMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI1NzgiIHkxPSI0NjgiIHgyPSI1NzgiIHkyPSI1NDMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik02MDguOCA1MTkgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFY1NDIgaC04NCBWNTMwLjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNjIwIDU0MiB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEg1NDcuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWNTQyIEg4NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI1MzYiIHk9IjUxOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI1MzYiIHkxPSI1NDIiIHgyPSI2MjAiIHkyPSI1NDIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI1NDIiIHk9IjUzNi43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlRpbmNpZHVudDwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjYzMCIgeT0iNTU1LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI1ODIiIHk9IjUxMi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBNQVNTQTEgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTE4IiB5PSI2NiIgd2lkdGg9IjU4IiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjExOCIgeT0iOTEiIHdpZHRoPSI1OCIgaGVpZ2h0PSIzOSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMTgiIHk9IjY2IiB3aWR0aD0iNTgiIGhlaWdodD0iNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTE4IiB5MT0iOTEiIHgyPSIxNzYiIHkyPSI5MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iMTI1IiB5PSI4My43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPk1hc3NhPC90ZXh0PgoJPHRleHQgeD0iMTI0IiB5PSIxMDUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+bWV0dXM8L3RleHQ+Cgk8bGluZSB4MT0iMTI0IiB5MT0iMTA3LjYiIHgyPSIxNTUiIHkyPSIxMDcuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iMTI0IiB5PSIxMTkuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+cG9zdWVyZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQU5URTEgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzExIiB5PSI2NiIgd2lkdGg9IjUwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMxMSIgeT0iOTEiIHdpZHRoPSI1MCIgaGVpZ2h0PSIzOSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMTEiIHk9IjY2IiB3aWR0aD0iNTAiIGhlaWdodD0iNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzExIiB5MT0iOTEiIHgyPSIzNjEiIHkyPSI5MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iMzE5IiB5PSI4My43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkFudGU8L3RleHQ+Cgk8dGV4dCB4PSIzMTciIHk9IjEwNS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj52aXRhZTwvdGV4dD4KCTxsaW5lIHgxPSIzMTciIHkxPSIxMDcuNiIgeDI9IjM0MSIgeTI9IjEwNy42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSIzMTciIHk9IjExOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj50ZW1wb3I8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IE1BU1NBMiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI3NDciIHk9IjY2IiB3aWR0aD0iNTgiIGhlaWdodD0iMjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNzQ3IiB5PSI5MSIgd2lkdGg9IjU4IiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijc0NyIgeT0iNjYiIHdpZHRoPSI1OCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI3NDciIHkxPSI5MSIgeDI9IjgwNSIgeTI9IjkxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSI3NTQiIHk9IjgzLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+TWFzc2E8L3RleHQ+Cgk8dGV4dCB4PSI3NTMiIHk9IjEwNS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5tZXR1czwvdGV4dD4KCTxsaW5lIHgxPSI3NTMiIHkxPSIxMDcuNiIgeDI9Ijc4NCIgeTI9IjEwNy42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSI3NTMiIHk9IjExOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5wb3N1ZXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBTElRVUVUMSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMDgiIHk9IjE0MSIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIwOCIgeT0iMTY2IiB3aWR0aD0iNzAiIGhlaWdodD0iNjciIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjA4IiB5PSIxNDEiIHdpZHRoPSI3MCIgaGVpZ2h0PSI5MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMDgiIHkxPSIxNjYiIHgyPSIyNzgiIHkyPSIxNjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9IjIxNSIgeT0iMTU4Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+QWxpcXVldDwvdGV4dD4KCTx0ZXh0IHg9IjIxNCIgeT0iMTgwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmhlbmRyZXJpdDwvdGV4dD4KCTxsaW5lIHgxPSIyMTQiIHkxPSIxODIuNiIgeDI9IjI2MiIgeTI9IjE4Mi42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSIyMTQiIHk9IjE5NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5tZXR1czwvdGV4dD4KCTx0ZXh0IHg9IjIxNCIgeT0iMjA4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmxhY3VzPC90ZXh0PgoJPHRleHQgeD0iMjE0IiB5PSIyMjIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+cXVpczwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgR1JBVklEQTEgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzk0IiB5PSIxNjIiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOTQiIHk9IjE4NyIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM5NCIgeT0iMTYyIiB3aWR0aD0iNzAiIGhlaWdodD0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzk0IiB5MT0iMTg3IiB4Mj0iNDY0IiB5Mj0iMTg3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSI0MDAiIHk9IjE3OS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkdyYXZpZGE8L3RleHQ+Cgk8dGV4dCB4PSI0MDAiIHk9IjIwMS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5vcm5hcmU8L3RleHQ+Cgk8bGluZSB4MT0iNDAwIiB5MT0iMjAzLjYiIHgyPSI0MzUiIHkyPSIyMDMuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgo8L2c+Cgo8IS0tIEVudGl0eSBBTElRVUVUMiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI2MzkiIHk9IjE0MSIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjYzOSIgeT0iMTY2IiB3aWR0aD0iNzAiIGhlaWdodD0iNjciIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNjM5IiB5PSIxNDEiIHdpZHRoPSI3MCIgaGVpZ2h0PSI5MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI2MzkiIHkxPSIxNjYiIHgyPSI3MDkiIHkyPSIxNjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9IjY0NiIgeT0iMTU4Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+QWxpcXVldDwvdGV4dD4KCTx0ZXh0IHg9IjY0NSIgeT0iMTgwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmhlbmRyZXJpdDwvdGV4dD4KCTxsaW5lIHgxPSI2NDUiIHkxPSIxODIuNiIgeDI9IjY5MyIgeTI9IjE4Mi42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSI2NDUiIHk9IjE5NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5tZXR1czwvdGV4dD4KCTx0ZXh0IHg9IjY0NSIgeT0iMjA4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmxhY3VzPC90ZXh0PgoJPHRleHQgeD0iNjQ1IiB5PSIyMjIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+cXVpczwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgR1JBVklEQTIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNTQzIiB5PSIyNTgiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDMiIHk9IjI4MyIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjU0MyIgeT0iMjU4IiB3aWR0aD0iNzAiIGhlaWdodD0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTQzIiB5MT0iMjgzIiB4Mj0iNjEzIiB5Mj0iMjgzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSI1NDkiIHk9IjI3NS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkdyYXZpZGE8L3RleHQ+Cgk8dGV4dCB4PSI1NDkiIHk9IjI5Ny4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5vcm5hcmU8L3RleHQ+Cgk8bGluZSB4MT0iNTQ5IiB5MT0iMjk5LjYiIHgyPSI1ODQiIHkyPSIyOTkuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgo8L2c+Cgo8IS0tIEVudGl0eSBBTlRFMiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI3NTEiIHk9IjI1MSIgd2lkdGg9IjUwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijc1MSIgeT0iMjc2IiB3aWR0aD0iNTAiIGhlaWdodD0iMzkiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNzUxIiB5PSIyNTEiIHdpZHRoPSI1MCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI3NTEiIHkxPSIyNzYiIHgyPSI4MDEiIHkyPSIyNzYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9Ijc1OSIgeT0iMjY4Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+QW50ZTwvdGV4dD4KCTx0ZXh0IHg9Ijc1NyIgeT0iMjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnZpdGFlPC90ZXh0PgoJPGxpbmUgeDE9Ijc1NyIgeTE9IjI5Mi42IiB4Mj0iNzgxIiB5Mj0iMjkyLjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTx0ZXh0IHg9Ijc1NyIgeT0iMzA0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnRlbXBvcjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQUxJUVVFVDMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTEyIiB5PSIzMzMiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMTIiIHk9IjM1OCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjY3IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjExMiIgeT0iMzMzIiB3aWR0aD0iNzAiIGhlaWdodD0iOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTEyIiB5MT0iMzU4IiB4Mj0iMTgyIiB5Mj0iMzU4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSIxMTkiIHk9IjM1MC43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkFsaXF1ZXQ8L3RleHQ+Cgk8dGV4dCB4PSIxMTgiIHk9IjM3Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5oZW5kcmVyaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMTE4IiB5MT0iMzc0LjYiIHgyPSIxNjYiIHkyPSIzNzQuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iMTE4IiB5PSIzODYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+bWV0dXM8L3RleHQ+Cgk8dGV4dCB4PSIxMTgiIHk9IjQwMC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5sYWN1czwvdGV4dD4KCTx0ZXh0IHg9IjExOCIgeT0iNDE0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnF1aXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFMSVFVRVQ0IC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjYzOSIgeT0iMzMzIiB3aWR0aD0iNzAiIGhlaWdodD0iMjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNjM5IiB5PSIzNTgiIHdpZHRoPSI3MCIgaGVpZ2h0PSI2NyIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI2MzkiIHk9IjMzMyIgd2lkdGg9IjcwIiBoZWlnaHQ9IjkyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjYzOSIgeTE9IjM1OCIgeDI9IjcwOSIgeTI9IjM1OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iNjQ2IiB5PSIzNTAuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5BbGlxdWV0PC90ZXh0PgoJPHRleHQgeD0iNjQ1IiB5PSIzNzIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+aGVuZHJlcml0PC90ZXh0PgoJPGxpbmUgeDE9IjY0NSIgeTE9IjM3NC42IiB4Mj0iNjkzIiB5Mj0iMzc0LjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTx0ZXh0IHg9IjY0NSIgeT0iMzg2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm1ldHVzPC90ZXh0PgoJPHRleHQgeD0iNjQ1IiB5PSI0MDAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+bGFjdXM8L3RleHQ+Cgk8dGV4dCB4PSI2NDUiIHk9IjQxNC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5xdWlzPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBNQVNTQTMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjE0IiB5PSI0MzYiIHdpZHRoPSI1OCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTQiIHk9IjQ2MSIgd2lkdGg9IjU4IiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxNCIgeT0iNDM2IiB3aWR0aD0iNTgiIGhlaWdodD0iNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjE0IiB5MT0iNDYxIiB4Mj0iMjcyIiB5Mj0iNDYxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSIyMjEiIHk9IjQ1My43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPk1hc3NhPC90ZXh0PgoJPHRleHQgeD0iMjIwIiB5PSI0NzUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+bWV0dXM8L3RleHQ+Cgk8bGluZSB4MT0iMjIwIiB5MT0iNDc3LjYiIHgyPSIyNTEiIHkyPSI0NzcuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iMjIwIiB5PSI0ODkuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+cG9zdWVyZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTUFTU0E0IC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU0OSIgeT0iNDM2IiB3aWR0aD0iNTgiIGhlaWdodD0iMjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTQ5IiB5PSI0NjEiIHdpZHRoPSI1OCIgaGVpZ2h0PSIzOSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDkiIHk9IjQzNiIgd2lkdGg9IjU4IiBoZWlnaHQ9IjY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU0OSIgeTE9IjQ2MSIgeDI9IjYwNyIgeTI9IjQ2MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iNTU2IiB5PSI0NTMuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5NYXNzYTwvdGV4dD4KCTx0ZXh0IHg9IjU1NSIgeT0iNDc1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm1ldHVzPC90ZXh0PgoJPGxpbmUgeDE9IjU1NSIgeTE9IjQ3Ny42IiB4Mj0iNTg2IiB5Mj0iNDc3LjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTx0ZXh0IHg9IjU1NSIgeT0iNDg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnBvc3VlcmU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEdSQVZJREE0IC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijg1MCIgeT0iNDQzIiB3aWR0aD0iNzAiIGhlaWdodD0iMjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iODUwIiB5PSI0NjgiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4NTAiIHk9IjQ0MyIgd2lkdGg9IjcwIiBoZWlnaHQ9IjUwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijg1MCIgeTE9IjQ2OCIgeDI9IjkyMCIgeTI9IjQ2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iODU2IiB5PSI0NjAuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5HcmF2aWRhPC90ZXh0PgoJPHRleHQgeD0iODU2IiB5PSI0ODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+b3JuYXJlPC90ZXh0PgoJPGxpbmUgeDE9Ijg1NiIgeTE9IjQ4NC42IiB4Mj0iODkxIiB5Mj0iNDg0LjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KPC9nPgoKPCEtLSBFbnRpdHkgR1JBVklEQTMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTAiIHk9IjUxOCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEwIiB5PSI1NDMiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMCIgeT0iNTE4IiB3aWR0aD0iNzAiIGhlaWdodD0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTAiIHkxPSI1NDMiIHgyPSI4MCIgeTI9IjU0MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iMTYiIHk9IjUzNS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkdyYXZpZGE8L3RleHQ+Cgk8dGV4dCB4PSIxNiIgeT0iNTU3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm9ybmFyZTwvdGV4dD4KCTxsaW5lIHgxPSIxNiIgeTE9IjU1OS42IiB4Mj0iNTEiIHkyPSI1NTkuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgo8L2c+Cgo8IS0tIEVudGl0eSBBTlRFMyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMjIiIHk9IjUxMSIgd2lkdGg9IjUwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iNTM2IiB3aWR0aD0iNTAiIGhlaWdodD0iMzkiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTIyIiB5PSI1MTEiIHdpZHRoPSI1MCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMjIiIHkxPSI1MzYiIHgyPSIxNzIiIHkyPSI1MzYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9IjEzMCIgeT0iNTI4Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+QW50ZTwvdGV4dD4KCTx0ZXh0IHg9IjEyOCIgeT0iNTUwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnZpdGFlPC90ZXh0PgoJPGxpbmUgeDE9IjEyOCIgeTE9IjU1Mi42IiB4Mj0iMTUyIiB5Mj0iNTUyLjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTx0ZXh0IHg9IjEyOCIgeT0iNTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPnRlbXBvcjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQU5URTQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNjQ5IiB5PSI1MTEiIHdpZHRoPSI1MCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI2NDkiIHk9IjUzNiIgd2lkdGg9IjUwIiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjY0OSIgeT0iNTExIiB3aWR0aD0iNTAiIGhlaWdodD0iNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNjQ5IiB5MT0iNTM2IiB4Mj0iNjk5IiB5Mj0iNTM2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSI2NTciIHk9IjUyOC43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkFudGU8L3RleHQ+Cgk8dGV4dCB4PSI2NTUiIHk9IjU1MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj52aXRhZTwvdGV4dD4KCTxsaW5lIHgxPSI2NTUiIHkxPSI1NTIuNiIgeDI9IjY3OSIgeTI9IjU1Mi42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSI2NTUiIHk9IjU2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj50ZW1wb3I8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Extensions-du-mod%C3%A8le\">Extensions du modèle<a class=\"anchor-link\" href=\"#Extensions-du-mod%C3%A8le\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Entit%C3%A9-faible-(ou-identification-relative)\">Entité faible (ou identification relative)<a class=\"anchor-link\" href=\"#Entit%C3%A9-faible-(ou-identification-relative)\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Préfixez d'un tiret bas (<code>_</code>) une cardinalité 11 pour indiquer que l'entité distinguée est faible.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [35]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nŒUVRE: Cote œuvre, Titre, Date parution\nDF, 1N ŒUVRE, _11 EXEMPLAIRE\nEXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTQiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMzU0IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNTQiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjYxIiB5MT0iNTYiIHgyPSIxNjIiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNzgiIHkxPSI1NiIgeDI9IjE2MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTYyIiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTQ5IiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTE4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTg4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjE4OCIgeTE9Ijc0IiB4Mj0iMjA2IiB5Mj0iNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IE9FVVZSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTEzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsWSVVZSRTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Db3RlIMWTdXZyZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iOTQiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5UaXRyZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZSBwYXJ1dGlvbjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVhFTVBMQUlSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMTEiIHk9IjkiIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjExIiB5PSIzOSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTEiIHk9IjkiIHdpZHRoPSIxMzQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjExIiB5MT0iMzkiIHgyPSIzNDUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjE5IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVYRU1QTEFJUkU8L3RleHQ+Cgk8dGV4dCB4PSIyMTkiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gZXhlbXBsYWlyZTwvdGV4dD4KCTxsaW5lIHgxPSIyMTkiIHkxPSI1OSIgeDI9IjMyNyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMjE5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij7DiXRhdCBkdSBsaXZyZTwvdGV4dD4KCTx0ZXh0IHg9IjIxOSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkRhdGUgZOKAmWFjaGF0PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans le diagramme, les identifiants (ou plutôt, discriminateurs) d'une telle entité seront soulignés en pointillés, tandis que le 11 sera par défaut souligné d'un trait plein.</p>\n<p>Notez qu'un discriminateur n'est pas toujours obligatoire :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [36]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> \nEmployé: Num. employé, Nom employé, Prénom employé\nDf, _11 Conjoint, 01 Employé\nConjoint: _Nom conjoint, Prénom conjoint\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNjIiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMzYyIDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNjIiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjI5MiIgeTE9IjU2IiB4Mj0iMTgyIiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzEiIHkxPSI1NiIgeDI9IjE4MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTgyIiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTY5IiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjA4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjIwOCIgeTE9Ijc0IiB4Mj0iMjI2IiB5Mj0iNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxMzgiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVNUExPWUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjEzMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FbXBsb3nDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIGVtcGxvecOpPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSIxMTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob20gZW1wbG95w6k8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByw6lub20gZW1wbG95w6k8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTkpPSU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIzMSIgeT0iMTgiIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjMxIiB5PSI0OCIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzEiIHk9IjE4IiB3aWR0aD0iMTIyIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIzMSIgeTE9IjQ4IiB4Mj0iMzUzIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI1MSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db25qb2ludDwvdGV4dD4KCTx0ZXh0IHg9IjIzOSIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Tm9tIGNvbmpvaW50PC90ZXh0PgoJPHRleHQgeD0iMjM5IiB5PSI4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tIGNvbmpvaW50PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Son absence implique cependant que l'occurrence de l'entité forte qui « renforce » une occurrence de l'entité faible ne peut en renforcer une autre : d'où la cardinalité maximale 1 sur la patte distinguant EMPLOYÉ.</p>\n<p>Mocodo rejettera donc la version « polygame » du MCD précédent (avec 0N à la place de 01) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [37]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nEmployé: Num. employé, Nom employé, Prénom employé\nDf, _11 Conjoint, 0N Employé\nConjoint: _Nom conjoint, Prénom conjoint\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.50 - L'entité faible « CONJOINT » devrait avoir un discriminateur.</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"H%C3%A9ritage-(g%C3%A9n%C3%A9ralisation-/-sp%C3%A9cialisation)\">Héritage (généralisation / spécialisation)<a class=\"anchor-link\" href=\"#H%C3%A9ritage-(g%C3%A9n%C3%A9ralisation-/-sp%C3%A9cialisation)\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'héritage permet de regrouper dans une entité, dite « mère », les attributs communs à plusieurs autres entités, dites « filles », qui se distinguent les unes des autres par des attributs spécifiques.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour définir une spécialisation, insérez une ligne spécifiant :</p>\n<p>$$\n\\overbrace{\\texttt{/}\\,\\texttt{XT}\\,\\texttt{\\\\}}^{\\text{sa nature entre barres obliques}}\n\\qquad\n\\overbrace{\\texttt{&lt;}\\,\\texttt{-}}^{\\text{son type de flèche}}\n\\qquad\n\\overbrace{\\texttt{mère}}^{\\text{une entité}}\n\\qquad\n\\overbrace{\\texttt{,}}^{\\text{une virgule}}\n\\qquad\n\\overbrace{\\texttt{fille 1, fille 2, fille 3}}^{\\text{des entités séparées par des virgules}}\n\\qquad\n\\overbrace{\\texttt{: discriminateur}}^{\\text{optionnellement, un attribut}}\n$$</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [38]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nPersonne: num SS, nom, prénom\n\n/XT\\ Personne &lt;- Homme, Femme: sexe\n\nHomme: \n:\nFemme: nom de jeune fille\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiB2aWV3Qm94PSIwIDAgMjk2IDI3MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBQRVJTT05ORV9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjEzMCIgeTE9IjU2IiB4Mj0iMTMwIiB5Mj0iMTUyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxMzAgMTAzIDEzNiAxMTUgMTMwIDExMSAxMjQgMTE1IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSI0OCIgeTE9IjIzMSIgeDI9IjEzMCIgeTI9IjE1MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMjMiIHkxPSIyMzEiIHgyPSIxMzAiIHkyPSIxNTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cG9seWdvbiBwb2ludHM9IjEzMCAxMjMuMTMgMTA1IDE2Ni40MyAxNTUgMTY2LjQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTE4IiB5PSIxNTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+WFQ8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gRW50aXR5IFBFUlNPTk5FIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijc3IiB5PSI5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijc3IiB5PSIzOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI3NyIgeT0iOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI3NyIgeTE9IjM5IiB4Mj0iMTgzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9Ijg2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBlcnNvbm5lPC90ZXh0PgoJPHRleHQgeD0iODUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBTUzwvdGV4dD4KCTxsaW5lIHgxPSI4NSIgeTE9IjU5IiB4Mj0iMTMxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI4NSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iODUiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcsOpbm9tPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBIT01NRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIyMTAiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyNDAiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMTAiIHdpZHRoPSI3OCIgaGVpZ2h0PSI0MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMjQwIiB4Mj0iODciIHkyPSIyNDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIyMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ib21tZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRkVNTUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMDEiIHdpZHRoPSIxMjgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMzEiIHdpZHRoPSIxMjgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMDEiIHdpZHRoPSIxMjgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTU5IiB5MT0iMjMxIiB4Mj0iMjg3IiB5Mj0iMjMxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOTQiIHk9IjIyMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZlbW1lPC90ZXh0PgoJPHRleHQgeD0iMTY3IiB5PSIyNDguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGRlIGpldW5lIGZpbGxlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Inscrivez dans le triangle les symboles de votre choix pour prendre une part active aux guerres culturelles de notre temps :</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<table>\n<thead>\n<tr>\n<th>Totalité</th>\n<th>Exclusion</th>\n<th style=\"text-align:center\">Symboles</th>\n<th style=\"text-align:center\">Exemple de population</th>\n<th style=\"text-align:left\">Toute personne est :</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>oui</td>\n<td>oui</td>\n<td style=\"text-align:center\"><code>/XT\\</code></td>\n<td style=\"text-align:center\"><big>♂♂♂♂♂♂♂<br/>♀♀♀♀♀♀♀♀♀♀</big></td>\n<td style=\"text-align:left\">- soit un homme<br/>- soit une femme</td>\n</tr>\n<tr>\n<td>non</td>\n<td>oui</td>\n<td style=\"text-align:center\"><code>/X\\</code></td>\n<td style=\"text-align:center\"><big>♂♂♂♂♂♂♂♂<br/>♀♀♀♀♀♀<br/>○○○○</big></td>\n<td style=\"text-align:left\">- soit un homme<br/>- soit une femme<br/>- soit aucun des deux</td>\n</tr>\n<tr>\n<td>oui</td>\n<td>non</td>\n<td style=\"text-align:center\"><code>/T\\</code></td>\n<td style=\"text-align:center\"><big>♂♂♂♂♂♂<br/>♀♀♀♀♀♀♀♀<br/>⚥⚥⚥⚥</big></td>\n<td style=\"text-align:left\">- soit un homme<br/>- soit une femme<br/>- soit les deux à la fois</td>\n</tr>\n<tr>\n<td>non</td>\n<td>non</td>\n<td style=\"text-align:center\"><code>/\\</code></td>\n<td style=\"text-align:center\"><big>♂♂♂♂♂<br/>♀♀♀♀♀♀<br/>○○○○<br/>⚥⚥⚥⚥</big></td>\n<td style=\"text-align:left\">- soit un homme<br/>- soit une femme<br/>- soit aucun des deux<br/>- soit les deux à la fois</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Contrainte-inter-associations\">Contrainte inter-associations<a class=\"anchor-link\" href=\"#Contrainte-inter-associations\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour définir une telle contrainte, ajoutez n'importe où une ligne spécifiant :</p>\n<p>$$\n\\overbrace{\\texttt{(}\\,\\texttt{FOO}\\,\\texttt{)}}^{\\text{son nom entre parenthèses}}\n\\quad\n\\overbrace{\n    \\texttt{-}\\,\\texttt{&gt;}\n    \\texttt{boîte 1,}\n    \\quad\n    \\texttt{.}\\,\\texttt{.}\n    \\texttt{boîte 2,}\n    \\quad\n    \\texttt{-}\\,\\texttt{-}\n    \\texttt{boîte 3,}\n    \\quad\n    \\texttt{boîte 4}\n}^{\\text{les types de liens et les boîtes qu'elle met en jeu, séparés par des virgules}}\n\\quad\n\\overbrace{\\texttt{:}\\,\\,\\texttt{horizontale, verticale}}^{\\text{optionnellement, ses coordonnées}}\n$$</p>\n<p><strong>Précisions.</strong></p>\n<ul>\n<li>Comme leur nom ne l'indique pas, ces contraintes peuvent aussi bien porter sur des entités que des associations.</li>\n<li>Le nom d'une contrainte peut être formé de zéro à trois symboles quelconques.</li>\n<li>Un lien est soit vide (trait invisible), soit formé d'un ou plusieurs symboles <code>-</code> (trait plein) ou <code>.</code> (trait pointillé), optionnellement précédés d'un symbole <code>&lt;</code> (flèche vers la contrainte) et/ou suivis d'un symbole <code>&gt;</code> (flèche vers la boîte).</li>\n<li>Au contraire des boîtes (entités et associations), les contraintes ne sont pas... contraintes par la grille sous-jacente : la mise en page du MCD n'en tient absolument pas compte. Celui de l'exemple ci-dessous a donc dû être « aéré » avec des <code>:</code> pour leur faire de la place.</li>\n<li>Les clauses de définition des contraintes peuvent apparaître n'importe où. Notez cependant que tout réarrangement automatique les enverra systématiquement à la fin du texte-source.</li>\n<li>Chaque coordonnée du centre de la contrainte peut être exprimée sous la forme :<ul>\n<li>d'une référence à une boîte sur laquelle l'aligner horizontalement ou verticalement (respectivement) ;</li>\n<li>d'un pourcentage de la largeur ou de la hauteur (respectivement) du MCD.</li>\n</ul>\n</li>\n<li>En l'absence de coordonnées, la contrainte est placée au barycentre des boîtes qu'elle relie.</li>\n</ul>\n<p>Voici un exemple concret, adapté de la Fig. 7.37 de <em>Merise, deuxième génération</em> (Dominique Nanci et Bernard Espinasse, 4e éd., 2001) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [39]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\n:::\nDépôt: num dépôt, surface\n\n:\nLouer, 11 Commande, 0N Dépôt\n:\nStocker, 1N Dépôt, 1N Article: quantité\n\nCommande: num. commande, date\nComposer, 1N Commande, 0N Article\n:\nArticle: réf. article, prix\n\n(I) -&gt;Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiB2aWV3Qm94PSIwIDAgNDE3IDI3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IElfQ09OU1RSQUlOVF8jMSAtLT4KPGc+Cgk8cG9seWdvbiBwb2ludHM9IjMyMCAxNTEuMjggMzEwLjI1IDE2MC40OSAzMTIuMzQgMTUzLjU5IDMwNi43OCAxNDkuMCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTM4IiB4Mj0iMjYzLjUiIHkyPSIxNjguMzMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iNDciIHgyPSIyNjMuNSIgeTI9IjE2OC4zMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMjI5IiB4Mj0iMjYzLjUiIHkyPSIxNjguMzMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtZGFzaGFycmF5PSIwLDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJPGxpbmUgeDE9IjIxMCIgeTE9IjIyOSIgeDI9IjI2My41IiB5Mj0iMTY4LjMzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIxMCIgeTE9IjEzOCIgeDI9IjI2My41IiB5Mj0iMTY4LjMzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjYzLjUiIGN5PSIxNjguMzMiIHI9IjEyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjI2MSIgeT0iMTcyLjUzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBzdHlsZT0icG9pbnRlci1ldmVudHM6IG5vbmU7Ij5JPC90ZXh0PgoJPC9nPgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIExPVUVSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2OSIgeTE9IjIyOSIgeDI9IjIxMCIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNjQiIHkxPSI0NyIgeDI9IjIxMCIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMzEgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTcwIFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI0NSAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxODkgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE3NSIgeT0iMTA5IiB3aWR0aD0iNzAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNzUiIHkxPSIxMzciIHgyPSIyNDUiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxODIiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkxvdWVyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA5Ljg0IiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjI5NyIgeT0iNjguOTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBTVE9DS0VSIC0tPgo8Zz4KCTxsaW5lIHgxPSIzNjQiIHkxPSI0NyIgeDI9IjM2NCIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNjQiIHkxPSIyMjkiIHgyPSIzNjQiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMzk0IDEwOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxMzcgaC04OCBWMTIzIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik00MDggMTM3IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzM0IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTM3IEg4OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzMjAiIHk9IjEwOSIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzIwIiB5MT0iMTM3IiB4Mj0iNDA4IiB5Mj0iMTM3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzI3IiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TdG9ja2VyPC90ZXh0PgoJCTx0ZXh0IHg9IjMyNyIgeT0iMTU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM2OSIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzNjkiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTVBPU0VSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2OSIgeTE9IjIyOSIgeDI9IjIxMCIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNjQiIHkxPSIyMjkiIHgyPSIyMTAiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQ4IDIwMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMjggaC0xMDQgVjIxNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjYyIDIyOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3MiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOCBIMTA0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE1OCIgeT0iMjAwIiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTU4IiB5MT0iMjI4IiB4Mj0iMjYyIiB5Mj0iMjI4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTY1IiB5PSIyMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21wb3NlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEzNCIgeT0iMjQ1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyOTciIHk9IjI0NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBERVBPVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMjEiIHk9IjkiIHdpZHRoPSI4NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9IjM5IiB3aWR0aD0iODYiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzIxIiB5PSI5IiB3aWR0aD0iODYiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzIxIiB5MT0iMzkiIHgyPSI0MDciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzM3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkTDqXDDtHQ8L3RleHQ+Cgk8dGV4dCB4PSIzMjkiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBkw6lww7R0PC90ZXh0PgoJPGxpbmUgeDE9IjMyOSIgeTE9IjU5IiB4Mj0iMzk4IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMjkiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnN1cmZhY2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjE5MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMjEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTIwIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIyMjEiIHgyPSIxMjkiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyIiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIyMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjI0MSIgeDI9IjEyMSIgeTI9IjI0MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQVJUSUNMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMjEiIHk9IjE5MSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iMjIxIiB3aWR0aD0iODYiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzIxIiB5PSIxOTEiIHdpZHRoPSI4NiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMjEiIHkxPSIyMjEiIHgyPSI0MDciIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMzMCIgeT0iMjEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXJ0aWNsZTwvdGV4dD4KCTx0ZXh0IHg9IjMyOSIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnLDqWYuIGFydGljbGU8L3RleHQ+Cgk8bGluZSB4MT0iMzI5IiB5MT0iMjQxIiB4Mj0iMzkzIiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzI5IiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJpeDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Article</strong> (<u>réf. article</u>, prix)</li>\n<li><strong>Commande</strong> (<u>num. commande</u>, date, <em>#num dépôt</em>)</li>\n<li><strong>Composer</strong> (<u><em>#num. commande</em></u>, <u><em>#réf. article</em></u>)</li>\n<li><strong>Dépôt</strong> (<u>num dépôt</u>, surface)</li>\n<li><strong>Stocker</strong> (<u><em>#num dépôt</em></u>, <u><em>#réf. article</em></u>, quantité)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez que pour Mocodo, ces contraintes sont purement décoratives : le passage au niveau relationnel ou physique n'en tient pas compte.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Agr%C3%A9gat-(ou-pseudo-entit%C3%A9)\">Agrégat (ou pseudo-entité)<a class=\"anchor-link\" href=\"#Agr%C3%A9gat-(ou-pseudo-entit%C3%A9)\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans le MCD ci-dessous, le petit rond et l'enveloppe pointillée indiquent qu'une réservation d'une chambre donnée à une date donnée ne peut être faite que par un seul client :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [40]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --colors ocean # changement de palette pour faire apparaître un fond semi-transparent \nDate: Date\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\nChambre: Num. chambre, Prix\n\nClient: Id. client\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiB2aWV3Qm94PSIwIDAgMzg0IDE5NyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIxNjciIGN5PSIxMTMiIHI9IjYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjYzBkNGZmNTUiLz4KCTxsaW5lIHgxPSIxNjciIHkxPSIxNDkiIHgyPSIxNjciIHkyPSI1NiIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMTEiIHkxPSI1NiIgeDI9IjE2NyIgeTI9IjU2IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNTYiIHgyPSIxNjciIHkyPSI1NiIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMCAxMyBMMzY0IDEzIGE3IDcgMCAwIDEgNyA3IEwzNzEgOTIgYTcgNyAwIDAgMSAtNyA3IEwyMCA5OSBhNyA3IDAgMCAxIC03IC03IEwxMyAyMCBhNyA3IDAgMCAxIDcgLTciIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjMiLz4KCQk8cGF0aCBkPSJNMjAgMTMgTDM2NCAxMyBhNyA3IDAgMCAxIDcgNyBMMzcxIDkyIGE3IDcgMCAwIDEgLTcgNyBMMjAgOTkgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yMDMgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMDAgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiNiMmJiYTQiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMTcgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMzEgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTAwIiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNyIgeT0iMjciIHdpZHRoPSIxMDAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjODU5NTZiIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMTciIHkxPSI1NSIgeDI9IjIxNyIgeTI9IjU1IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTI0IiB5PSI0OC4zIiBmaWxsPSIjMjczNjBjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDqXNlcnZlcjwvdGV4dD4KCQk8dGV4dCB4PSIxMjQiIHk9IjczLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkR1csOpZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE3NyIgeT0iMTA2IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMjciIHk9Ijc3IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI4OCIgeT0iNzciIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREFURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxOCIgeT0iMjYiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iNTYiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iMjYiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxOCIgeTE9IjU2IiB4Mj0iNzgiIHkyPSI1NiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjciIHk9IjQ3LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjI2IiB5PSI3My4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPGxpbmUgeDE9IjI2IiB5MT0iNzYiIHgyPSI1NyIgeTI9Ijc2IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBDSEFNQlJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI1NiIgeT0iMTgiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjU2IiB5PSI0OCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNTYiIHk9IjE4IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI1NiIgeTE9IjQ4IiB4Mj0iMzY2IiB5Mj0iNDgiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3MSIgeT0iMzkuMyIgZmlsbD0iIzEzMTExNCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DaGFtYnJlPC90ZXh0PgoJPHRleHQgeD0iMjY0IiB5PSI2NS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIGNoYW1icmU8L3RleHQ+Cgk8bGluZSB4MT0iMjY0IiB5MT0iNjgiIHgyPSIzNTgiIHkyPSI2OCIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI2NCIgeT0iODIuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEyOCIgeT0iMTE5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTI4IiB5PSIxNDkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMjgiIHk9IjExOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEyOCIgeTE9IjE0OSIgeDI9IjIwNiIgeTI9IjE0OSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTM3IiB5PSIxNDAuMyIgZmlsbD0iIzEzMTExNCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSIxMzYiIHk9IjE2Ni4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5JZC4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjEzNiIgeTE9IjE2OSIgeDI9IjE5MCIgeTI9IjE2OSIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La syntaxe est minimale : une simple barre oblique <code>/</code> avant la cardinalité de l'entité-cible.</p>\n<p>S'il y a au maximum deux entités à agréger, et que l'angle formé par l'association et les entités est plat ou rectangle, une enveloppe de points matérialise la pseudo-entité.</p>\n<p>Sinon, pour des raisons de simplicité du code et de clarté du diagramme, l'enveloppe n'est pas affichée. Cependant, le petit rond subsiste et le reste des traitements est bien sûr inchangé.</p>\n<p><strong>Remarques.</strong></p>\n<ul>\n<li>La représentation traditionnelle demanderait à insérer une association DF entre CLIENT et RÉSERVER. Mais permettre l'association d'une entité et d'une association demanderait à apporter au code de Mocodo des changements conséquents, pour un bénéfice qui ne nous saute pas forcément aux yeux.</li>\n<li>Les agrégats sur association binaire sont soit inutiles (sur une DF), soit impossibles (sur une non-DF, ils reviennent à permettre à une même occurrence d'entité de renforcer plusieurs occurrences d'une entité faible sans discriminateur). Mocodo les interdit dans les deux cas.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"CIF-%C3%A0-unicit%C3%A9-compl%C3%A8te\">CIF à unicité complète<a class=\"anchor-link\" href=\"#CIF-%C3%A0-unicit%C3%A9-compl%C3%A8te\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La notion d'agrégation n'a pas très bonne presse dans les milieux autorisés. Ceux-ci lui préfèrent généralement celle (équivalente) de contrainte d'intégrité fonctionnelle à unicité complète. Pour rentrer dans leurs bonnes grâces (et désactiver du même coup la visualisation de l'enveloppe et du petit rond), il suffit d'expliciter la contrainte correspondante dans le MCD précédent. Mocodo peut le faire pour vous :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [41]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t create:cifs arrange --seed=12 --colors ocean\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiB2aWV3Qm94PSIwIDAgMzg0IDE5NyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IENJRl9DT05TVFJBSU5UXyMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNjciIHkxPSI1NiIgeDI9IjQ4IiB5Mj0iMTQ5IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iMTI4IDE0OSAxMTYgMTU1IDEyMCAxNDkgMTE2IDE0MyIgZmlsbD0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMTY3IiB5MT0iMTQ5IiB4Mj0iNDgiIHkyPSIxNDkiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzExIiB5MT0iNTYiIHgyPSI0OCIgeTI9IjE0OSIgc3Ryb2tlPSIjODU5NTZiIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0OCIgeTE9IjU2IiB4Mj0iNDgiIHkyPSIxNDkiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI0OCIgY3k9IjE0OSIgcj0iMTMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMzkuNSIgeT0iMTUzLjIiIGZpbGw9IiM4NTk1NmIiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkNJRjwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMTY3IiB5MT0iMTQ5IiB4Mj0iMTY3IiB5Mj0iNTYiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzExIiB5MT0iNTYiIHgyPSIxNjciIHkyPSI1NiIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0OCIgeTE9IjU2IiB4Mj0iMTY3IiB5Mj0iNTYiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjAzIDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTAwIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjE3IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMxIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDEwMCIgZmlsbD0iI2NjZDZiYSIgc3Ryb2tlPSIjY2NkNmJhIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMTciIHk9IjI3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTE3IiB5MT0iNTUiIHgyPSIyMTciIHkyPSI1NSIgc3Ryb2tlPSIjODU5NTZiIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEyNCIgeT0iNDguMyIgZmlsbD0iIzI3MzYwYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6lzZXJ2ZXI8L3RleHQ+CgkJPHRleHQgeD0iMTI0IiB5PSI3My4xIiBmaWxsPSIjNjA3NzM0IiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EdXLDqWU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNzciIHk9IjEwNiIgZmlsbD0iIzcyNmY4MyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjI3IiB5PSI3NyIgZmlsbD0iIzcyNmY4MyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iODgiIHk9Ijc3IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERBVEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTgiIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjU2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTgiIHkxPSI1NiIgeDI9Ijc4IiB5Mj0iNTYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3IiB5PSI0Ny4zIiBmaWxsPSIjMTMxMTE0IiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyNiIgeT0iNzMuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTxsaW5lIHgxPSIyNiIgeTE9Ijc2IiB4Mj0iNTciIHkyPSI3NiIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgQ0hBTUJSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNTYiIHk9IjE4IiB3aWR0aD0iMTEwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI1NiIgeT0iNDgiIHdpZHRoPSIxMTAiIGhlaWdodD0iNDYiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjU2IiB5PSIxOCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNTYiIHkxPSI0OCIgeDI9IjM2NiIgeTI9IjQ4IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNzEiIHk9IjM5LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2hhbWJyZTwvdGV4dD4KCTx0ZXh0IHg9IjI2NCIgeT0iNjUuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjaGFtYnJlPC90ZXh0PgoJPGxpbmUgeDE9IjI2NCIgeTE9IjY4IiB4Mj0iMzU4IiB5Mj0iNjgiIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNjQiIHk9IjgyLjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXg8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMjgiIHk9IjExOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEyOCIgeT0iMTQ5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTI4IiB5PSIxMTkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMjgiIHkxPSIxNDkiIHgyPSIyMDYiIHkyPSIxNDkiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEzNyIgeT0iMTQwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTM2IiB5PSIxNjYuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+SWQuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxMzYiIHkxPSIxNjkiIHgyPSIxOTAiIHkyPSIxNjkiIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --seed=12 --colors ocean\nDate: Date\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\nChambre: Num. chambre, Prix\n\n-INVISIBLE_1, XX Client, XX Client\nClient: Id. client\n:\n\n(CIF) ..Réserver, -&gt;Client, --Chambre, --Date: INVISIBLE_1, INVISIBLE_1\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Remarquez que la visibilité de la CIF est assurée par le positionnement de celle-ci sur une boîte invisible introduite à cet effet : si vous rectifiez ce positionnement, vous pouvez bien sûr supprimer cette boîte.</p>\n<p><a href=\"https://www.developpez.net/forums/d2099422/general-developpement/alm/outils/looping/cif-depliees-compactees/\">Vous avez également le droit</a> d'alléger la visualisation des CIFs <em>complètes</em> en transformant les traits pleins <code>\"--\"</code> des entités émettrices en traits invisibles <code>\"\"</code>. Là encore, Mocodo peut le faire pour vous :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [42]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t create:cifs=light arrange --seed=12 --colors ocean\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiB2aWV3Qm94PSIwIDAgMzg0IDE5NyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODQiIGhlaWdodD0iMTk3IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IENJRl9DT05TVFJBSU5UXyMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNjciIHkxPSI1NiIgeDI9IjQ4IiB5Mj0iMTQ5IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iMTI4IDE0OSAxMTYgMTU1IDEyMCAxNDkgMTE2IDE0MyIgZmlsbD0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMTY3IiB5MT0iMTQ5IiB4Mj0iNDgiIHkyPSIxNDkiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI0OCIgY3k9IjE0OSIgcj0iMTMiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMzkuNSIgeT0iMTUzLjIiIGZpbGw9IiM4NTk1NmIiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkNJRjwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMTY3IiB5MT0iMTQ5IiB4Mj0iMTY3IiB5Mj0iNTYiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzExIiB5MT0iNTYiIHgyPSIxNjciIHkyPSI1NiIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0OCIgeTE9IjU2IiB4Mj0iMTY3IiB5Mj0iNTYiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjAzIDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTAwIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjE3IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMxIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDEwMCIgZmlsbD0iI2NjZDZiYSIgc3Ryb2tlPSIjY2NkNmJhIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMTciIHk9IjI3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTE3IiB5MT0iNTUiIHgyPSIyMTciIHkyPSI1NSIgc3Ryb2tlPSIjODU5NTZiIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEyNCIgeT0iNDguMyIgZmlsbD0iIzI3MzYwYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6lzZXJ2ZXI8L3RleHQ+CgkJPHRleHQgeD0iMTI0IiB5PSI3My4xIiBmaWxsPSIjNjA3NzM0IiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EdXLDqWU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNzciIHk9IjEwNiIgZmlsbD0iIzcyNmY4MyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjI3IiB5PSI3NyIgZmlsbD0iIzcyNmY4MyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iODgiIHk9Ijc3IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERBVEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTgiIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjU2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTgiIHkxPSI1NiIgeDI9Ijc4IiB5Mj0iNTYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3IiB5PSI0Ny4zIiBmaWxsPSIjMTMxMTE0IiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyNiIgeT0iNzMuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTxsaW5lIHgxPSIyNiIgeTE9Ijc2IiB4Mj0iNTciIHkyPSI3NiIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgQ0hBTUJSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNTYiIHk9IjE4IiB3aWR0aD0iMTEwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI1NiIgeT0iNDgiIHdpZHRoPSIxMTAiIGhlaWdodD0iNDYiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjU2IiB5PSIxOCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNTYiIHkxPSI0OCIgeDI9IjM2NiIgeTI9IjQ4IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNzEiIHk9IjM5LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2hhbWJyZTwvdGV4dD4KCTx0ZXh0IHg9IjI2NCIgeT0iNjUuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjaGFtYnJlPC90ZXh0PgoJPGxpbmUgeDE9IjI2NCIgeTE9IjY4IiB4Mj0iMzU4IiB5Mj0iNjgiIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNjQiIHk9IjgyLjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXg8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMjgiIHk9IjExOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEyOCIgeT0iMTQ5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTI4IiB5PSIxMTkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMjgiIHkxPSIxNDkiIHgyPSIyMDYiIHkyPSIxNDkiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEzNyIgeT0iMTQwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTM2IiB5PSIxNjYuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+SWQuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxMzYiIHkxPSIxNjkiIHgyPSIxOTAiIHkyPSIxNjkiIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --seed=12 --colors ocean\nDate: Date\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\nChambre: Num. chambre, Prix\n\n-INVISIBLE_1, XX Client, XX Client\nClient: Id. client\n:\n\n(CIF) ..Réserver, -&gt;Client, Chambre, Date: INVISIBLE_1, INVISIBLE_1\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Limitation.</strong> Au niveau fonctionnel, c'est toujours la barre oblique qui conditionne le traitement des CIF. Par conséquent, les CIF à unicité <em>incomplète</em> ne sont prises en charge qu'au niveau visuel.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Identifiants-explicites-dans-les-associations\">Identifiants explicites dans les associations<a class=\"anchor-link\" href=\"#Identifiants-explicites-dans-les-associations\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo 4.1.1 relaxe par défaut (sauf dans la version en ligne) la contrainte de Merise restreignant aux entités la présence d'identifiants. Si vous l'osez, vous pouvez donc obtenir le même schéma relationnel avec le MCD « allégé » suivant :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [43]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nClient: Id. client\nRéserver, 1N Client, 0N Chambre: _Date, Durée\nChambre: Num. chambre, Prix\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNjQiIGhlaWdodD0iOTQiIHZpZXdCb3g9IjAgMCAzNjQgOTQiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzY0IiBoZWlnaHQ9Ijk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNDgiIHkxPSI0NyIgeDI9IjE2NiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMwMCIgeTE9IjQ3IiB4Mj0iMTY2IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjAyIDEwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjM4IGgtMTAwIFYyNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjE2IDM4IHYzMiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzggSDEwMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMTYiIHk9IjEwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9Ijc0IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTE2IiB5MT0iMzgiIHgyPSIyMTYiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEyMyIgeT0iMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6lzZXJ2ZXI8L3RleHQ+CgkJPHRleHQgeD0iMTIzIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJCTxsaW5lIHgxPSIxMjMiIHkxPSI1OSIgeDI9IjE1NCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJCTx0ZXh0IHg9IjEyMyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RHVyw6llPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMjEiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIxNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjQ3IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTciIHdpZHRoPSI3OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iNDciIHgyPSI4NyIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+SWQuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjY3IiB4Mj0iNzEiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgQ0hBTUJSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNDUiIHk9IjkiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjQ1IiB5PSIzOSIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNDUiIHk9IjkiIHdpZHRoPSIxMTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjQ1IiB5MT0iMzkiIHgyPSIzNTUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjYwIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNoYW1icmU8L3RleHQ+Cgk8dGV4dCB4PSIyNTMiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY2hhbWJyZTwvdGV4dD4KCTxsaW5lIHgxPSIyNTMiIHkxPSI1OSIgeDI9IjM0NyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjUzIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Chambre</strong> (<u>Num. chambre</u>, Prix)</li>\n<li><strong>Réserver</strong> (<u>Id. client</u>, <u><em>#Num. chambre</em></u>, <u>Date</u>, Durée)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'introduction de cette possibilité, surtout destinée à simplifier le plongement des MCD touffus, est discutée <a href=\"#Par-suppression-de-ces-m%C3%AAmes-entit%C3%A9s\">ici</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Conversion-d'un-MCD\">Conversion d'un MCD<a class=\"anchor-link\" href=\"#Conversion-d'un-MCD\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Passage-au-relationnel\">Passage au relationnel<a class=\"anchor-link\" href=\"#Passage-au-relationnel\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il se fait en deux étapes:</p>\n<ul>\n<li>la création d'une représentation <strong>interne</strong> complète du MLD ;</li>\n<li>la traduction de celle-ci en une représentation <strong>externe</strong> dans le ou les formats de sortie souhaités.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour construire la <strong>représentation interne</strong>, l'algorithme de base réalise la séquence d'opérations suivante :</p>\n<ol>\n<li>Pour chaque entité, une relation (table) de même nom et de mêmes attributs est créée. Le ou les identifiants de l'entité constituent la clé primaire de la relation.</li>\n<li>Toute relation issue d'une entité faible est renforcée, c'est-à-dire que la clé primaire de l'entité qu'elle détermine fonctionnellement vient s'adjoindre à sa clé primaire, au besoin de façon récursive.</li>\n<li>Les associations sont traitées ainsi :</li>\n<li>si toutes les pattes de l'association portent la cardinalité maximale N, une relation de même nom et de mêmes attributs est créée. Sa clé primaire est constituée de l'ensemble des clés primaires des relations issues des entités mises en jeu ;</li>\n<li>dans le cas contraire, c'est-à-dire si l'une des pattes de l'association porte la cardinalité (1,1), ou à défaut (0,1), l'entité distinguée se voit adjoindre :\n1. en tant que clés étrangères, l'ensemble des clés primaires des autres entités mises en jeu;\n2. en tant que simples attributs, l'ensemble des attributs de l'association.</li>\n</ol>\n<p><strong>Remarque.</strong> Un couple de cardinalités non standard, c'est-à-dire distinct de (0,1), (1,1), (0,N) et (1,N), est traité comme (0,1) si son deuxième symbole est un 1, et comme (0,N) sinon. Cela couvre en particulier les cas (*, 1), (*,N), (?,?) et (X,X).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour construire la <strong>représentation externe</strong>, Mocodo formate la représentation interne à l'aide d'un gabarit. Près d'une centaine de gabarits sont fournis, qui permettent de produire quatre grandes catégories de résultats :</p>\n<ol>\n<li>le schéma relationnel dans toutes les combinaisons de formats (HTML, Markdown, texte brut, $\\LaTeX$) et d'options (avec ou sans explications, avec ou sans <em>boilerplate</em>, avec ou sans visualisation des contraintes d'unicité et d'optionalité) ;</li>\n<li>le diagramme relationnel au format Mocodo, avec ou sans visualisation des contraintes d'unicité et d'optionalité, ou dans des formats externes, comme DBML ou D2.</li>\n<li>le DDL en SQL ANSI et dans les principaux dialectes (Microsoft SQL Server, MySQL, Oracle DB, PostgreSQL, SQLite), avec ou sans <em>boilerplate</em> de création de la base ;</li>\n<li>le graphe des dépendances.</li>\n</ol>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Niveau-logique\">Niveau logique<a class=\"anchor-link\" href=\"#Niveau-logique\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Sch%C3%A9ma-relationnel\">Schéma relationnel<a class=\"anchor-link\" href=\"#Sch%C3%A9ma-relationnel\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La transformation <code>-t mld</code> opère la conversion d'un MCD (modèle conceptuel de données) en un MLD (modèle logique de données), autrement appelé <strong>schéma relationnel</strong> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [44]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t mld\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Client</strong> (<u>Réf. client</u>, Nom, Prénom, Adresse)</li>\n<li><strong>Commande</strong> (<u>Num. commande</u>, Date, Montant, <em>#Réf. client</em>)</li>\n<li><strong>Inclure</strong> (<u><em>#Num. commande</em></u>, <u><em>#Réf. produit</em></u>, Quantité)</li>\n<li><strong>Produit</strong> (<u>Réf. produit</u>, Libellé, Prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Sous Jupyter Notebook, comme pour toutes les opérations de conversion, le tracé du MCD est omis par défaut. Dans le cas très fréquent où l'on a besoin de visualiser simultanément le MCD et le MLD, on peut invoquer l'option <code>-t</code> sans arguments (ou encore <code>--mld</code>) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [45]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTk0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjQiIHgyPSI0MTkiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzgiIHkxPSI2NCIgeDI9IjQxOSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg2IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDYyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzkwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3NiIgeT0iMzUiIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM3NiIgeTE9IjYzIiB4Mj0iNDYyIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIzODMiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2NyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iODciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzQ3IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzOCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzEiIHkxPSI2NyIgeDI9IjMzOSIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjMxIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDkxIiB5PSI0NyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5MSIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTEiIHkxPSI0NyIgeDI9IjU4NSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDIiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0OTkiIHkxPSI2NyIgeDI9IjU3NCIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDk5IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Client</strong> (<u>Réf. client</u>, Nom, Prénom, Adresse)</li>\n<li><strong>Commande</strong> (<u>Num. commande</u>, Date, Montant, <em>#Réf. client</em>)</li>\n<li><strong>Inclure</strong> (<u><em>#Num. commande</em></u>, <u><em>#Réf. produit</em></u>, Quantité)</li>\n<li><strong>Produit</strong> (<u>Réf. produit</u>, Libellé, Prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Diagramme-relationnel\">Diagramme relationnel<a class=\"anchor-link\" href=\"#Diagramme-relationnel\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La plupart des SGBD offrent une représentation hybride (graphique / texte) de la base sous la forme de tables liées par des flèches. Nous l'appelons <strong>diagramme relationnel</strong>. Sous Mocodo :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [46]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp --colors mondrian -t diagram\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2ODAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjgwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY4MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjZmVmZWVjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gY2xpZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkNMVVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSI0NyIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjE3IiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM1NiIgeTE9IjQ3IiB4Mj0iNDkwIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM4NyIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJPHRleHQgeD0iMzY0IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jTnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI2NyIgeDI9IjQ4MSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQ0OCIgeTI9Ijg0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU0OCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTQ4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU0OCIgeTE9IjQ3IiB4Mj0iNjQyIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU1OSIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU1NiIgeTE9IjY3IiB4Mj0iNjMxIiB5Mj0iNjciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NTYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDkwIDc4LjUgQzUxOSA3MCA1MDkuMzMgNjEuNSA1NDggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1NDggNjEuNSA1MzYgNjcuNSA1NDAgNjEuNSA1MzYgNTUuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ5MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le nom du fichier généré avant rendu graphique se termine par <code>_mld.mcd</code>. L'extension <code>.mcd</code> signifie que Mocodo peut le prendre comme texte-source (bien que ce ne soit pas un schéma conceptuel). Examinons son contenu :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [47]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Code</span><span class=\"p\">(</span><span class=\"s2\">\"ccp_mld.mcd\"</span><span class=\"p\">,</span> <span class=\"n\">language</span><span class=\"o\">=</span><span class=\"s2\">\"text\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[47]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #FF0000 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #0044DD } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.output_html .no { color: #880000 } /* Name.Constant */\n.output_html .nd { color: #AA22FF } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #0000FF } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #bbbbbb } /* Text.Whitespace */\n.output_html .mb { color: #666666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666666 } /* Literal.Number.Float */\n.output_html .mh { color: #666666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #0000FF } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>%%mocodo\n:\nClient: Réf. client, Nom, Prénom, Adresse\n:\nCommande: Num. commande, Date, Montant, #Réf. client &gt; Client &gt; Réf. client\n:\nInclure: #Num. commande &gt; Commande &gt; Num. commande, _#Réf. produit &gt; Produit &gt; Réf. produit, Quantité\n:\nProduit: Réf. produit, Libellé, Prix unitaire\n:\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La syntaxe d'un MLD est effectivement la même que celle d'un MCD, à ceci près que les associations sont remplacées par des liens allant de l'attribut <code>a1</code> de l'entité <code>E1</code> à l'attribut <code>a2</code> de l'entité <code>E2</code>, et notés : <code>E1: ... a1 &gt; E2 &gt; a2</code>.</p>\n<p>Les relations sont placées dans le même ordre que les boîtes du MCD d'origine. Vous devrez quelquefois les réarranger (automatiquement ou manuellement) pour obtenir un résultat plus esthétique. Notez que des boîtes invisibles ont été automatiquement insérées une colonne sur deux afin de laisser de la place aux flèches.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Limitation.</strong> Les clés étrangères composites sont actuellement représentées comme si elles étaient séparées (autant de flèches que de parties).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveautés de la version 4.0.</strong></p>\n<ul>\n<li>Ce qui se notait <code>E1: ... a1-&gt;E2-&gt;a2</code> se note maintenant <code>E1: ... a1 &gt; E2 &gt; a2</code>.</li>\n<li>Sous Jupyter Notebook, un seule étape suffit pour visualiser le diagramme relationnel.</li>\n<li>Le nom du fichier intermédiaire se termine par <code>_mld.mcd</code> au lieu de <code>.mld</code>. L'ancienne extension est abandonnée.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Niveau-physique%C2%A0:-DDL\">Niveau physique : DDL<a class=\"anchor-link\" href=\"#Niveau-physique%C2%A0:-DDL\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"SQL\">SQL<a class=\"anchor-link\" href=\"#SQL\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La principale raison de vivre d'un MCD est de se métamorphoser <em>in fine</em> en une chatoyante base de données relationnelles. Cela se fait au moyen d'un sous-ensemble du langage SQL appelé DDL (<em>Data Definition Language</em>). Sous Mocodo :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [48]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t sql\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Client</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_client</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Nom</span><span class=\"w\">        </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Prenom</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Adresse</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Num_commande</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"nb\">Date</span><span class=\"w\">         </span><span class=\"nb\">DATE</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Montant</span><span class=\"w\">      </span><span class=\"nb\">DECIMAL</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_client</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">Ref_produit</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Num_commande</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_produit</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Quantite</span><span class=\"w\">     </span><span class=\"nb\">INTEGER</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Produit</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Ref_produit</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">Libelle</span><span class=\"w\">       </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">50</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">Prix_unitaire</span><span class=\"w\"> </span><span class=\"nb\">DECIMAL</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Client</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_client</span><span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Produit</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Ref_produit</span><span class=\"p\">);</span>\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Inclure</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">Commande</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">Num_commande</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez le <code>NOT NULL</code> des clés primaires. Il s'agit d'une redondance, mais aussi d'une bonne pratique. Non seulement parce qu'<em>explicit is better than implicit</em> : elle peut se révéler utile, par exemple pour désactiver les contraintes de clé primaire pendant une maintenance tout en continuant à interdire le remplissage avec des <code>NULL</code>. Si cela vous gêne, nous montrons en annexe comment l'éliminer.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Principales nouveautés de la version 4.0.</strong></p>\n<ul>\n<li>Génération automatique des contraintes <code>UNIQUE</code>, <code>NOT NULL</code> et <code>NULL</code> appropriées.</li>\n<li>Les libellés sont convertis en ASCII, et toute suite de caractères qui ne sont ni des lettres, ni des chiffres, ni des tirets bas sont remplacés par un unique tiret bas. Cela simplifie la référence aux tables et aux champs, et évite de noyer le DDL sous un essaim de délimiteurs (qui plus est spécifiques à chaque dialecte). Ainsi, « Réf. client » se trouvera transformé en <code>Ref_client</code>.</li>\n<li>Vos choix de casse (minuscules, MAJUSCULES, <em>snake_case</em>, <em>camelCase</em>, <em>PascalCase</em>, etc.) sont respectés.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Inf%C3%A9rence-de-type\">Inférence de type<a class=\"anchor-link\" href=\"#Inf%C3%A9rence-de-type\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Avec l'option de réécriture <code>-t create:types</code> Mocodo essaiera d'inférer des libellés des attributs tout type manquant. La langue définie avec l'option <code>--language</code> est prioritaire, mais l'anglais prend la relève en cas d'échec.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [49]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t create:types --select rw\nCustomer: Customer ID, Last Name, First Name, Address\nMake Order, 0N Customer, 11 Order\nOrder: Order Number, Date, Amount\nINCLUDE, 1N Order, 0N Product: Quantity\nProduct: Product ID, Description, Unit Price\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --select rw\nCustomer: Customer ID [VARCHAR(8)], Last Name [VARCHAR(255)], First Name [VARCHAR(255)], Address [VARCHAR(30)]\nMake Order, 0N Customer, 11 Order\nOrder: Order Number [VARCHAR(8)], Date [DATE], Amount [DECIMAL(10,2)]\nINCLUDE, 1N Order, 0N Product: Quantity [INTEGER]\nProduct: Product ID [VARCHAR(8)], Description [TEXT], Unit Price [DECIMAL(10,2)]\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il va de soi que les types inférés devront être systématiquement contrôlés, et parfois corrigés ou complétés. Une discussion sur StackOverflow, <a href=\"https://stackoverflow.com/questions/354763/common-mysql-fields-and-their-appropriate-data-types\">Common MySQL fields and their appropriate data types</a>, a servi de point de départ. La liste des types utilisée est <a href=\"https://en.wikibooks.org/wiki/Structured_Query_Language/Data_Types\">celle de Wikipedia</a>. Consultez les correspondances spécifiées dans <code>mocodo/resources/default_datatypes_fr.tsv</code>, etc. pour plus de détails, et n'hésitez pas à <a href=\"https://github.com/laowantong/mocodo/issues/new\">ouvrir le débat</a> si vous avez des corrections ou des suggestions.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Si vous préférez tout typer à la main, vous pouvez au moins créer les « cases » à remplir :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [50]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t create:types=[] --select rw\nCustomer: Customer ID, Last Name, First Name, Address\nMake Order, 0N Customer, 11 Order\nOrder: Order Number, Date, Amount\nINCLUDE, 1N Order, 0N Product: Quantity\nProduct: Product ID, Description, Unit Price\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --select rw\nCustomer: Customer ID [], Last Name [], First Name [], Address []\nMake Order, 0N Customer, 11 Order\nOrder: Order Number [], Date [], Amount []\nINCLUDE, 1N Order, 0N Product: Quantity []\nProduct: Product ID [], Description [], Unit Price []\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Dialectes-de-SQL\">Dialectes de SQL<a class=\"anchor-link\" href=\"#Dialectes-de-SQL\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'argument <code>sql</code> peut être remplacé par un nom de dialecte parmi <code>mysql</code>, <code>oracle</code>, <code>postgresql</code>, <code>sqlite</code> et (nouveauté de la version 4) <code>mssql</code>. Quelques transformations seront alors appliquées au code-source généré. Du fait de l'uniformisation de la syntaxe apportée par la version 4, elles sont assez minimes.</p>\n<p>Notez les points suivants :</p>\n<ul>\n<li>Mocodo ne touche pas aux types spécifiés par l'utilisateur. Une traduction inter-dialectes automatique est envisageable dans le futur, mais c'est un problème qui n'a en réalité aucune solution satisfaisante.</li>\n<li>Mocodo protège les noms de tables ou de colonnes qui se trouveraient faire partie des mots réservés par le dialecte-cible. Par exemple, ci-dessous, les noms <code>USER</code> et <code>MEMBER</code> sont réservés en MySQL. Les listes viennent du site <a href=\"https://modern-sql.com\">modern-sql.com</a> de Markus Winand, et plus précisément de la page <a href=\"https://modern-sql.com/reserved-words-empirical-list\">https://modern-sql.com/reserved-words-empirical-list</a>.</li>\n<li>Avec la sous-sous-option <code>b</code>, un <em>boilerplate</em> de création de la base est ajouté en préambule.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [51]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mysql:b\nUSER: username, mail, member\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl_mysql.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">DATABASE</span><span class=\"w\"> </span><span class=\"k\">IF</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">EXISTS</span><span class=\"w\"> </span><span class=\"o\">`</span><span class=\"n\">MCD</span><span class=\"o\">`</span>\n<span class=\"w\">  </span><span class=\"nb\">CHARACTER</span><span class=\"w\"> </span><span class=\"k\">SET</span><span class=\"w\"> </span><span class=\"n\">utf8mb4</span>\n<span class=\"w\">  </span><span class=\"k\">COLLATE</span><span class=\"w\"> </span><span class=\"n\">utf8mb4_general_ci</span>\n<span class=\"p\">;</span>\n<span class=\"n\">USE</span><span class=\"w\"> </span><span class=\"o\">`</span><span class=\"n\">MCD</span><span class=\"o\">`</span><span class=\"p\">;</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"o\">`</span><span class=\"k\">USER</span><span class=\"o\">`</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">username</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">mail</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"o\">`</span><span class=\"n\">member</span><span class=\"o\">`</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Notes-sur-les-r%C3%A8gles-de-passage\">Notes sur les règles de passage<a class=\"anchor-link\" href=\"#Notes-sur-les-r%C3%A8gles-de-passage\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"G%C3%A9n%C3%A9ration-de-contraintes-d'optionalit%C3%A9-et-d'unicit%C3%A9\">Génération de contraintes d'optionalité et d'unicité<a class=\"anchor-link\" href=\"#G%C3%A9n%C3%A9ration-de-contraintes-d'optionalit%C3%A9-et-d'unicit%C3%A9\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Avec la sous-sous-option <code>c</code>, Mocodo peut faire apparaître dès le niveau logique certaines contraintes du niveau physique. Les notations sont les suivantes :</p>\n<table>\n<thead>\n<tr>\n<th>Contrainte</th>\n<th style=\"text-align:left\">niveau logique</th>\n<th style=\"text-align:left\">niveau physique</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>non-optionalité</td>\n<td style=\"text-align:left\">attribut!</td>\n<td style=\"text-align:left\"><code>NOT NULL</code></td>\n</tr>\n<tr>\n<td>optionalité</td>\n<td style=\"text-align:left\">attribut?</td>\n<td style=\"text-align:left\"><code>NULL</code></td>\n</tr>\n<tr>\n<td>unicité</td>\n<td style=\"text-align:left\">attribut $^{u1\\ u2...}$</td>\n<td style=\"text-align:left\"><code>UNIQUE</code></td>\n</tr>\n</tbody>\n</table>\n<p>Par exemple, ci-dessous, la clé étrangère <em>#Réf_client</em> est maintenant marquée comme <strong>non optionnelle</strong> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [52]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t mld:c\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Client</strong> (<u>Réf. client</u>, Nom, Prénom, Adresse)</li>\n<li><strong>Commande</strong> (<u>Num. commande</u>, Date, Montant, <em>#Réf. client!</em>)</li>\n<li><strong>Inclure</strong> (<u><em>#Num. commande</em></u>, <u><em>#Réf. produit</em></u>, Quantité)</li>\n<li><strong>Produit</strong> (<u>Réf. produit</u>, Libellé, Prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La clé étrangère <em>#id entreprise</em> est marquée comme <strong>optionnelle</strong> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [53]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nEntreprise: id. entreprise, raison, activité, adresse\nEnvoyer, 0N Entreprise, 01 Participant\nParticipant: id. inscrit, nom, adresse\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNDA4IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTlZPWUVSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2OCIgeTE9IjY0IiB4Mj0iMjAyIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzM4IiB5MT0iNjQiIHgyPSIyMDIiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMzQgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05MiBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI0OCA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg5MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjM1IiB3aWR0aD0iOTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTYiIHkxPSI2MyIgeDI9IjI0OCIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTY0IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVudm95ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzIiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyNTQiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVFJFUFJJU0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW50cmVwcmlzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gZW50cmVwcmlzZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTAxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmFpc29uPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFjdGl2aXTDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBBUlRJQ0lQQU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3NyIgeT0iMTciIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc3IiB5PSI0NyIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzciIHk9IjE3IiB3aWR0aD0iMTIyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NyIgeTE9IjQ3IiB4Mj0iMzk5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4NSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QYXJ0aWNpcGFudDwvdGV4dD4KCTx0ZXh0IHg9IjI4NSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGluc2NyaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjciIHgyPSIzNDMiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI4NSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iMjg1IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Entreprise</strong> (<u>id. entreprise</u>, raison, activité, adresse)</li>\n<li><strong>Participant</strong> (<u>id. inscrit</u>, nom, adresse, <em>#id. entreprise?</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La clé étrangère <em>#id employé</em> est marquée comme <strong>unique</strong> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [54]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nEMPLOYÉ: id. employé, nom employé\nDIRIGER, 11 DÉPARTEMENT, 01 EMPLOYÉ\nDÉPARTEMENT: id. département, nom département\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MjYiIGhlaWdodD0iOTQiIHZpZXdCb3g9IjAgMCA0MjYgOTQiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iNDI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBESVJJR0VSIC0tPgo8Zz4KCTxsaW5lIHgxPSIzNDAiIHkxPSI0NyIgeDI9IjE4OCIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjYxIiB5MT0iNDciIHgyPSIxODgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMjAgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC05MiBWMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIzNCA0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE1NiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjQ2IEg5MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNDIiIHk9IjE4IiB3aWR0aD0iOTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNDIiIHkxPSI0NiIgeDI9IjIzNCIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTUwIiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRJUklHRVI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNDAiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIxMTgiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVNUExPWUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjExMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FTVBMT1nDiTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gZW1wbG95w6k8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9Ijg5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGVtcGxvecOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBERVBBUlRFTUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNjMiIHk9IjkiIHdpZHRoPSIxNTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjYzIiB5PSIzOSIgd2lkdGg9IjE1NCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjMiIHk9IjkiIHdpZHRoPSIxNTQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjYzIiB5MT0iMzkiIHgyPSI0MTciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjcxIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkTDiVBBUlRFTUVOVDwvdGV4dD4KCTx0ZXh0IHg9IjI3MSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGTDqXBhcnRlbWVudDwvdGV4dD4KCTxsaW5lIHgxPSIyNzEiIHkxPSI1OSIgeDI9IjM3MCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjcxIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>DÉPARTEMENT</strong> (<u>id. département</u>, nom département, <em>#id. employé!</em> <sup>u1</sup>)</li>\n<li><strong>EMPLOYÉ</strong> (<u>id. employé</u>, nom employé)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Ajout-manuel-de-contraintes-d'optionalit%C3%A9-et-d'unicit%C3%A9\">Ajout manuel de contraintes d'optionalité et d'unicité<a class=\"anchor-link\" href=\"#Ajout-manuel-de-contraintes-d'optionalit%C3%A9-et-d'unicit%C3%A9\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les contraintes <code>NOT NULL</code> ou <code>NULL</code> spécifiées dans les types peuvent également faire l'objet d'une visualisation au niveau relationnel :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [55]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mld:c\nPersonne: id. personne [VARCHAR(8)], nom [VARCHAR(255) NOT NULL], prénom [VARCHAR(255)], nom de jeune fille [VARCHAR(255) NULL]\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Personne</strong> (<u>id. personne</u>, nom!, prénom, nom de jeune fille?)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour les contraintes d'unicité, qui peuvent s'appliquer à <em>plusieurs groupes</em> d'attributs potentiellement <em>non disjoints</em>, la notation est un peu plus complexe. Voici un exemple <a href=\"https://github.com/laowantong/mocodo/issues/79\">proposé par Fabien Duchateau</a> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [56]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c --shapes trebuchet # changement de police de caractères pour mieux distinguer les 1 des I\nCLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjIiIGhlaWdodD0iMTQyIiB2aWV3Qm94PSIwIDAgMTIyIDE0MiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMjIiIGhlaWdodD0iMTQyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iMjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzMiIHk9IjM1IiB3aWR0aD0iODAiIGhlaWdodD0iOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzUiIHdpZHRoPSIyNCIgaGVpZ2h0PSI5OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzMiIHkxPSIzNSIgeDI9IjMzIiB5Mj0iMTMzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC4yNSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iMTI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzNSIgeDI9IjExMyIgeTI9IjM1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPC9nPgoJPHRleHQgeD0iMzgiIHk9IjI3LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPkNMSUVOVDwvdGV4dD4KCTx0ZXh0IHg9IjM4IiB5PSI1My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSIxNCIgeT0iNTMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+SUQ8L3RleHQ+Cgk8bGluZSB4MT0iMzgiIHkxPSI1NiIgeDI9IjEwNyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzgiIHk9IjcxLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE2IiB5PSI3MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4xPC90ZXh0PgoJPHRleHQgeD0iMzgiIHk9Ijg5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPlByw6lub208L3RleHQ+Cgk8dGV4dCB4PSIxNiIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MTwvdGV4dD4KCTx0ZXh0IHg9IjM4IiB5PSIxMDcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+QWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjIwIiB5PSIxMDcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCIvPgoJPHRleHQgeD0iMzgiIHk9IjEyNS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5NYWlsPC90ZXh0PgoJPHRleHQgeD0iMTYiIHk9IjEyNS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4yPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>CLIENT</strong> (<u>Réf. client</u>, Nom <sup>u1</sup>, Prénom <sup>u1</sup>, Adresse, Mail <sup>u2</sup>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>C'est l'occasion d'introduire quelques définitions :</p>\n<ul>\n<li>On appelle <strong>identifiant candidat</strong> d'une entité tout sous-ensemble minimal d'attributs dont chaque occurrence est unique.</li>\n<li>Parmi ces sous-ensembles, l'un est élu <strong>identifiant</strong> (tout court), souligné, et appelé à devenir clé primaire lors du passage au relationnel.</li>\n<li>Les candidats malheureux sont appelés <strong>identifiants alternatifs</strong>.</li>\n</ul>\n<p>Ainsi, dans l'exemple précédent, l'ensemble des identifiants candidats de CLIENT est constitué de :</p>\n<ul>\n<li>l'identifiant proprement dit <em>Réf. client</em> ;</li>\n<li>l'identifiant alternatif (<em>Nom</em>, <em>Prénom</em>) (dont on supposera pour les besoins de la cause qu'il assure l'unicité) ;</li>\n<li>l'identifiant alternatif <em>Mail</em>.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Par défaut, dès la première déclaration d'un identifiant alternatif, Mocodo fait apparaître une gouttière à gauche des attributs de <strong>toutes</strong> les entités. Y sont portés :</p>\n<ul>\n<li>un symbole « ID » (resp. « id ») pour l'identifiant fort (resp. faible).</li>\n<li>des chiffres de 1 à 9 correspondant aux numéros des identifiants alternatifs.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La notation de Mocodo permet de faire de n'importe quels sous-ensembles d'attributs des identifiants alternatifs. Ci-dessous, le premier identifiant alternatif est le triplet (<em>bar</em>, <em>biz</em>, <em>quux</em>), le second (<em>biz</em>, <em>buz</em>, <em>quux</em>) et le troisième (<em>qux</em>, <em>quux</em>) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [57]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t markdown:c sql --shapes trebuchet\nFOO: foo, 1_bar, 12_biz, 2_buz, 3_qux, 123_quux\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDIiIGhlaWdodD0iMTYwIiB2aWV3Qm94PSIwIDAgMTAyIDE2MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDIiIGhlaWdodD0iMTYwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgRk9PIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIyNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MSIgeT0iMzUiIHdpZHRoPSI0MiIgaGVpZ2h0PSIxMTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzUiIHdpZHRoPSI0MiIgaGVpZ2h0PSIxMTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjUxIiB5MT0iMzUiIHgyPSI1MSIgeTI9IjE1MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuMjUiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODQiIGhlaWdodD0iMTQyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzNSIgeDI9IjkzIiB5Mj0iMzUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8L2c+Cgk8dGV4dCB4PSIzNyIgeT0iMjcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+Rk9PPC90ZXh0PgoJPHRleHQgeD0iNTYiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmZvbzwvdGV4dD4KCTx0ZXh0IHg9IjIzIiB5PSI1My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5JRDwvdGV4dD4KCTxsaW5lIHgxPSI1NiIgeTE9IjU2IiB4Mj0iNzgiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjU2IiB5PSI3MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5iYXI8L3RleHQ+Cgk8dGV4dCB4PSIyNSIgeT0iNzEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MTwvdGV4dD4KCTx0ZXh0IHg9IjU2IiB5PSI4OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5iaXo8L3RleHQ+Cgk8dGV4dCB4PSIyMCIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MSAyPC90ZXh0PgoJPHRleHQgeD0iNTYiIHk9IjEwNy42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5idXo8L3RleHQ+Cgk8dGV4dCB4PSIyNSIgeT0iMTA3LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPjI8L3RleHQ+Cgk8dGV4dCB4PSI1NiIgeT0iMTI1LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPnF1eDwvdGV4dD4KCTx0ZXh0IHg9IjI1IiB5PSIxMjUuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MzwvdGV4dD4KCTx0ZXh0IHg9IjU2IiB5PSIxNDMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+cXV1eDwvdGV4dD4KCTx0ZXh0IHg9IjE0IiB5PSIxNDMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MSAyIDM8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>FOO</strong> (<u>foo</u>, bar <sup>u1</sup>, biz <sup>u1 u2</sup>, buz <sup>u2</sup>, qux <sup>u3</sup>, quux <sup>u1 u2 u3</sup>)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">FOO</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">foo</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">foo</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">bar</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">biz</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">buz</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">qux</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">quux</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">biz</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">quux</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">biz</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">buz</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">quux</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">qux</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">quux</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Examinons le cas exceptionnel où l'identifiant à souligner a un attribut commun avec un identifiant alternatif. Ce dernier devant être distinct et minimal, cela implique que l'identifiant est composite.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [58]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --shapes trebuchet\nEntité 1_: 1_foo, _bar, 1_biz\nEntité 2_: foo, 1_bar, 1_biz\nEntité 3_: foo, 01_bar, 1_biz\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNjQiIGhlaWdodD0iMTA2IiB2aWV3Qm94PSIwIDAgMzY0IDEwNiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNjQiIGhlaWdodD0iMTA2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgRU5USVRFXzFfIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI5OCIgaGVpZ2h0PSIyNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NSIgeT0iMzUiIHdpZHRoPSI2MiIgaGVpZ2h0PSI2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzNSIgd2lkdGg9IjM2IiBoZWlnaHQ9IjYyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0NSIgeTE9IjM1IiB4Mj0iNDUiIHkyPSI5NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuMjUiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTgiIGhlaWdodD0iODgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM1IiB4Mj0iMTA3IiB5Mj0iMzUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8L2c+Cgk8dGV4dCB4PSIzMiIgeT0iMjcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+RW50aXTDqSAxPC90ZXh0PgoJPHRleHQgeD0iNTAiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmZvbzwvdGV4dD4KCTx0ZXh0IHg9IjE0IiB5PSI1My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4xIElEPC90ZXh0PgoJPGxpbmUgeDE9IjUwIiB5MT0iNTYiIHgyPSI3MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTAiIHk9IjcxLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmJhcjwvdGV4dD4KCTx0ZXh0IHg9IjIwIiB5PSI3MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5JRDwvdGV4dD4KCTxsaW5lIHgxPSI1MCIgeTE9Ijc0IiB4Mj0iNzIiIHkyPSI3NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjUwIiB5PSI4OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5iaXo8L3RleHQ+Cgk8dGV4dCB4PSIyMiIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRU5USVRFXzJfIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzOSIgeT0iOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjI2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE2MyIgeT0iMzUiIHdpZHRoPSI2MiIgaGVpZ2h0PSI2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzkiIHk9IjM1IiB3aWR0aD0iMjQiIGhlaWdodD0iNjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE2MyIgeTE9IjM1IiB4Mj0iMTYzIiB5Mj0iOTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjI1Ii8+CgkJPHJlY3QgeD0iMTM5IiB5PSI5IiB3aWR0aD0iODYiIGhlaWdodD0iODgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTM5IiB5MT0iMzUiIHgyPSIyMjUiIHkyPSIzNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTwvZz4KCTx0ZXh0IHg9IjE1NiIgeT0iMjcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+RW50aXTDqSAyPC90ZXh0PgoJPHRleHQgeD0iMTY4IiB5PSI1My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5mb288L3RleHQ+Cgk8dGV4dCB4PSIxNDQiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPklEPC90ZXh0PgoJPGxpbmUgeDE9IjE2OCIgeTE9IjU2IiB4Mj0iMTkwIiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNjgiIHk9IjcxLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmJhcjwvdGV4dD4KCTx0ZXh0IHg9IjE0NiIgeT0iNzEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MTwvdGV4dD4KCTx0ZXh0IHg9IjE2OCIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+Yml6PC90ZXh0PgoJPHRleHQgeD0iMTQ2IiB5PSI4OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4xPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFTlRJVEVfM18gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjU3IiB5PSI5IiB3aWR0aD0iOTgiIGhlaWdodD0iMjYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjkzIiB5PSIzNSIgd2lkdGg9IjYyIiBoZWlnaHQ9IjYyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI1NyIgeT0iMzUiIHdpZHRoPSIzNiIgaGVpZ2h0PSI2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjkzIiB5MT0iMzUiIHgyPSIyOTMiIHkyPSI5NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuMjUiLz4KCQk8cmVjdCB4PSIyNTciIHk9IjkiIHdpZHRoPSI5OCIgaGVpZ2h0PSI4OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNTciIHkxPSIzNSIgeDI9IjM1NSIgeTI9IjM1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPC9nPgoJPHRleHQgeD0iMjgwIiB5PSIyNy42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5FbnRpdMOpIDM8L3RleHQ+Cgk8dGV4dCB4PSIyOTgiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmZvbzwvdGV4dD4KCTx0ZXh0IHg9IjI2OCIgeT0iNTMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+SUQ8L3RleHQ+Cgk8bGluZSB4MT0iMjk4IiB5MT0iNTYiIHgyPSIzMjAiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI5OCIgeT0iNzEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+YmFyPC90ZXh0PgoJPHRleHQgeD0iMjYyIiB5PSI3MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4xIElEPC90ZXh0PgoJPGxpbmUgeDE9IjI5OCIgeTE9Ijc0IiB4Mj0iMzIwIiB5Mj0iNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyOTgiIHk9Ijg5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmJpejwvdGV4dD4KCTx0ZXh0IHg9IjI3MCIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+MTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<ul>\n<li>Si l'attribut commun est en tête de liste (ici, <em>foo</em>, entité 1), rien ne change, on écrit <code>1_foo</code>.</li>\n<li>S'il n'est pas en tête de liste (ici, <em>bar</em>, entité 2), l'écriture <code>1_bar</code> dénote déjà l'appartenance à un identifiant alternatif. Elle ne peut dénoter simultanément l'appartenance à l'identifiant à souligner.</li>\n<li>C'est pourquoi on doit donc expliciter l'appartenance à l'identifiant à souligner qui, comme on l'a vu, est numéroté <code>0</code> (entité 3).</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Un sous-cas demande encore réflexion : celui où le premier attribut ne fait pas partie de l'identifiant à souligner (entité 4). Si l'on veut alors que ce premier attribut appartienne à une clé alternative, il faut expliciter le <code>0</code> (entité 5).</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [59]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --shapes trebuchet\nEntité 40: _foo, _bar, biz\nEntité 50: 01_foo, _bar, 1_biz\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMjIiIGhlaWdodD0iMTA2IiB2aWV3Qm94PSIwIDAgMjIyIDEwNiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyMjIiIGhlaWdodD0iMTA2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgRU5USVRFXzQwIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NiIgaGVpZ2h0PSIyNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMyIgeT0iMzUiIHdpZHRoPSI2MiIgaGVpZ2h0PSI2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzNSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjYyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMyIgeTE9IjM1IiB4Mj0iMzMiIHkyPSI5NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuMjUiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iODYiIGhlaWdodD0iODgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM1IiB4Mj0iOTUiIHkyPSIzNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTwvZz4KCTx0ZXh0IHg9IjI2IiB5PSIyNy42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5FbnRpdMOpIDQ8L3RleHQ+Cgk8dGV4dCB4PSIzOCIgeT0iNTMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+Zm9vPC90ZXh0PgoJPHRleHQgeD0iMjAiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiLz4KCTx0ZXh0IHg9IjM4IiB5PSI3MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5iYXI8L3RleHQ+Cgk8dGV4dCB4PSIxNCIgeT0iNzEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+SUQ8L3RleHQ+Cgk8bGluZSB4MT0iMzgiIHkxPSI3NCIgeDI9IjYwIiB5Mj0iNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzOCIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+Yml6PC90ZXh0PgoJPHRleHQgeD0iMjAiIHk9Ijg5LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiLz4KPC9nPgoKPCEtLSBFbnRpdHkgRU5USVRFXzUwIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEyNyIgeT0iOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjI2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE1MSIgeT0iMzUiIHdpZHRoPSI2MiIgaGVpZ2h0PSI2MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMjciIHk9IjM1IiB3aWR0aD0iMjQiIGhlaWdodD0iNjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE1MSIgeTE9IjM1IiB4Mj0iMTUxIiB5Mj0iOTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjI1Ii8+CgkJPHJlY3QgeD0iMTI3IiB5PSI5IiB3aWR0aD0iODYiIGhlaWdodD0iODgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTI3IiB5MT0iMzUiIHgyPSIyMTMiIHkyPSIzNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTwvZz4KCTx0ZXh0IHg9IjE0NCIgeT0iMjcuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+RW50aXTDqSA1PC90ZXh0PgoJPHRleHQgeD0iMTU2IiB5PSI1My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij5mb288L3RleHQ+Cgk8dGV4dCB4PSIxMzQiIHk9IjUzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPjE8L3RleHQ+Cgk8dGV4dCB4PSIxNTYiIHk9IjcxLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJUcmVidWNoZXQgTVMiIGZvbnQtc2l6ZT0iMTQiPmJhcjwvdGV4dD4KCTx0ZXh0IHg9IjEzMiIgeT0iNzEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+SUQ8L3RleHQ+Cgk8bGluZSB4MT0iMTU2IiB5MT0iNzQiIHgyPSIxNzgiIHkyPSI3NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE1NiIgeT0iODkuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IlRyZWJ1Y2hldCBNUyIgZm9udC1zaXplPSIxNCI+Yml6PC90ZXh0PgoJPHRleHQgeD0iMTM0IiB5PSI4OS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iVHJlYnVjaGV0IE1TIiBmb250LXNpemU9IjE0Ij4xPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>En résumé, on explicite le <code>0</code>, soit pour <strong>empêcher le soulignement du premier attribut</strong>, soit pour <strong>forcer le soulignement d'un attribut suivant</strong>.</p>\n<p>Cela devrait vous rappeler quelque chose… Remplacez <code>0</code> par <code>_</code> dans la phrase précédente et vous retrouverez la règle que vous avez appris à connaître et à aimer : on explicite le <code>_</code>, soit pour empêcher le soulignement du premier attribut, soit pour forcer le soulignement d'un attribut suivant.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Gestion-des-entit%C3%A9s-faibles-(identification-relative)\">Gestion des entités faibles (identification relative)<a class=\"anchor-link\" href=\"#Gestion-des-entit%C3%A9s-faibles-(identification-relative)\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans ce joli exemple dû à Idris NEUMANN, <a href=\"http://ineumann.developpez.com/tutoriels/merise/initiation-merise/#LIV-A\"><em>Initiation à la conception de bases de données relationnelles avec MERISE</em></a>, les renforcements successifs aboutissent à faire entrer l'identifiant de RUE dans celui de APPARTEMENT, alors même que ces entités sont séparées par non moins de trois associations :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [60]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nAppartement: num appart., nb pièces\nComposer, 0N Étage, _11 Appartement\nÉtage: num étage, nb appartements\nAppartenir, 1N Immeuble, _11 Étage\nImmeuble: num immeuble, nb étages\nSe situer, 0N Rue, _11 Immeuble\nRue: code rue, nom rue\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NTIiIGhlaWdodD0iOTQiIHZpZXdCb3g9IjAgMCA5NTIgOTQiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iOTUyIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBDT01QT1NFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMzY2IiB5MT0iNDciIHgyPSIyMjQiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI3NiIgeTE9IjQ3IiB4Mj0iMjI0IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjYyIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtMTA0IFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjc2IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTg2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDEwNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNzIiIHk9IjE4IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTcyIiB5MT0iNDYiIHgyPSIyNzYiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3OSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21wb3NlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI4MSIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjE0OCIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSIxNDgiIHkxPSI2NSIgeDI9IjE2NiIgeTI9IjY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEFQUEFSVEVOSVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY1NiIgeTE9IjQ3IiB4Mj0iNTE0IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzY2IiB5MT0iNDciIHgyPSI1MTQiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik01NTggMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC0xMTYgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01NzIgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0NzAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTE2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQ1NiIgeT0iMTgiIHdpZHRoPSIxMTYiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI0NTYiIHkxPSI0NiIgeDI9IjU3MiIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNDYzIiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFwcGFydGVuaXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI1NzciIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI0MzIiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iNDMyIiB5MT0iNjUiIHgyPSI0NTAiIHkyPSI2NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBTRV9TSVRVRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjkwNiIgeTE9IjQ3IiB4Mj0iNzkwIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjU2IiB5MT0iNDciIHgyPSI3OTAiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik04MjYgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC0xMDAgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik04NDAgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg3NTQgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTAwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9Ijc0MCIgeT0iMTgiIHdpZHRoPSIxMDAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI3NDAiIHkxPSI0NiIgeDI9Ijg0MCIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNzQ3IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNlIHNpdHVlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9Ijg0NSIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjcxNiIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSI3MTYiIHkxPSI2NSIgeDI9IjczNCIgeTI9IjY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBBUFBBUlRFTUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMzQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTQzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFwcGFydGVtZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBhcHBhcnQuPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI5MiIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIHBpw6hjZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVUQUdFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMwNSIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMDUiIHk9IjM5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMwNSIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMDUiIHkxPSIzOSIgeDI9IjQyNyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNDAiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+w4l0YWdlPC90ZXh0PgoJPHRleHQgeD0iMzEzIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gw6l0YWdlPC90ZXh0PgoJPGxpbmUgeDE9IjMxMyIgeTE9IjU5IiB4Mj0iMzc4IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIzMTMiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIGFwcGFydGVtZW50czwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgSU1NRVVCTEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNjAxIiB5PSI5IiB3aWR0aD0iMTEwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjYwMSIgeT0iMzkiIHdpZHRoPSIxMTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNjAxIiB5PSI5IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjYwMSIgeTE9IjM5IiB4Mj0iNzExIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjYxMyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbW1ldWJsZTwvdGV4dD4KCTx0ZXh0IHg9IjYwOSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIGltbWV1YmxlPC90ZXh0PgoJPGxpbmUgeDE9IjYwOSIgeTE9IjU5IiB4Mj0iNzAyIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSI2MDkiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIMOpdGFnZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFJVRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI4NjkiIHk9IjkiIHdpZHRoPSI3NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4NjkiIHk9IjM5IiB3aWR0aD0iNzQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iODY5IiB5PSI5IiB3aWR0aD0iNzQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iODY5IiB5MT0iMzkiIHgyPSI5NDMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iODg4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJ1ZTwvdGV4dD4KCTx0ZXh0IHg9Ijg3NyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y29kZSBydWU8L3RleHQ+Cgk8bGluZSB4MT0iODc3IiB5MT0iNTkiIHgyPSI5MzQiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9Ijg3NyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHJ1ZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Appartement</strong> (<u><em>#code rue</em></u>, <u><em>#num immeuble</em></u>, <u><em>#num étage</em></u>, <u>num appart.</u>, nb pièces)</li>\n<li><strong>Étage</strong> (<u><em>#code rue</em></u>, <u><em>#num immeuble</em></u>, <u>num étage</u>, nb appartements)</li>\n<li><strong>Immeuble</strong> (<u><em>#code rue</em></u>, <u>num immeuble</u>, nb étages)</li>\n<li><strong>Rue</strong> (<u>code rue</u>, nom rue)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le résultat apparaît plus clairement sur le diagramme relationnel :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [61]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t diagram --colors mondrian\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2OTAiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgNjkwIDE0NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY5MCIgaGVpZ2h0PSIxNDYiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBBUFBBUlRFTUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSIxMzQiIGhlaWdodD0iOTgiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSIxMzQiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM4IiB5MT0iMzkiIHgyPSIxNzIiIHkyPSIzOSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDciIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXBwYXJ0ZW1lbnQ8L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iNTYuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I2NvZGUgcnVlPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNTkiIHgyPSIxMTIiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSI3My4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jbnVtIGltbWV1YmxlPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNzYiIHgyPSIxNDgiIHkyPSI3NiIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jbnVtIMOpdGFnZTwvdGV4dD4KCTxsaW5lIHgxPSI0NiIgeTE9IjkzIiB4Mj0iMTIwIiB5Mj0iOTMiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0NiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gYXBwYXJ0LjwvdGV4dD4KCTxsaW5lIHgxPSI0NiIgeTE9IjExMCIgeDI9IjEyMSIgeTI9IjExMCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSIxMjQiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIHBpw6hjZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVUQUdFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIzMCIgeT0iMTgiIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjMwIiB5PSI0OCIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzAiIHk9IjE4IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMzAiIHkxPSI0OCIgeDI9IjM1MiIgeTI9IjQ4IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjUiIHk9IjM5LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+w4l0YWdlPC90ZXh0PgoJPHRleHQgeD0iMjM4IiB5PSI2NS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jY29kZSBydWU8L3RleHQ+Cgk8bGluZSB4MT0iMjM4IiB5MT0iNjgiIHgyPSIzMDQiIHkyPSI2OCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIzOCIgeT0iODIuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I251bSBpbW1ldWJsZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzgiIHkxPSI4NSIgeDI9IjM0MCIgeTI9Ijg1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjM4IiB5PSI5OS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gw6l0YWdlPC90ZXh0PgoJPGxpbmUgeDE9IjIzOCIgeTE9IjEwMiIgeDI9IjMwMyIgeTI9IjEwMiIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIzOCIgeT0iMTE2IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uYiBhcHBhcnRlbWVudHM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElNTUVVQkxFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQxMCIgeT0iMjYiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDEwIiB5PSI1NiIgd2lkdGg9IjExMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MTAiIHk9IjI2IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQxMCIgeTE9IjU2IiB4Mj0iNTIwIiB5Mj0iNTYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQyMiIgeT0iNDcuMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbW1ldWJsZTwvdGV4dD4KCTx0ZXh0IHg9IjQxOCIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I2NvZGUgcnVlPC90ZXh0PgoJPGxpbmUgeDE9IjQxOCIgeTE9Ijc2IiB4Mj0iNDg0IiB5Mj0iNzYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0MTgiIHk9IjkwLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBpbW1ldWJsZTwvdGV4dD4KCTxsaW5lIHgxPSI0MTgiIHkxPSI5MyIgeDI9IjUxMSIgeTI9IjkzIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDE4IiB5PSIxMDciIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIMOpdGFnZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFJVRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1NzgiIHk9IjM1IiB3aWR0aD0iNzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTc4IiB5PSI2NSIgd2lkdGg9Ijc0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjU3OCIgeT0iMzUiIHdpZHRoPSI3NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1NzgiIHkxPSI2NSIgeDI9IjY1MiIgeTI9IjY1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1OTciIHk9IjU2LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UnVlPC90ZXh0PgoJPHRleHQgeD0iNTg2IiB5PSI4Mi4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb2RlIHJ1ZTwvdGV4dD4KCTxsaW5lIHgxPSI1ODYiIHkxPSI4NSIgeDI9IjY0MyIgeTI9Ijg1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTg2IiB5PSI5OS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gcnVlPC90ZXh0Pgo8L2c+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoQVBQQVJURU1FTlQpIHRvICZxdW90O2NvZGUgcnVlJnF1b3Q7IChFVEFHRSkgLS0+CjxwYXRoIGQ9Ik0xNzIgNTMuNSBDMjAxIDU4IDE5MS4zMyA2Mi41IDIzMCA2Mi41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjIzMCA2Mi41IDIxOCA2OC41IDIyMiA2Mi41IDIxOCA1Ni41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMTcyIiBjeT0iNTMuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEFQUEFSVEVNRU5UKSB0byAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEVUQUdFKSAtLT4KPHBhdGggZD0iTTE3MiA3MC41IEMyMDEgNzUgMTkxLjMzIDc5LjUgMjMwIDc5LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjMwIDc5LjUgMjE4IDg1LjUgMjIyIDc5LjUgMjE4IDczLjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzIiIGN5PSI3MC41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O251bSDDqXRhZ2UmcXVvdDsgKEFQUEFSVEVNRU5UKSB0byAmcXVvdDtudW0gw6l0YWdlJnF1b3Q7IChFVEFHRSkgLS0+CjxwYXRoIGQ9Ik0xNzIgODcuNSBDMjAxIDkyIDE5MS4zMyA5Ni41IDIzMCA5Ni41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjIzMCA5Ni41IDIxOCAxMDIuNSAyMjIgOTYuNSAyMTggOTAuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjE3MiIgY3k9Ijg3LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7Y29kZSBydWUmcXVvdDsgKEVUQUdFKSB0byAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoSU1NRVVCTEUpIC0tPgo8cGF0aCBkPSJNMzUyIDYyLjUgQzM4MSA2Ni41IDM3MS4zMyA3MC41IDQxMCA3MC41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjQxMCA3MC41IDM5OCA3Ni41IDQwMiA3MC41IDM5OCA2NC41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMzUyIiBjeT0iNjIuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEVUQUdFKSB0byAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKElNTUVVQkxFKSAtLT4KPHBhdGggZD0iTTM1MiA3OS41IEMzODEgODMuNSAzNzEuMzMgODcuNSA0MTAgODcuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI0MTAgODcuNSAzOTggOTMuNSA0MDIgODcuNSAzOTggODEuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjM1MiIgY3k9Ijc5LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7Y29kZSBydWUmcXVvdDsgKElNTUVVQkxFKSB0byAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoUlVFKSAtLT4KPHBhdGggZD0iTTUyMCA3MC41IEM1NDkgNzUgNTM5LjMzIDc5LjUgNTc4IDc5LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iNTc4IDc5LjUgNTY2IDg1LjUgNTcwIDc5LjUgNTY2IDczLjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSI1MjAiIGN5PSI3MC41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Une phase préliminaire de l'algorithme de passage au relationnel consiste à « renforcer » les entités faibles de façon à traiter uniquement des identifiants forts dans la suite. Cela permet la gestion des renforcements en cascade comme ci-dessus, ainsi que la détection des problèmes de renforcement cyclique :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [62]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nPick, 0N Land, _11 Peer\nLand: true, hold\n\nPeer: foot, city\nZone, 1N Peer, _11 Land\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNjgiIGhlaWdodD0iMTk0IiB2aWV3Qm94PSIwIDAgMTY4IDE5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNjgiIGhlaWdodD0iMTk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQSUNLIC0tPgo8Zz4KCTxsaW5lIHgxPSIxMjgiIHkxPSI0NyIgeDI9IjM5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzkiIHkxPSIxNDciIHgyPSIzOSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTUyIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtNTQgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik02NiA0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDI2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDU0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyIiB5PSIxOCIgd2lkdGg9IjU0IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTIiIHkxPSI0NiIgeDI9IjY2IiB5Mj0iNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyMCIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QaWNrPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNzMiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSI0NCIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iNDQiIHkxPSIxMDMiIHgyPSI2MiIgeTI9IjEwMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBaT05FIC0tPgo8Zz4KCTxsaW5lIHgxPSIzOSIgeTE9IjE0NyIgeDI9IjEyOCIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxMjgiIHkxPSI0NyIgeDI9IjEyOCIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0xNDQgMTE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjE0NiBoLTYwIFYxMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTE1OCAxNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMTIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNDYgSDYwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9Ijk4IiB5PSIxMTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9Ijk4IiB5MT0iMTQ2IiB4Mj0iMTU4IiB5Mj0iMTQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTA2IiB5PSIxMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ab25lPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNzQiIHk9IjE2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTMzIiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSIxMzMiIHkxPSIxMDMiIHgyPSIxNTEiIHkyPSIxMDMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IExBTkQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOTciIHk9IjkiIHdpZHRoPSI2MiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NyIgeT0iMzkiIHdpZHRoPSI2MiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NyIgeT0iOSIgd2lkdGg9IjYyIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijk3IiB5MT0iMzkiIHgyPSIxNTkiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTA2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkxhbmQ8L3RleHQ+Cgk8dGV4dCB4PSIxMDUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnRydWU8L3RleHQ+Cgk8bGluZSB4MT0iMTA1IiB5MT0iNTkiIHgyPSIxMzIiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1kYXNoYXJyYXk9IjQiLz4KCTx0ZXh0IHg9IjEwNSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aG9sZDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUEVFUiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIxMDkiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMzkiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMDkiIHdpZHRoPSI2MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMTM5IiB4Mj0iNjkiIHkyPSIxMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QZWVyPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjE1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5mb290PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMTU5IiB4Mj0iNDQiIHkyPSIxNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIxNyIgeT0iMTczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNpdHk8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [63]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.17 - Cycle d'entités faibles dans \"Land\", \"Peer\".</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Gestion-de-l'h%C3%A9ritage\">Gestion de l'héritage<a class=\"anchor-link\" href=\"#Gestion-de-l'h%C3%A9ritage\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La bonne gestion d'un héritage est primordiale, tant du point de vue de la préservation du patrimoine, que de l'optimisation des ressources financières, de la minimisation des conflits familiaux et du respect des dernières volontés du défunt. Je blague.</p>\n<p>Adaptons ici un exemple d'un <a href=\"https://stph.scenari-community.org/bdd/rel3.pdf\">cours de Stéphane Crozat</a>. Nous reprenons sa terminologie et donnons en parallèle celle introduite par Martin Fowler dans <em>Patterns of Enterprise Application Architecture</em>, Addison-Wesley (2003).</p>\n<p>Ci-dessous, l'héritage est considéré comme <em>total</em> (tout document est soit un ouvrage, soit une thèse, soit les deux). Crozat passe en revue trois mécanismes possibles pour le passage au relationnel.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<hr>\n<p>L'<strong>héritage par référence</strong> (en anglais, <a href=\"http://martinfowler.com/eaaCatalog/classTableInheritance.html\"><em>Class Table Inheritance</em></a> ou <em>Table Per Type Inheritance</em>) se note en Mocodo par une flèche simple allant vers les filles. Une référence à la table-mère sera ajoutée dans chaque table-fille comme clé étrangère. L'intérêt de cette solution est en raison directe du nombre d'attributs non identifiants de l'entité-mère.</p>\n</hr></div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [64]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nDOCUMENT: cote, titre, auteur\n    \nOUVRAGE: éditeur\n/T\\ DOCUMENT -&gt; OUVRAGE, THÈSE\nTHÈSE: discipline, université\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgMzEwIDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBET0NVTUVOVF9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjE2OSIgeTE9IjU2IiB4Mj0iMTY5IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjYyIiB5MT0iMTY1IiB4Mj0iMTY5IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxMTUgMTY1IDEyNyAxNTkgMTIzIDE2NSAxMjcgMTcxIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIyNjIiIHkxPSIxNjUiIHgyPSIxNjkiIHkyPSIxNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjIyMyAxNjUgMjExIDE3MSAyMTUgMTY1IDIxMSAxNTkiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGc+CgkJPHBvbHlnb24gcG9pbnRzPSIxNjkgMTM2LjEzIDE0NCAxNzkuNDMgMTk0IDE3OS40MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjE2MyIgeT0iMTcxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlQ8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gRW50aXR5IERPQ1VNRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMDgiIHk9IjM5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMDgiIHkxPSIzOSIgeDI9IjIzMCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxMTYiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RE9DVU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvdGU8L3RleHQ+Cgk8bGluZSB4MT0iMTE2IiB5MT0iNTkiIHgyPSIxNDUiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjExNiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGl0cmU8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdXRldXI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IE9VVlJBR0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTM1IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE2NSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMzUiIHdpZHRoPSIxMDYiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjE2NSIgeDI9IjExNSIgeTI9IjE2NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjE1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk9VVlJBR0U8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOpZGl0ZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSEVTRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMjMiIHk9IjEyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTU3IiB3aWR0aD0iNzgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSIxMjciIHdpZHRoPSI3OCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMjMiIHkxPSIxNTciIHgyPSIzMDEiIHkyPSIxNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzMSIgeT0iMTQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VEjDiFNFPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGlzY2lwbGluZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iMTkxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnVuaXZlcnNpdMOpPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>DOCUMENT</strong> (<u>cote</u>, titre, auteur)</li>\n<li><strong>OUVRAGE</strong> (<u><em>#cote</em></u>, éditeur)</li>\n<li><strong>THÈSE</strong> (<u><em>#cote</em></u>, discipline, université)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<hr>\n<p>L'<strong>héritage par absorption dans les tables-filles</strong> (en anglais, <a href=\"http://martinfowler.com/eaaCatalog/concreteTableInheritance.html\"><em>Concrete Table Inheritance</em></a> ou <em>Table Per Concrete Inheritance</em>) se note en doublant la flèche :</p>\n<ol>\n<li>les attributs de la table-mère sont reproduits dans chacune des filles. Pour chaque document qui est à la fois un ouvrage et une thèse, il y aura donc duplication des triplets (<u>cote</u>, titre, auteur).</li>\n<li>la table-mère disparaît. Pour éviter de perdre les informations sur les documents qui ne seraient ni des ouvrages, ni des thèses, Mocodo lève une erreur si l'héritage n'est pas total (T ou XT).</li>\n</ol>\n</hr></div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [65]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nDOCUMENT: cote, titre, auteur\n    \nOUVRAGE: éditeur\n/T\\ DOCUMENT =&gt; OUVRAGE, THÈSE\nTHÈSE: discipline, université\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgMzEwIDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBET0NVTUVOVF9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjE3MCIgeTE9IjU2IiB4Mj0iMTcwIiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjE2OCIgeTE9IjU2IiB4Mj0iMTY4IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjYyIiB5MT0iMTY1IiB4Mj0iMTY5IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxMTUgMTY1IDEyNyAxNTkgMTIzIDE2NSAxMjcgMTcxIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIyNjIiIHkxPSIxNjUiIHgyPSIxNjkiIHkyPSIxNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjIyMyAxNjUgMjExIDE3MSAyMTUgMTY1IDIxMSAxNTkiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGc+CgkJPHBvbHlnb24gcG9pbnRzPSIxNjkgMTM2LjEzIDE0NCAxNzkuNDMgMTk0IDE3OS40MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjE2MyIgeT0iMTcxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlQ8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gRW50aXR5IERPQ1VNRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMDgiIHk9IjM5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMDgiIHkxPSIzOSIgeDI9IjIzMCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxMTYiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RE9DVU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvdGU8L3RleHQ+Cgk8bGluZSB4MT0iMTE2IiB5MT0iNTkiIHgyPSIxNDUiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjExNiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGl0cmU8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdXRldXI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IE9VVlJBR0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTM1IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE2NSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMzUiIHdpZHRoPSIxMDYiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjE2NSIgeDI9IjExNSIgeTI9IjE2NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjE1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk9VVlJBR0U8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOpZGl0ZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSEVTRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMjMiIHk9IjEyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTU3IiB3aWR0aD0iNzgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSIxMjciIHdpZHRoPSI3OCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMjMiIHkxPSIxNTciIHgyPSIzMDEiIHkyPSIxNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzMSIgeT0iMTQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VEjDiFNFPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGlzY2lwbGluZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iMTkxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnVuaXZlcnNpdMOpPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>OUVRAGE</strong> (<u>cote</u>, titre, auteur, éditeur)</li>\n<li><strong>THÈSE</strong> (<u>cote</u>, titre, auteur, discipline, université)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<hr>\n<p>L'<strong>héritage par absorption dans la table-mère</strong> (en anglais, <a href=\"http://martinfowler.com/eaaCatalog/singleTableInheritance.html\"><em>Single Table Inheritance</em></a> ou <em>Table Per Hierarchy Inheritance</em>) se note par une flèche simple allant vers la mère. Les tables-filles disparaissent, et leurs attributs migrent dans la mère avec une contrainte d'optionalité (point d'interrogation en relationnel, <code>NULL</code> en SQL).</p>\n</hr></div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [66]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c sql\nDOCUMENT: cote, titre, auteur\n\nOUVRAGE: éditeur\n/X\\ DOCUMENT &lt;- OUVRAGE, THÈSE: discriminateur [ENUM ('OUVRAGE', 'THÈSE')]\nTHÈSE: discipline, université\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgMzEwIDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBET0NVTUVOVF9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjE2OSIgeTE9IjU2IiB4Mj0iMTY5IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxNjkgMTAzIDE3NSAxMTUgMTY5IDExMSAxNjMgMTE1IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSI2MiIgeTE9IjE2NSIgeDI9IjE2OSIgeTI9IjE2NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNjIiIHkxPSIxNjUiIHgyPSIxNjkiIHkyPSIxNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cG9seWdvbiBwb2ludHM9IjE2OSAxMzYuMTMgMTQ0IDE3OS40MyAxOTQgMTc5LjQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTYzIiB5PSIxNzEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+WDwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBFbnRpdHkgRE9DVU1FTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTA4IiB5PSI5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEwOCIgeT0iMzkiIHdpZHRoPSIxMjIiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTA4IiB5PSI5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEwOCIgeTE9IjM5IiB4Mj0iMjMwIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjExNiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ET0NVTUVOVDwvdGV4dD4KCTx0ZXh0IHg9IjExNiIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y290ZTwvdGV4dD4KCTxsaW5lIHgxPSIxMTYiIHkxPSI1OSIgeDI9IjE0NSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTE2IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50aXRyZTwvdGV4dD4KCTx0ZXh0IHg9IjExNiIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF1dGV1cjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgT1VWUkFHRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIxMzUiIHdpZHRoPSIxMDYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTY1IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjEzNSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMTY1IiB4Mj0iMTE1IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMTU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+T1VWUkFHRTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+w6lkaXRldXI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFRIRVNFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTI3IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSIxNTciIHdpZHRoPSI3OCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjEyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjE1NyIgeDI9IjMwMSIgeTI9IjE1NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjMxIiB5PSIxNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5USMOIU0U8L3RleHQ+Cgk8dGV4dCB4PSIyMzEiIHk9IjE3NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kaXNjaXBsaW5lPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSIxOTEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dW5pdmVyc2l0w6k8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>DOCUMENT</strong> (<u>cote</u>, titre, auteur, discriminateur?, éditeur?, discipline?, université?)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">DOCUMENT</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">cote</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">cote</span><span class=\"w\">           </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">titre</span><span class=\"w\">          </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">auteur</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">discriminateur</span><span class=\"w\"> </span><span class=\"n\">ENUM</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"s1\">'OUVRAGE'</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"s1\">'THÈSE'</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">editeur</span><span class=\"w\">        </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">discipline</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">universite</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ci-dessus, nous avons donné comme « attribut » au triangle d'héritage un « discriminateur » de type <code>ENUM</code>. Cela ajoute à la table un champ optionnel ou non (selon que l'héritage est partiel ou total) permettant de déterminer à quel type concret d'une occurrence on a affaire.</p>\n<p>C'est par défaut un <code>UNSIGNED INT</code>, qui pourra prendre les valeurs :</p>\n<ul>\n<li>1 = OUVRAGE, 2 = THÈSE, pour l'héritage exclusif ;</li>\n<li>1 ($2^0$) = OUVRAGE, 2 ($2^1$) = THÈSE, 3 ($2^0 | 2^1$) = OUVRAGE + THÈSE, pour l'héritage non exclusif.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Alternativement à l'emploi d'un discriminateur, Mocodo peut ajouter un drapeau booléen par table-fille. Cela se note en doublant la flèche :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [67]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c sql\nDOCUMENT: cote, titre, auteur\n\nOUVRAGE: éditeur\n/T\\ DOCUMENT &lt;= OUVRAGE, THÈSE\nTHÈSE: discipline, université\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgMzEwIDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTAiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBET0NVTUVOVF9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjE2OSIgeTE9IjU2IiB4Mj0iMTY5IiB5Mj0iMTY1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxNjkgMTAzIDE3NSAxMTUgMTY5IDExMSAxNjMgMTE1IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSI2MiIgeTE9IjE2NiIgeDI9IjE2OSIgeTI9IjE2NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI2MiIgeTE9IjE2NCIgeDI9IjE2OSIgeTI9IjE2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNjIiIHkxPSIxNjYiIHgyPSIxNjkiIHkyPSIxNjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjYyIiB5MT0iMTY0IiB4Mj0iMTY5IiB5Mj0iMTY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBvbHlnb24gcG9pbnRzPSIxNjkgMTM2LjEzIDE0NCAxNzkuNDMgMTk0IDE3OS40MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjE2MyIgeT0iMTcxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlQ8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gRW50aXR5IERPQ1VNRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMDgiIHk9IjM5IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEwOCIgeT0iOSIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMDgiIHkxPSIzOSIgeDI9IjIzMCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxMTYiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RE9DVU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvdGU8L3RleHQ+Cgk8bGluZSB4MT0iMTE2IiB5MT0iNTkiIHgyPSIxNDUiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjExNiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGl0cmU8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdXRldXI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IE9VVlJBR0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTM1IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE2NSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMzUiIHdpZHRoPSIxMDYiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjE2NSIgeDI9IjExNSIgeTI9IjE2NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjE1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk9VVlJBR0U8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOpZGl0ZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSEVTRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMjMiIHk9IjEyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTU3IiB3aWR0aD0iNzgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSIxMjciIHdpZHRoPSI3OCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMjMiIHkxPSIxNTciIHgyPSIzMDEiIHkyPSIxNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzMSIgeT0iMTQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VEjDiFNFPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGlzY2lwbGluZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iMTkxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnVuaXZlcnNpdMOpPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>DOCUMENT</strong> (<u>cote</u>, titre, auteur, est ouvrage!, éditeur?, est these!, discipline?, université?)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">DOCUMENT</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">cote</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">cote</span><span class=\"w\">        </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">titre</span><span class=\"w\">       </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">auteur</span><span class=\"w\">      </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">est_ouvrage</span><span class=\"w\"> </span><span class=\"nb\">BOOLEAN</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">editeur</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">est_these</span><span class=\"w\">   </span><span class=\"nb\">BOOLEAN</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">discipline</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">universite</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Gestion-de-l'agr%C3%A9gation\">Gestion de l'agrégation<a class=\"anchor-link\" href=\"#Gestion-de-l'agr%C3%A9gation\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Un agrégat simple autour d'une association dont toutes les cardinalités maximales sont N se traduit en relationnel comme la même association non agrégée, mais avec une clé primaire réduite :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [68]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nDATE: date\nRÉSERVER, /1N CLIENT, 1N CHAMBRE, 0N DATE: durée\nCHAMBRE: num. chambre, prix\n\nCLIENT: id. client, nom client\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDQiIGhlaWdodD0iMjEzIiB2aWV3Qm94PSIwIDAgNDA0IDIxMyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MDQiIGhlaWdodD0iMjEzIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZFUiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIxODAiIGN5PSIxMTMiIHI9IjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGNTUiLz4KCTxsaW5lIHgxPSIxODAiIHkxPSIxNTciIHgyPSIxODAiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMzEiIHkxPSI1NiIgeDI9IjE4MCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjUxIiB5MT0iNTYiIHgyPSIxODAiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMCAxMyBMMzg0IDEzIGE3IDcgMCAwIDEgNyA3IEwzOTEgOTIgYTcgNyAwIDAgMSAtNyA3IEwyMCA5OSBhNyA3IDAgMCAxIC03IC03IEwxMyAyMCBhNyA3IDAgMCAxIDcgLTciIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjMiLz4KCQk8cGF0aCBkPSJNMjAgMTMgTDM4NCAxMyBhNyA3IDAgMCAxIDcgNyBMMzkxIDkyIGE3IDcgMCAwIDEgLTcgNyBMMjAgOTkgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yMjMgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMTQgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMzcgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMzcgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMyIgeT0iMjciIHdpZHRoPSIxMTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMjMiIHkxPSI1NSIgeDI9IjIzNyIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTMwIiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDiVNFUlZFUjwvdGV4dD4KCQk8dGV4dCB4PSIxMzAiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmR1csOpZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5MCIgeT0iMTA2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDciIHk9Ijc3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI5NCIgeT0iNzciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREFURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxOCIgeT0iMjYiIHdpZHRoPSI2NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iNTYiIHdpZHRoPSI2NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iMjYiIHdpZHRoPSI2NiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxOCIgeTE9IjU2IiB4Mj0iODQiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjciIHk9IjQ3LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REFURTwvdGV4dD4KCTx0ZXh0IHg9IjI2IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPGxpbmUgeDE9IjI2IiB5MT0iNzYiIHgyPSI1NCIgeTI9Ijc2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBDSEFNQlJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3NiIgeT0iMTgiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc2IiB5PSI0OCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzYiIHk9IjE4IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NiIgeTE9IjQ4IiB4Mj0iMzg2IiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4NSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DSEFNQlJFPC90ZXh0PgoJPHRleHQgeD0iMjg0IiB5PSI2NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIGNoYW1icmU8L3RleHQ+Cgk8bGluZSB4MT0iMjg0IiB5MT0iNjgiIHgyPSIzNzMiIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI4NCIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJpeDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzOCIgeT0iMTE5IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTM4IiB5PSIxNDkiIHdpZHRoPSI4NCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzgiIHk9IjExOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEzOCIgeTE9IjE0OSIgeDI9IjIyMiIgeTI9IjE0OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQ2IiB5PSIxNDAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNDYiIHk9IjE2Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE0NiIgeTE9IjE2OSIgeDI9IjE5OSIgeTI9IjE2OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE0NiIgeT0iMTgzLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBjbGllbnQ8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>CHAMBRE</strong> (<u>num. chambre</u>, prix)</li>\n<li><strong>CLIENT</strong> (<u>id. client</u>, nom client)</li>\n<li><strong>RÉSERVER</strong> (<u><em>#num. chambre</em></u>, <u>date</u>, <em>#id. client!</em>, durée)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Un agrégat simple autour d'une association dont la cardinalité maximale « de sortie » est 1 se traduit en relationnel comme la même association non agrégée, mais avec une contrainte d'unicité sur la clé étrangère. Ci-dessous, au lieu d'avoir simplement <em>num résa</em> $\\implies$ (<em>num voilier</em>, <em>num semaine</em>), on a donc en plus (<em>num voilier</em>, <em>num semaine</em>) $\\implies$ <em>num résa</em> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [69]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nVoilier: num voilier, longueur\nOffrir, /11 Réservation, 0N Voilier, 0N Semaine: tarif\nSemaine: num semaine, date début\n\nRéservation: num résa, arrhes, date résa\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNzgiIGhlaWdodD0iMjQwIiB2aWV3Qm94PSIwIDAgMzc4IDI0MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNzgiIGhlaWdodD0iMjQwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBPRkZSSVIgLS0+CjxnPgoJPGNpcmNsZSBjeD0iMTg0IiBjeT0iMTIyIiByPSI2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0iI0ZGRkZGRjU1Ii8+Cgk8bGluZSB4MT0iMTg0IiB5MT0iMTc1IiB4Mj0iMTg0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjIiIHkxPSI1NiIgeDI9IjE4NCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMxMSIgeTE9IjU2IiB4Mj0iMTg0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjAgMTMgTDM1OCAxMyBhNyA3IDAgMCAxIDcgNyBMMzY1IDkyIGE3IDcgMCAwIDEgLTcgNyBMMjAgOTkgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC4zIi8+CgkJPHBhdGggZD0iTTIwIDEzIEwzNTggMTMgYTcgNyAwIDAgMSA3IDcgTDM2NSA5MiBhNyA3IDAgMCAxIC03IDcgTDIwIDk5IGE3IDcgMCAwIDEgLTcgLTcgTDEzIDIwIGE3IDcgMCAwIDEgNyAtNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWRhc2hhcnJheT0iMCw0IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCQk8cGF0aCBkPSJNMjA5IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtNzggVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMjMgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNTkgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBINzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTQ1IiB5PSIyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTQ1IiB5MT0iNTUiIHgyPSIyMjMiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE1MyIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5PZmZyaXI8L3RleHQ+CgkJPHRleHQgeD0iMTUyIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50YXJpZjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5NCIgeT0iMTE1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIxMTYiIHk9Ijc3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMzMiIHk9Ijc3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFZPSUxJRVIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTgiIHk9IjE4IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjQ4IiB3aWR0aD0iODgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjE4IiB3aWR0aD0iODgiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTgiIHkxPSI0OCIgeDI9IjEwNiIgeTI9IjQ4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyOSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Wb2lsaWVyPC90ZXh0PgoJPHRleHQgeD0iMjYiIHk9IjY1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSB2b2lsaWVyPC90ZXh0PgoJPGxpbmUgeDE9IjI2IiB5MT0iNjgiIHgyPSI5NyIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjYiIHk9IjgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxvbmd1ZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTRU1BSU5FIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI2MiIgeT0iMTgiIHdpZHRoPSI5OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjIiIHk9IjQ4IiB3aWR0aD0iOTgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjYyIiB5PSIxOCIgd2lkdGg9Ijk4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI2MiIgeTE9IjQ4IiB4Mj0iMzYwIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3NCIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TZW1haW5lPC90ZXh0PgoJPHRleHQgeD0iMjcwIiB5PSI2NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gc2VtYWluZTwvdGV4dD4KCTxsaW5lIHgxPSIyNzAiIHkxPSI2OCIgeDI9IjM1MiIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjcwIiB5PSI4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIGTDqWJ1dDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUkVTRVJWQVRJT04gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTE5IiB5PSIxMjgiIHdpZHRoPSIxMzAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTE5IiB5PSIxNTgiIHdpZHRoPSIxMzAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTE5IiB5PSIxMjgiIHdpZHRoPSIxMzAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTE5IiB5MT0iMTU4IiB4Mj0iMjQ5IiB5Mj0iMTU4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9IjE0OS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDqXNlcnZhdGlvbjwvdGV4dD4KCTx0ZXh0IHg9IjEyNyIgeT0iMTc1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSByw6lzYTwvdGV4dD4KCTxsaW5lIHgxPSIxMjciIHkxPSIxNzgiIHgyPSIxODUiIHkyPSIxNzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxMjciIHk9IjE5Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hcnJoZXM8L3RleHQ+Cgk8dGV4dCB4PSIxMjciIHk9IjIwOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZSByw6lzYTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Réservation</strong> (<u>num résa</u>, arrhes, date résa, <em>#num voilier!</em> <sup>u1</sup>, <em>#num semaine!</em> <sup>u1</sup>, tarif)</li>\n<li><strong>Semaine</strong> (<u>num semaine</u>, date début)</li>\n<li><strong>Voilier</strong> (<u>num voilier</u>, longueur)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le cas des agrégats multiples, plus rare, est étudié en annexe.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Ajustement-des-r%C3%A8gles-de-passage\">Ajustement des règles de passage<a class=\"anchor-link\" href=\"#Ajustement-des-r%C3%A8gles-de-passage\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Supprimer-ou-maintenir-une-table-facultative\">Supprimer ou maintenir une table facultative<a class=\"anchor-link\" href=\"#Supprimer-ou-maintenir-une-table-facultative\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le passage au relationnel supprime automatiquement les tables réduites à une clé primaire, pourvu qu'aucun composant de celle-ci ne soit clé étrangère. Si l'on souhaite maintenir certaines de ces tables, on préfixe d'un <code>+</code> l'entité concernée. Ainsi, ci-dessous, Date est supprimée, mais pas Thème.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [70]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select mld mcd -t mld:e\nAnimateur: num. animateur, nom animateur\nIntervenir, 1N Animateur, 1N Formation, 1N Date: nb heures\nFormation: id. formation, durée\nAborder, 1N Thème, 1N Formation\n+Thème: thème\n\nDate: date\n:\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><p><strong>Aborder</strong> (<u><em>#thème</em></u>, <u><em>#id. formation</em></u>)</p>\n<ul>\n<li>Le champ <em>thème</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Thème</em>.</li>\n<li>Le champ <em>id. formation</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Formation</em>.</li>\n</ul>\n</li>\n<li><p><strong>Animateur</strong> (<u>num. animateur</u>, nom animateur)</p>\n<ul>\n<li>Le champ <em>num. animateur</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Animateur</em>.</li>\n<li>Le champ <em>nom animateur</em> était déjà un simple attribut de l'entité <em>Animateur</em>.</li>\n</ul>\n</li>\n<li><p><strong>Formation</strong> (<u>id. formation</u>, durée)</p>\n<ul>\n<li>Le champ <em>id. formation</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Formation</em>.</li>\n<li>Le champ <em>durée</em> était déjà un simple attribut de l'entité <em>Formation</em>.</li>\n</ul>\n</li>\n<li><p><strong>Intervenir</strong> (<u><em>#num. animateur</em></u>, <u><em>#id. formation</em></u>, <u>date</u>, nb heures)</p>\n<ul>\n<li>Le champ <em>num. animateur</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Animateur</em>.</li>\n<li>Le champ <em>id. formation</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Formation</em>.</li>\n<li>Le champ <em>date</em> fait partie de la clé primaire de la table. Sa table d'origine (<em>Date</em>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n<li>Le champ <em>nb heures</em> était déjà un simple attribut de l'association <em>Intervenir</em>.</li>\n</ul>\n</li>\n<li><p><strong>Thème</strong> (<u>thème</u>)</p>\n<ul>\n<li>Le champ <em>thème</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Thème</em>.\n<br/></li>\n</ul>\n</li>\n</ul>\n<hr>\n<p><strong>NB.</strong> La table <em>Date</em> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</p>\n</hr></div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzgiIGhlaWdodD0iMTY5IiB2aWV3Qm94PSIwIDAgNjM4IDE2OSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzgiIGhlaWdodD0iMTY5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBJTlRFUlZFTklSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NiIgeTE9IjQ3IiB4Mj0iMjA4IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzQ5IiB5MT0iNDciIHgyPSIyMDgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMDgiIHkxPSIxMzAiIHgyPSIyMDgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNTAgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC0xMTIgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjQgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNjYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE1MiIgeT0iMTgiIHdpZHRoPSIxMTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTIiIHkxPSI0NiIgeDI9IjI2NCIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTU5IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkludGVydmVuaXI8L3RleHQ+CgkJPHRleHQgeD0iMTU5IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uYiBoZXVyZXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNjkiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTMiIHk9IjkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQUJPUkRFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNTkyIiB5MT0iNDciIHgyPSI0ODAiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNDkiIHkxPSI0NyIgeDI9IjQ4MCIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTUxMiAxOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFY0NiBoLTkyIFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNTI2IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDQ4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDkyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQzNCIgeT0iMTgiIHdpZHRoPSI5MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQzNCIgeTE9IjQ2IiB4Mj0iNTI2IiB5Mj0iNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0NDEiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QWJvcmRlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUzMSIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQxMCIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQU5JTUFURVVSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIxMTQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QW5pbWF0ZXVyPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gYW5pbWF0ZXVyPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSIxMTUiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gYW5pbWF0ZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBGT1JNQVRJT04gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjkzIiB5PSI5IiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5MyIgeT0iMzkiIHdpZHRoPSIxMTIiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjkzIiB5PSI5IiB3aWR0aD0iMTEyIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI5MyIgeTE9IjM5IiB4Mj0iNDA1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMwMiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Gb3JtYXRpb248L3RleHQ+Cgk8dGV4dCB4PSIzMDEiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlkLiBmb3JtYXRpb248L3RleHQ+Cgk8bGluZSB4MT0iMzAxIiB5MT0iNTkiIHgyPSIzODIiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMwMSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZHVyw6llPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSEVNRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1NTUiIHk9IjE3IiB3aWR0aD0iNzQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTU1IiB5PSI0NyIgd2lkdGg9Ijc0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjU1NSIgeT0iMTciIHdpZHRoPSI3NCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1NTUiIHkxPSI0NyIgeDI9IjYyOSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1NjQiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VGjDqG1lPC90ZXh0PgoJPHRleHQgeD0iNTYzIiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50aMOobWU8L3RleHQ+Cgk8bGluZSB4MT0iNTYzIiB5MT0iNjciIHgyPSI2MDMiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgREFURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNzgiIHk9IjEwMCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3OCIgeT0iMTMwIiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc4IiB5PSIxMDAiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzgiIHkxPSIxMzAiIHgyPSIyMzgiIHkyPSIxMzAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4NyIgeT0iMTIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4NiIgeT0iMTQ3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8bGluZSB4MT0iMTg2IiB5MT0iMTUwIiB4Mj0iMjE0IiB5Mj0iMTUwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez l'explication de la suppression (en NB) et celle de la perte du caractère étranger de l'attribut <em>date</em> (dans la table Intervenir). Pour une discussion sur cette problématique, cf. <a href=\"https://github.com/laowantong/mocodo/issues/66\">issue #66</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Forcer-une-table-pour-%C3%A9viter-un-champ-optionnel\">Forcer une table pour éviter un champ optionnel<a class=\"anchor-link\" href=\"#Forcer-une-table-pour-%C3%A9viter-un-champ-optionnel\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Une association de dépendance fonctionnelle ne donne normalement pas lieu à une création de table. Pour reprendre un exemple vu plus haut :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [71]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c\nEntreprise: id. entreprise, raison, activité, adresse\nEnvoyer, 0N Entreprise, 01 Participant\nParticipant: id. inscrit, nom, adresse\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNDA4IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTlZPWUVSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2OCIgeTE9IjY0IiB4Mj0iMjAyIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzM4IiB5MT0iNjQiIHgyPSIyMDIiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMzQgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05MiBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI0OCA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg5MiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjM1IiB3aWR0aD0iOTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTYiIHkxPSI2MyIgeDI9IjI0OCIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTY0IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVudm95ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzIiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyNTQiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVFJFUFJJU0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW50cmVwcmlzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gZW50cmVwcmlzZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTAxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmFpc29uPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFjdGl2aXTDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBBUlRJQ0lQQU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3NyIgeT0iMTciIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc3IiB5PSI0NyIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzciIHk9IjE3IiB3aWR0aD0iMTIyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NyIgeTE9IjQ3IiB4Mj0iMzk5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4NSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QYXJ0aWNpcGFudDwvdGV4dD4KCTx0ZXh0IHg9IjI4NSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGluc2NyaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjciIHgyPSIzNDMiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI4NSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iMjg1IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Entreprise</strong> (<u>id. entreprise</u>, raison, activité, adresse)</li>\n<li><strong>Participant</strong> (<u>id. inscrit</u>, nom, adresse, <em>#id. entreprise?</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans le cas où les particuliers sont beaucoup plus nombreux que les employés d'entreprise, la clé étrangère <em>#id. entreprise</em> est presque toujours à <code>NULL</code>. C'est une perte d'espace de stockage. On peut <s>entourer l'association de crochets droits</s> préfixer d'un <code>+</code> (à partir de la version 4) l'association pour forcer sa conversion en table. Mocodo produit alors une visualisation intermédiaire entre entité et association :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [72]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --select all -t mld:c --colors mondrian\nEntreprise: id. entreprise, raison, activité, adresse\n+Envoyer, 0N Entreprise, 01 Participant\nParticipant: id. inscrit, nom, adresse\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNDA4IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MDgiIGhlaWdodD0iMTI4IiBmaWxsPSIjZmVmZWVjIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTlZPWUVSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2OCIgeTE9IjY0IiB4Mj0iMjAyIiB5Mj0iNjQiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzM4IiB5MT0iNjQiIHgyPSIyMDIiIHkyPSI2NCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxyZWN0IHg9IjE0NiIgeT0iMjUiIHdpZHRoPSIxMTIiIGhlaWdodD0iNzgiIGZpbGw9IiNmY2VkNWY1NSIgcng9IjciIHN0cm9rZT0iIzA2MDEwMDU1IiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxwYXRoIGQ9Ik0yMzQgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05MiBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiMwODFhODQiIHN0cm9rZT0iIzA4MWE4NCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI0OCA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg5MiIgZmlsbD0iI2ZlZmVlYyIgc3Ryb2tlPSIjZmVmZWVjIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjM1IiB3aWR0aD0iOTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTYiIHkxPSI2MyIgeDI9IjI0OCIgeTI9IjYzIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTY0IiB5PSI1Ni4zIiBmaWxsPSIjZmVmZWVjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVudm95ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzIiIHk9IjgwIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyNTQiIHk9IjgwIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVFJFUFJJU0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW50cmVwcmlzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gZW50cmVwcmlzZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTAxIiB5Mj0iNTkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmFpc29uPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFjdGl2aXTDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBBUlRJQ0lQQU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3NyIgeT0iMTciIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc3IiB5PSI0NyIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzciIHk9IjE3IiB3aWR0aD0iMTIyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NyIgeTE9IjQ3IiB4Mj0iMzk5IiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4NSIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QYXJ0aWNpcGFudDwvdGV4dD4KCTx0ZXh0IHg9IjI4NSIgeT0iNjQuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGluc2NyaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjciIHgyPSIzNDMiIHkyPSI2NyIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI4NSIgeT0iODEuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iMjg1IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Entreprise</strong> (<u>id. entreprise</u>, raison, activité, adresse)</li>\n<li><strong>Envoyer</strong> (<u><em>#id. inscrit</em></u>, <em>#id. entreprise!</em>)</li>\n<li><strong>Participant</strong> (<u>id. inscrit</u>, nom, adresse)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cela permet du même coup d'éviter un champ optionnel, dont la gestion peut être délicate (notamment sous Microsoft SQL Server qui, au mépris du standard SQL, ne semble pas convaincu qu'une colonne <code>UNIQUE</code> peut contenir plus d'un <code>NULL</code> !).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Pr%C3%A9ciser-le-r%C3%B4le-d'une-cl%C3%A9-%C3%A9trang%C3%A8re\">Préciser le rôle d'une clé étrangère<a class=\"anchor-link\" href=\"#Pr%C3%A9ciser-le-r%C3%B4le-d'une-cl%C3%A9-%C3%A9trang%C3%A8re\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ce MCD modélise la soutenance de stage des étudiants, ainsi que la visite d'amitié et de contrôle dont les honore leur enseignant responsable :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [73]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nSoutenir, 01 Étudiant, 0N Date: note stage\nÉtudiant: num. étudiant, nom, coordonnées\n\nDate: date\nRépondre de, 0N Date, 11 Étudiant, 0N Enseignant\nEnseignant: num. enseignant, nom, coordonnées\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTIiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgNDEyIDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTIiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBTT1VURU5JUiAtLT4KPGc+Cgk8bGluZSB4MT0iMTg3IiB5MT0iNTYiIHgyPSI1OCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU4IiB5MT0iMTU2IiB4Mj0iNTgiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik05MyAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTk4IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTA3IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjMgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOSIgeT0iMjciIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjkiIHkxPSI1NSIgeDI9IjEwNyIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTYiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U291dGVuaXI8L3RleHQ+CgkJPHRleHQgeD0iMTYiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vdGUgc3RhZ2U8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMTMiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+Cgk8dGV4dCB4PSI2MyIgeT0iMTE4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUkVQT05EUkVfREUgLS0+CjxnPgoJPGxpbmUgeDE9IjU4IiB5MT0iMTU2IiB4Mj0iMTg3IiB5Mj0iMTU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjE4NyIgeTE9IjU2IiB4Mj0iMTg3IiB5Mj0iMTU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0MiIgeTE9IjE1NiIgeDI9IjE4NyIgeTI9IjE1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMzggMTI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjE1NSBoLTEzMCBWMTQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNTIgMTU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTU1IEgxMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTIyIiB5PSIxMjciIHdpZHRoPSIxMzAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMjIiIHkxPSIxNTUiIHgyPSIyNTIiIHkyPSIxNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMzAiIHk9IjE0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDqXBvbmRyZSBkZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjkzIiB5PSIxNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjE5MiIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIyNTciIHk9IjE3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFVFVESUFOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMzYiIHk9IjkiIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTM2IiB5PSIzOSIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzYiIHk9IjkiIHdpZHRoPSIxMDIiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTM2IiB5MT0iMzkiIHgyPSIyMzgiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQ2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsOJdHVkaWFudDwvdGV4dD4KCTx0ZXh0IHg9IjE0NCIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiDDqXR1ZGlhbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMTQ0IiB5MT0iNTkiIHgyPSIyMzAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE0NCIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iMTQ0IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y29vcmRvbm7DqWVzPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBEQVRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI4IiB5PSIxMjYiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyOCIgeT0iMTU2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjgiIHk9IjEyNiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI4IiB5MT0iMTU2IiB4Mj0iODgiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM3IiB5PSIxNDcuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMzYiIHk9IjE3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPGxpbmUgeDE9IjM2IiB5MT0iMTc2IiB4Mj0iNjQiIHkyPSIxNzYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IEVOU0VJR05BTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjgxIiB5PSIxMDkiIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjgxIiB5PSIxMzkiIHdpZHRoPSIxMjIiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjgxIiB5PSIxMDkiIHdpZHRoPSIxMjIiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjgxIiB5MT0iMTM5IiB4Mj0iNDAzIiB5Mj0iMTM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyOTAiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVuc2VpZ25hbnQ8L3RleHQ+Cgk8dGV4dCB4PSIyODkiIHk9IjE1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIGVuc2VpZ25hbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMjg5IiB5MT0iMTU5IiB4Mj0iMzkwIiB5Mj0iMTU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjg5IiB5PSIxNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iMjg5IiB5PSIxOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvb3Jkb25uw6llczwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Enseignant</strong> (<u>num. enseignant</u>, nom, coordonnées)</li>\n<li><strong>Étudiant</strong> (<u>num. étudiant</u>, nom, coordonnées, date 1, note stage, date 2, <em>#num. enseignant</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Force est de constater que la table Étudiant laisse quelque peu à désirer du point de vue sémantique :</p>\n<ul>\n<li>on ne sait pas à quoi correspondent les attributs <em>date 1</em> et <em>date 2</em> : ils ne peuvent en tout cas certainement pas être laissés en l'état ;</li>\n<li>ensuite, on pourrait avoir envie d'expliciter la raison pour laquelle un enseignant apparaît parmi les attributs d'un étudiant.</li>\n</ul>\n<p>Ces précisions peuvent être apportées en insérant, entre la cardinalité et l'entité des pattes appropriées, une note entre crochets, appelée <strong>rôle</strong>. Ces rôles seront utilisés pour compléter le nom des clés étrangères correspondantes. Cela permet de réintroduire la sémantique perdue lors de la disparition des associations de dépendance fonctionnelle par lesquelles elle ont migré :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [74]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mld\nSoutenir, 01 Étudiant, 0N [soutenance] Date: note stage\nÉtudiant: num. étudiant, nom, coordonnées\n\nDate: date\nRépondre de, 0N [+ visite resp] Date, 11 Étudiant, 0N [-num. ens. resp.] Enseignant\nEnseignant: num. enseignant, nom, coordonnées\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Enseignant</strong> (<u>num. enseignant</u>, nom, coordonnées)</li>\n<li><strong>Étudiant</strong> (<u>num. étudiant</u>, nom, coordonnées, date soutenance, note stage, date visite resp, <em>#num. ens. resp.</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La composition du rôle est entièrement paramétrable :</p>\n<ul>\n<li><em>date soutenance</em> : par défaut, le rôle est concaténé à la clé, avec un séparateur dépendant du gabarit (espace par défaut, tiret bas pour SQL).</li>\n<li><em>date visite resp.</em> : <code>+</code> en préfixe supprime le séparateur.</li>\n<li><em>num. ens. resp.</em> : <code>-</code> en préfixe supprime le nom de la clé et le remplace par le rôle.</li>\n</ul>\n<p>Pour ne pas surcharger le dessin, le rôle n'est pas affiché à côté du lien, mais il apparaît au survol de la cardinalité.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Correction de la version 4.0.</strong> Dans une association réflexive hiérarchique, c'est désormais le rôle porté par la patte <code>*N</code> qui sert à rétablir la sémantique. Auparavant c'était l'inverse, en contradiction avec le traitement des associations binaires et n-aires : si vous avez utilisé des rôles dans une association réflexive avant la version 4.0.0, vous devez donc les permutez pour que Mocodo les traite correctement. Reprenons la filiation patrilinéaire :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [75]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nHOMME: num. SS, nom, prénom\nENGENDRER, 0N [père] HOMME, 01 [fils] HOMME\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNjciIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMjY3IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyNjciIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTkdFTkRSRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfYmVkMTQzYTYgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik01MyA1NiBDODQuNjcgMjQgMTMxIDI0IDE5MiA1NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik01MyA1NiBDODQgODggMTMwLjMzIDg4IDE5MiA1NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDQgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMzIgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNTggNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNDAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTMyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyNiIgeT0iMjciIHdpZHRoPSIxMzIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMjYiIHkxPSI1NSIgeDI9IjI1OCIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTM0IiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVOR0VORFJFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEwMiIgeT0iNDkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93X2JlZDE0M2E2KGV2dCwncMOocmUnKSIgb25tb3VzZW91dD0iaGlkZV9iZWQxNDNhNihldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMTAyIiB5PSI3MSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfYmVkMTQzYTYoZXZ0LCdmaWxzJykiIG9ubW91c2VvdXQ9ImhpZGVfYmVkMTQzYTYoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsMTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgSE9NTUUgLS0+CjxnIGNsYXNzPSJwYWdlXzBfYmVkMTQzYTYgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI5NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5IT01NRTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIFNTPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI2NyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHLDqW5vbTwvdGV4dD4KPC9nPgoKPCEtLSBOb3RlcyAtLT4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2VjbWFzY3JpcHQiPgo8IVtDREFUQVsKCWZ1bmN0aW9uIHNob3dfYmVkMTQzYTYoZXZ0LCB0ZXh0KSB7CgkJdmFyIHBvcyA9IChldnQudGFyZ2V0LmdldEF0dHJpYnV0ZSgieSIpIDwgNjcpID8gImJvdHRvbSIgOiAidG9wIjsKCQl2YXIgbm90ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfbm90ZV9iZWQxNDNhNiIpOwoJCW5vdGUudGV4dENvbnRlbnQgPSB0ZXh0OwoJCW5vdGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfb3ZlcmxheV9iZWQxNDNhNiIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCX0KCWZ1bmN0aW9uIGhpZGVfYmVkMTQzYTYoZXZ0KSB7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9ub3RlX2JlZDE0M2E2Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9vdmVybGF5X2JlZDE0M2E2Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9ub3RlX2JlZDE0M2E2Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9vdmVybGF5X2JlZDE0M2E2Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7Cgl9Cl1dPgo8L3NjcmlwdD4KPHJlY3QgaWQ9InRvcF9vdmVybGF5X2JlZDE0M2E2IiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0idG9wX25vdGVfYmVkMTQzYTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzMyIgeT0iMjQiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8cmVjdCBpZD0iYm90dG9tX292ZXJsYXlfYmVkMTQzYTYiIHg9IjAiIHk9IjcyIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0iYm90dG9tX25vdGVfYmVkMTQzYTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzMyIgeT0iOTYiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>HOMME</strong> (<u>num. SS</u>, nom, prénom, <em>#num. SS père</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Orienter-la-migration-dans-les-DF-%C3%A0-double-sens\">Orienter la migration dans les DF à double sens<a class=\"anchor-link\" href=\"#Orienter-la-migration-dans-les-DF-%C3%A0-double-sens\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Lorsque toutes les cardinalités d'une dépendance fonctionnelle sont 11 (ou toutes 01), le sens de migration est spécifié à coût zéro en référençant l'entité réceptrice en tête de la liste des entités énumérées dans la clause de définition de l'association :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [76]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mld diagram sql --colors mondrian\nUSER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]\nDF, 11 USER, 11 AUTHENTICATION\nAUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>AUTHENTICATION</strong> (<u>email</u>, password hash, salt)</li>\n<li><strong>USER</strong> (<u>user id</u>, name, pseudo, <em>#email</em>)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMzgyIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjM4MiIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBVU0VSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM4IiB5PSI5IiB3aWR0aD0iNjgiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjM5IiB3aWR0aD0iNjgiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI2OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzgiIHkxPSIzOSIgeDI9IjEwNiIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0NyIgeT0iMzAuMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5VU0VSPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnVzZXIgaWQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9Ijg5IiB5Mj0iNTkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0NiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bmFtZTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wc2V1ZG88L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jZW1haWw8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFVVEhFTlRJQ0FUSU9OIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE2NCIgeT0iMTciIHdpZHRoPSIxODAiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY0IiB5PSI0NyIgd2lkdGg9IjE4MCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNjQiIHk9IjE3IiB3aWR0aD0iMTgwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE2NCIgeTE9IjQ3IiB4Mj0iMzQ0IiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3MiIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BVVRIRU5USUNBVElPTjwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iNjQuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZW1haWw8L3RleHQ+Cgk8bGluZSB4MT0iMTcyIiB5MT0iNjciIHgyPSIyMDUiIHkyPSI2NyIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3MiIgeT0iODEuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cGFzc3dvcmQgaGFzaDwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iOTgiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnNhbHQ8L3RleHQ+CjwvZz4KCjwhLS0gTGluayBmcm9tICZxdW90O2VtYWlsJnF1b3Q7IChVU0VSKSB0byAmcXVvdDtlbWFpbCZxdW90OyAoQVVUSEVOVElDQVRJT04pIC0tPgo8cGF0aCBkPSJNMTA2IDEwNC41IEMxMzUgODMgMTI1LjMzIDYxLjUgMTY0IDYxLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTY0IDYxLjUgMTUyIDY3LjUgMTU2IDYxLjUgMTUyIDU1LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxMDYiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">AUTHENTICATION</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">email</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">password_hash</span><span class=\"w\"> </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">64</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">salt</span><span class=\"w\">          </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">16</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"k\">USER</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">user_id</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">name</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">pseudo</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">email</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"k\">USER</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"n\">AUTHENTICATION</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans la version avec identification relative, c'est l'entité faible qui doit être placée en tête :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [77]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mld diagram sql --colors mondrian\nUSER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]\nDF, _11 AUTHENTICATION, 11 USER\nAUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>AUTHENTICATION</strong> (<u><em>#user id</em></u>, <u>email</u>, password hash, salt)</li>\n<li><strong>USER</strong> (<u>user id</u>, name, pseudo)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMzgyIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjM4MiIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBVU0VSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM4IiB5PSIxNyIgd2lkdGg9IjY4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSI0NyIgd2lkdGg9IjY4IiBoZWlnaHQ9IjY0IiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSIxNyIgd2lkdGg9IjY4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM4IiB5MT0iNDciIHgyPSIxMDYiIHkyPSI0NyIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDciIHk9IjM4LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VVNFUjwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij51c2VyIGlkPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNjciIHgyPSI4OSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5hbWU8L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iOTgiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnBzZXVkbzwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQVVUSEVOVElDQVRJT04gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTY0IiB5PSI5IiB3aWR0aD0iMTgwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE2NCIgeT0iMzkiIHdpZHRoPSIxODAiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY0IiB5PSI5IiB3aWR0aD0iMTgwIiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNjQiIHkxPSIzOSIgeDI9IjM0NCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNzIiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QVVUSEVOVElDQVRJT048L3RleHQ+Cgk8dGV4dCB4PSIxNzIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPiN1c2VyIGlkPC90ZXh0PgoJPGxpbmUgeDE9IjE3MiIgeTE9IjU5IiB4Mj0iMjI0IiB5Mj0iNTkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzIiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmVtYWlsPC90ZXh0PgoJPGxpbmUgeDE9IjE3MiIgeTE9Ijc2IiB4Mj0iMjA1IiB5Mj0iNzYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzIiIHk9IjkwLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnBhc3N3b3JkIGhhc2g8L3RleHQ+Cgk8dGV4dCB4PSIxNzIiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2FsdDwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7dXNlciBpZCZxdW90OyAoQVVUSEVOVElDQVRJT04pIHRvICZxdW90O3VzZXIgaWQmcXVvdDsgKFVTRVIpIC0tPgo8cGF0aCBkPSJNMTY0IDUzLjUgQzEzNSA1Ny41IDE0NC42NyA2MS41IDEwNiA2MS41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjEwNiA2MS41IDExOCA1NS41IDExNCA2MS41IDExOCA2Ny41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMTY0IiBjeT0iNTMuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">AUTHENTICATION</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">email</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">user_id</span><span class=\"w\">       </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">email</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">password_hash</span><span class=\"w\"> </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">64</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">salt</span><span class=\"w\">          </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">16</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"k\">USER</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">user_id</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">name</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">pseudo</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">AUTHENTICATION</span><span class=\"w\"> </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"k\">USER</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les traitements alternatifs (fusion en une seule table ou migration dans les deux sens) ne sont pas pris en charge par Mocodo. La dernière pratique ressortit à la phase d'optimisation et de dénormalisation de la base, qui est en dehors de sa juridiction. La seule chose que vous pouvez faire, à des fins d'illustration, est de reprendre le MLD généré pour y ajouter à la main la migration inverse. Notez cependant que les schémas logique et physique générés seront alors dépourvus de toute clé étrangère (et nécessiteront donc également d'être retouchés à la main).</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [78]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t mld sql --colors mondrian --select all\n:\nUSER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)], #email &gt; AUTHENTICATION &gt; email\n:\nAUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)], #user id &gt; USER &gt; user id\n:\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMzgyIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiBmaWxsPSIjZmVmZWVjIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgVVNFUiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9IjY4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSIzOSIgd2lkdGg9IjY4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSI5IiB3aWR0aD0iNjgiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM4IiB5MT0iMzkiIHgyPSIxMDYiIHkyPSIzOSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDciIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VVNFUjwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij51c2VyIGlkPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNTkiIHgyPSI4OSIgeTI9IjU5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5hbWU8L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHNldWRvPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I2VtYWlsPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBVVRIRU5USUNBVElPTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNjQiIHk9IjkiIHdpZHRoPSIxODAiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY0IiB5PSIzOSIgd2lkdGg9IjE4MCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNjQiIHk9IjkiIHdpZHRoPSIxODAiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE2NCIgeTE9IjM5IiB4Mj0iMzQ0IiB5Mj0iMzkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3MiIgeT0iMzAuMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BVVRIRU5USUNBVElPTjwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iNTYuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZW1haWw8L3RleHQ+Cgk8bGluZSB4MT0iMTcyIiB5MT0iNTkiIHgyPSIyMDUiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3MiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cGFzc3dvcmQgaGFzaDwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2FsdDwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jdXNlciBpZDwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7ZW1haWwmcXVvdDsgKFVTRVIpIHRvICZxdW90O2VtYWlsJnF1b3Q7IChBVVRIRU5USUNBVElPTikgLS0+CjxwYXRoIGQ9Ik0xMDYgMTA0LjUgQzEzNSA3OSAxMjUuMzMgNTMuNSAxNjQgNTMuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSIxNjQgNTMuNSAxNTIgNTkuNSAxNTYgNTMuNSAxNTIgNDcuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjEwNiIgY3k9IjEwNC41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O3VzZXIgaWQmcXVvdDsgKEFVVEhFTlRJQ0FUSU9OKSB0byAmcXVvdDt1c2VyIGlkJnF1b3Q7IChVU0VSKSAtLT4KPHBhdGggZD0iTTE2NCAxMDQuNSBDMTM1IDc5IDE0NC42NyA1My41IDEwNiA1My41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjEwNiA1My41IDExOCA0Ny41IDExNCA1My41IDExOCA1OS41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMTY0IiBjeT0iMTA0LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>AUTHENTICATION</strong> (<u>email</u>, password hash, salt, user id)</li>\n<li><strong>USER</strong> (<u>user id</u>, name, pseudo, email)</li>\n</ul>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">AUTHENTICATION</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">email</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">password_hash</span><span class=\"w\"> </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">64</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">salt</span><span class=\"w\">          </span><span class=\"nb\">BINARY</span><span class=\"p\">(</span><span class=\"mi\">16</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">user_id</span><span class=\"w\">       </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"k\">USER</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">user_id</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">user_id</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">name</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">pseudo</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">email</span><span class=\"w\">   </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Autres-sorties-relationnelles\">Autres sorties relationnelles<a class=\"anchor-link\" href=\"#Autres-sorties-relationnelles\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Graphe-des-d%C3%A9pendances\">Graphe des dépendances<a class=\"anchor-link\" href=\"#Graphe-des-d%C3%A9pendances\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La table A <strong>dépend</strong> de la table B lorsque A possède une clé étrangère qui est clé primaire de B. Cette notion est utile dans le cas où l'on doit importer une base de données à partir d'un ensemble de fichiers CSV (ou autres). Si l'on veut éviter de perdre le bénéfice du contrôles de clés étrangères (en faisant, p. ex. sous MySQL, <code>SET FOREIGN_KEY_CHECKS = 0</code>), il conviendra de lire ces fichiers dans un <a href=\"https://fr.wikipedia.org/wiki/Tri_topologique\">ordre topologique</a> quelconque. Mocodo peut générer un graphe des dépendances qui met cet ordre en évidence :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [79]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t dependencies --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_dependencies.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjE5MnB0IiBoZWlnaHQ9IjE4OHB0Igogdmlld0JveD0iMC4wMCAwLjAwIDE5MS43NSAxODguMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTg0KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTg0IDE4Ny43NSwtMTg0IDE4Ny43NSw0IC00LDQiLz4KPCEtLSBDbGllbnQgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+Q2xpZW50PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI3Ny41LC0xODAgMTguNzUsLTE4MCAxOC43NSwtMTQ0IDc3LjUsLTE0NCA3Ny41LC0xODAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDguMTIiIHk9Ii0xNTcuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q2xpZW50PC90ZXh0Pgo8L2c+CjwhLS0gQ29tbWFuZGUgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+Q29tbWFuZGU8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9Ijk2LjI1LC0xMDggMCwtMTA4IDAsLTcyIDk2LjI1LC03MiA5Ni4yNSwtMTA4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ4LjEyIiB5PSItODUuMzMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q29tbWFuZGU8L3RleHQ+CjwvZz4KPCEtLSBDbGllbnQmIzQ1OyZndDtDb21tYW5kZSAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5DbGllbnQmIzQ1OyZndDtDb21tYW5kZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik00OC4xMiwtMTQzLjdDNDguMTIsLTEzNi40MSA0OC4xMiwtMTI3LjczIDQ4LjEyLC0xMTkuNTQiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTEuNjMsLTExOS42MiA0OC4xMywtMTA5LjYyIDQ0LjYzLC0xMTkuNjIgNTEuNjMsLTExOS42MiIvPgo8L2c+CjwhLS0gSW5jbHVyZSAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5JbmNsdXJlPC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxMzEuMjUsLTM2IDY1LC0zNiA2NSwwIDEzMS4yNSwwIDEzMS4yNSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTguMTIiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5JbmNsdXJlPC90ZXh0Pgo8L2c+CjwhLS0gQ29tbWFuZGUmIzQ1OyZndDtJbmNsdXJlIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPkNvbW1hbmRlJiM0NTsmZ3Q7SW5jbHVyZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik02MC40OCwtNzEuN0M2Ni4xOCwtNjMuNzMgNzMuMDUsLTU0LjEgNzkuMzYsLTQ1LjI2Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjgyLjA2LC00Ny41MSA4NS4wMywtMzcuMzQgNzYuMzcsLTQzLjQ0IDgyLjA2LC00Ny41MSIvPgo8L2c+CjwhLS0gUHJvZHVpdCAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5Qcm9kdWl0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNzUsLTEwOCAxMTQuNSwtMTA4IDExNC41LC03MiAxODMuNzUsLTcyIDE4My43NSwtMTA4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE0OS4xMiIgeT0iLTg1LjMzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlByb2R1aXQ8L3RleHQ+CjwvZz4KPCEtLSBQcm9kdWl0JiM0NTsmZ3Q7SW5jbHVyZSAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5Qcm9kdWl0JiM0NTsmZ3Q7SW5jbHVyZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMzYuNTIsLTcxLjdDMTMwLjcxLC02My43MyAxMjMuNywtNTQuMSAxMTcuMjYsLTQ1LjI2Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjEyMC4yLC00My4zNSAxMTEuNDgsLTM3LjMzIDExNC41NCwtNDcuNDcgMTIwLjIsLTQzLjM1Ii8+CjwvZz4KPC9nPgo8L3N2Zz4K\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Même si un tel graphe n'est pas forcément <a href=\"https://fr.wikipedia.org/wiki/Graphe_orient%C3%A9_acyclique\">sans circuits</a>, remplir les tables dans le sens de lecture des langues latines minimisera le recours à la désactivation des contraintes de clés étrangères.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Diagramme-relationnel-/-DDL-BDML\">Diagramme relationnel / DDL BDML<a class=\"anchor-link\" href=\"#Diagramme-relationnel-/-DDL-BDML\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>D'après <a href=\"https://dbml.dbdiagram.io\">son site officiel</a> :</p>\n<blockquote>\n<p>DBML (<em>Database Markup Language</em>) est un DSL (langage dédié) open-source conçu pour définir et documenter les schémas et structures de base de données. Il vise la simplicité, la cohérence et la lisibilité.</p>\n</blockquote>\n<p>Mocodo parle maintenant DBML :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [80]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t dbml --title CCP\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_ddl.dbml\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<pre><code class=\"language-dbml\">dbml\nTable \"Client\" {\n  \"Réf. client\" VARCHAR(8) [pk, NOT NULL]\n  \"Nom\"         VARCHAR(255)\n  \"Prénom\"      VARCHAR(255)\n  \"Adresse\"     VARCHAR(255)\n}\n\nTable \"Commande\" {\n  \"Num. commande\" VARCHAR(8) [pk, NOT NULL]\n  \"Date\"          DATE\n  \"Montant\"       DECIMAL(10,2)\n  \"Réf. client\"   VARCHAR(8) [NOT NULL]\n}\n\nTable \"Inclure\" {\n  \"Num. commande\" VARCHAR(8) [NOT NULL]\n  \"Réf. produit\"  VARCHAR(8) [NOT NULL]\n  \"Quantité\"      INTEGER\n  Indexes {\n    (\"Num. commande\", \"Réf. produit\") [pk]\n  }\n}\n\nTable \"Produit\" {\n  \"Réf. produit\"  VARCHAR(8) [pk, NOT NULL]\n  \"Libellé\"       VARCHAR(50)\n  \"Prix unitaire\" DECIMAL(10,2)\n}\n\nRef:\"Commande\".\"Réf. client\" &gt; \"Client\".\"Réf. client\"\nRef:\"Inclure\".\"Num. commande\" &gt; \"Commande\".\"Num. commande\"\nRef:\"Inclure\".\"Réf. produit\" &gt; \"Produit\".\"Réf. produit\"\n\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>À notre connaissance, il n'existe pas actuellement d'API publique de rendu des diagrammes DBML. Pour les visualiser, copiez-collez la sortie sur <a href=\"https://dbdiagram.io/d/651077feffbf5169f065359b\">Dbdiagram.io</a>, ou installez un <a href=\"https://marketplace.visualstudio.com/items?itemName=nicolas-liger.dbml-viewer\">plugin VS-Code</a> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [81]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">SVG</span><span class=\"p\">(</span><span class=\"s2\">\"../examples/dbml.svg\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[81]:</div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgxLjk2NSIgaGVpZ2h0PSIxNzQuNSI+PHN0eWxlPkBmb250LWZhY2V7Zm9udC1mYW1pbHk6J09wZW4gU2Fucyd9PC9zdHlsZT48c3ZnIHg9IjI1MS4zOTIiIHk9IjI3LjUiIHdpZHRoPSI2NyIgaGVpZ2h0PSIxNDciPjxwYXRoIGQ9Ik00IDIyaDE1cTEwIDAgMTAgMTB2NzlxMCAxMCAxMCAxMGgxNS0xNXEtMTAgMC0xMC0xMFYzMnEwLTEwLTEwLTEwSDRtMTAtNHY4bTQwIDkxLTEwIDQgMTAgNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOUI5Q0E0Ii8+PHRleHQgeD0iNyIgeT0iMTkiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTRweDtmb250LXdlaWdodDo0MDA7ZmlsbDp0cmFuc3BhcmVudCI+MTwvdGV4dD48dGV4dCB4PSI0My4yODkiIHk9IjExOCIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNHB4O2ZvbnQtd2VpZ2h0OjQwMDtmaWxsOnRyYW5zcGFyZW50Ij4qPC90ZXh0Pjwvc3ZnPjxzdmcgeD0iNjAzLjQ0NiIgeT0iMjcuNSIgd2lkdGg9IjY3IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNNCAyMmg1MEg0bTEwLTR2OG00MC04LTEwIDQgMTAgNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOUI5Q0E0Ii8+PHRleHQgeD0iNyIgeT0iMTkiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTRweDtmb250LXdlaWdodDo0MDA7ZmlsbDp0cmFuc3BhcmVudCI+MTwvdGV4dD48dGV4dCB4PSI0My4yODkiIHk9IjE5IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjE0cHg7Zm9udC13ZWlnaHQ6NDAwO2ZpbGw6dHJhbnNwYXJlbnQiPio8L3RleHQ+PC9zdmc+PHN2ZyB4PSI5NTUuNSIgeT0iMjcuNSIgd2lkdGg9IjY3IiBoZWlnaHQ9IjgxIj48cGF0aCBkPSJNNCA1NWgxNXExMCAwIDEwLTEwVjMycTAtMTAgMTAtMTBoMTUtMTVxLTEwIDAtMTAgMTB2MTNxMCAxMC0xMCAxMEg0bTAtNCAxMCA0LTEwIDRtNDAtNDF2OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOUI5Q0E0Ii8+PHRleHQgeD0iNyIgeT0iNTIiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTRweDtmb250LXdlaWdodDo0MDA7ZmlsbDp0cmFuc3BhcmVudCI+KjwvdGV4dD48dGV4dCB4PSI0Mi45OTUiIHk9IjE5IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjE0cHg7Zm9udC13ZWlnaHQ6NDAwO2ZpbGw6dHJhbnNwYXJlbnQiPjE8L3RleHQ+PC9zdmc+PHN2Zz48cGF0aCBmaWxsPSIjMjIyIiBkPSJNMCAwaDI1NS4zOTJ2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmb250LXdlaWdodDo3MDA7ZmlsbDojZmZmIj5DTElFTlQ8L3RleHQ+PC9zdmc+PHN2ZyB5PSIzMyI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgyNTUuMzkydjMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6I2Q3ZDdkOSI+UsOpZi4gY2xpZW50PC90ZXh0PjxwYXRoIGZpbGw9IiNEN0Q3RDkiIGQ9Ik04NS40MyAxMC43MzRhMi45NTMgMi45NTMgMCAxIDEtMS4xMDEgNS42OTVsLS44NjkuODY4aC0uNjU2di45ODRoLS45ODR2Ljk4NUg3OS44NXYtMS45N2wyLjc1Mi0yLjc1YTIuOTUzIDIuOTUzIDAgMCAxIDIuODI2LTMuODF6bTAtLjk4NGEzLjkzNyAzLjkzNyAwIDAgMC0zLjkwMSA0LjQ3N2wtMi41MTggMi41MThhLjQ5My40OTMgMCAwIDAtLjE0NC4zNDh2Mi42NjVjMCAuMjcyLjIyLjQ5Mi40OTIuNDkyaDIuOTUzYy4yNzIgMCAuNDkyLS4yMi40OTItLjQ5MnYtLjQ5MmguNDkyYy4yNzIgMCAuNDkzLS4yMi40OTMtLjQ5M3YtLjQxbC44Mi0uODIzYTMuOTM3IDMuOTM3IDAgMSAwIC44Mi03Ljc5em0wIDIuOTUzYS45ODQuOTg0IDAgMSAwIDEuOTY4IDAgLjk4NC45ODQgMCAwIDAtMS45NjkgMHoiLz48cGF0aCBmaWxsPSIjNjY2IiBkPSJNMjIzLjM5MiA3aDIwczIgMCAyIDJ2MTJzMCAyLTIgMmgtMjBzLTIgMC0yLTJWOXMwLTIgMi0yIi8+PHBhdGggZmlsbD0iI0Q3RDdEOSIgZD0iTTIzMi4yMDMgMTkuNWgtMS4xNjhsLTQuNzUtNy41NmgtLjA0N2wuMDQyLjY5Yy4wMTYuMjU0LjAyOC41MjcuMDM2LjgxOS4wMTIuMjg3LjAxOC41OC4wMTguODhWMTkuNWgtLjk0MnYtOWgxLjE2Mmw0LjczMiA3LjUzNWguMDQxYTE1Ny4xMyAxNTcuMTMgMCAwIDEtLjA2Ni0xLjQ2NSAzMy4yOTYgMzMuMjk2IDAgMCAxLS4wMTEtLjg1NlYxMC41aC45NTN2OXpNMjQxLjM5MiAxOS41aC0xLjE2OGwtNC43NS03LjU2aC0uMDQ3bC4wNDIuNjljLjAxNi4yNTQuMDI4LjUyNy4wMzYuODE5LjAxMS4yODcuMDE3LjU4LjAxNy44OFYxOS41aC0uOTQxdi05aDEuMTYybDQuNzMxIDcuNTM1aC4wNDJhMTU4LjM2NiAxNTguMzY2IDAgMCAxLS4wNjUtMS40NjUgMzMuMDY1IDMzLjA2NSAwIDAgMS0uMDEyLS44NTZWMTAuNWguOTUzdjl6Ii8+PHRleHQgeD0iMTM5LjM2NyIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmb250LXdlaWdodDo3MDA7ZmlsbDojOTk5Ij5WQVJDSEFSKDgpPC90ZXh0Pjwvc3ZnPjxzdmcgeT0iNjYiPjxwYXRoIGZpbGw9IiMzNzM4M0YiIGQ9Ik0wIDBoMjU1LjM5MnYzM0gweiIvPjx0ZXh0IHg9IjEwIiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZpbGw6I2Q3ZDdkOSI+Tm9tPC90ZXh0Pjx0ZXh0IHg9IjE1Ny40MTQiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojOTk5Ij5WQVJDSEFSKDI1NSk8L3RleHQ+PC9zdmc+PHN2ZyB5PSI5OSI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgyNTUuMzkydjMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojZDdkN2Q5Ij5QcsOpbm9tPC90ZXh0Pjx0ZXh0IHg9IjE1Ny40MTQiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojOTk5Ij5WQVJDSEFSKDI1NSk8L3RleHQ+PC9zdmc+PHN2ZyB5PSIxMzIiPjxwYXRoIGZpbGw9IiMzNzM4M0YiIGQ9Ik0wIDBoMjU1LjM5MnYzM0gweiIvPjx0ZXh0IHg9IjEwIiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZpbGw6I2Q3ZDdkOSI+QWRyZXNzZTwvdGV4dD48dGV4dCB4PSIxNTcuNDE0IiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZpbGw6Izk5OSI+VkFSQ0hBUigyNTUpPC90ZXh0Pjwvc3ZnPjxzdmcgeD0iMzA1LjM5MiI+PHBhdGggZmlsbD0iIzIyMiIgZD0iTTAgMGgzMDIuMDU0djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6I2ZmZiI+Q09NTUFOREU8L3RleHQ+PC9zdmc+PHN2ZyB4PSIzMDUuMzkyIiB5PSIzMyI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgzMDIuMDU0djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6I2Q3ZDdkOSI+TnVtLiBjb21tYW5kZTwvdGV4dD48cGF0aCBmaWxsPSIjRDdEN0Q5IiBkPSJNMTMyLjA5IDEwLjczNGEyLjk1MyAyLjk1MyAwIDEgMS0xLjEgNS42OTVsLS44NjguODY4aC0uNjU2di45ODRoLS45ODV2Ljk4NWgtMS45Njh2LTEuOTdsMi43NTEtMi43NWEyLjk1MyAyLjk1MyAwIDAgMSAyLjgyNy0zLjgxem0wLS45ODRhMy45MzcgMy45MzcgMCAwIDAtMy45IDQuNDc3bC0yLjUxOCAyLjUxOGEuNDkzLjQ5MyAwIDAgMC0uMTQ0LjM0OHYyLjY2NWMwIC4yNzIuMjIuNDkyLjQ5My40OTJoMi45NTNjLjI3MSAwIC40OTItLjIyLjQ5Mi0uNDkydi0uNDkyaC40OTJjLjI3MiAwIC40OTItLjIyLjQ5Mi0uNDkzdi0uNDFsLjgyMi0uODIzYTMuOTM3IDMuOTM3IDAgMSAwIC44Mi03Ljc5em0wIDIuOTUzYS45ODQuOTg0IDAgMSAwIDEuOTcgMCAuOTg0Ljk4NCAwIDAgMC0xLjk3IDB6Ii8+PHBhdGggZmlsbD0iIzY2NiIgZD0iTTI3MC4wNTQgN2gyMHMyIDAgMiAydjEyczAgMi0yIDJoLTIwcy0yIDAtMi0yVjlzMC0yIDItMiIvPjxwYXRoIGZpbGw9IiNEN0Q3RDkiIGQ9Ik0yNzguODY1IDE5LjVoLTEuMTY4bC00Ljc1LTcuNTZoLS4wNDdsLjA0Mi42OWMuMDE2LjI1NC4wMjcuNTI3LjAzNS44MTkuMDEyLjI4Ny4wMTguNTguMDE4Ljg4VjE5LjVoLS45NDF2LTloMS4xNjJsNC43MzEgNy41MzVoLjA0MmExNTcuMTMgMTU3LjEzIDAgMCAxLS4wNjYtMS40NjUgMzMuMjk2IDMzLjI5NiAwIDAgMS0uMDEyLS44NTZWMTAuNWguOTU0djl6TTI4OC4wNTQgMTkuNWgtMS4xNjhsLTQuNzUtNy41NmgtLjA0N2wuMDQxLjY5Yy4wMTYuMjU0LjAyOC41MjcuMDM2LjgxOS4wMTIuMjg3LjAxOC41OC4wMTguODhWMTkuNWgtLjk0MXYtOWgxLjE2Mmw0LjczMSA3LjUzNWguMDQyYTE1OC4zNjYgMTU4LjM2NiAwIDAgMS0uMDY2LTEuNDY1IDMzLjA2NSAzMy4wNjUgMCAwIDEtLjAxMi0uODU2VjEwLjVoLjk1NHY5eiIvPjx0ZXh0IHg9IjE4Ni4wMjgiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6Izk5OSI+VkFSQ0hBUig4KTwvdGV4dD48L3N2Zz48c3ZnIHg9IjMwNS4zOTIiIHk9IjY2Ij48cGF0aCBmaWxsPSIjMzczODNGIiBkPSJNMCAwaDMwMi4wNTR2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiNkN2Q3ZDkiPkRhdGU8L3RleHQ+PHRleHQgeD0iMjYwLjAxNyIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiM5OTkiPkRBVEU8L3RleHQ+PC9zdmc+PHN2ZyB4PSIzMDUuMzkyIiB5PSI5OSI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgzMDIuMDU0djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojZDdkN2Q5Ij5Nb250YW50PC90ZXh0Pjx0ZXh0IHg9IjIwMy41NDgiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojOTk5Ij5ERUNJTUFMKDEwLDIpPC90ZXh0Pjwvc3ZnPjxzdmcgeD0iMzA1LjM5MiIgeT0iMTMyIj48cGF0aCBmaWxsPSIjMzczODNGIiBkPSJNMCAwaDMwMi4wNTR2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiNkN2Q3ZDkiPlLDqWYuIGNsaWVudDwvdGV4dD48cGF0aCBmaWxsPSIjNjY2IiBkPSJNMjcwLjA1NCA3aDIwczIgMCAyIDJ2MTJzMCAyLTIgMmgtMjBzLTIgMC0yLTJWOXMwLTIgMi0yIi8+PHBhdGggZmlsbD0iI0Q3RDdEOSIgZD0iTTI3OC44NjUgMTkuNWgtMS4xNjhsLTQuNzUtNy41NmgtLjA0N2wuMDQyLjY5Yy4wMTYuMjU0LjAyNy41MjcuMDM1LjgxOS4wMTIuMjg3LjAxOC41OC4wMTguODhWMTkuNWgtLjk0MXYtOWgxLjE2Mmw0LjczMSA3LjUzNWguMDQyYTE1Ny4xMyAxNTcuMTMgMCAwIDEtLjA2Ni0xLjQ2NSAzMy4yOTYgMzMuMjk2IDAgMCAxLS4wMTItLjg1NlYxMC41aC45NTR2OXpNMjg4LjA1NCAxOS41aC0xLjE2OGwtNC43NS03LjU2aC0uMDQ3bC4wNDEuNjljLjAxNi4yNTQuMDI4LjUyNy4wMzYuODE5LjAxMi4yODcuMDE4LjU4LjAxOC44OFYxOS41aC0uOTQxdi05aDEuMTYybDQuNzMxIDcuNTM1aC4wNDJhMTU4LjM2NiAxNTguMzY2IDAgMCAxLS4wNjYtMS40NjUgMzMuMDY1IDMzLjA2NSAwIDAgMS0uMDEyLS44NTZWMTAuNWguOTU0djl6Ii8+PHRleHQgeD0iMTkwLjk0MSIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiM5OTkiPlZBUkNIQVIoOCk8L3RleHQ+PC9zdmc+PHN2ZyB4PSI2NTcuNDQ2Ij48cGF0aCBmaWxsPSIjMjIyIiBkPSJNMCAwaDMwMi4wNTR2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmb250LXdlaWdodDo3MDA7ZmlsbDojZmZmIj5JTkNMVVJFPC90ZXh0Pjwvc3ZnPjxzdmcgeD0iNjU3LjQ0NiIgeT0iMzMiPjxwYXRoIGZpbGw9IiMzNzM4M0YiIGQ9Ik0wIDBoMzAyLjA1NHYzM0gweiIvPjx0ZXh0IHg9IjEwIiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZvbnQtd2VpZ2h0OjcwMDtmaWxsOiNkN2Q3ZDkiPk51bS4gY29tbWFuZGU8L3RleHQ+PHBhdGggZmlsbD0iI0Q3RDdEOSIgZD0iTTEzMi4wOSAxMC43MzRhMi45NTMgMi45NTMgMCAxIDEtMS4xIDUuNjk1bC0uODY4Ljg2OGgtLjY1NnYuOTg0aC0uOTg1di45ODVoLTEuOTY4di0xLjk3bDIuNzUxLTIuNzVhMi45NTMgMi45NTMgMCAwIDEgMi44MjctMy44MXptMC0uOTg0YTMuOTM3IDMuOTM3IDAgMCAwLTMuOSA0LjQ3N2wtMi41MTggMi41MThhLjQ5My40OTMgMCAwIDAtLjE0NC4zNDh2Mi42NjVjMCAuMjcyLjIyLjQ5Mi40OTMuNDkyaDIuOTUzYy4yNzEgMCAuNDkyLS4yMi40OTItLjQ5MnYtLjQ5MmguNDkyYy4yNzIgMCAuNDkyLS4yMi40OTItLjQ5M3YtLjQxbC44MjItLjgyM2EzLjkzNyAzLjkzNyAwIDEgMCAuODItNy43OXptMCAyLjk1M2EuOTg0Ljk4NCAwIDEgMCAxLjk3IDAgLjk4NC45ODQgMCAwIDAtMS45NyAweiIvPjxwYXRoIGZpbGw9IiM2NjYiIGQ9Ik0yNzAuMDU0IDdoMjBzMiAwIDIgMnYxMnMwIDItMiAyaC0yMHMtMiAwLTItMlY5czAtMiAyLTIiLz48cGF0aCBmaWxsPSIjRDdEN0Q5IiBkPSJNMjc4Ljg2NSAxOS41aC0xLjE2OGwtNC43NS03LjU2aC0uMDQ3bC4wNDIuNjljLjAxNi4yNTQuMDI3LjUyNy4wMzUuODE5LjAxMi4yODcuMDE4LjU4LjAxOC44OFYxOS41aC0uOTQxdi05aDEuMTYybDQuNzMxIDcuNTM1aC4wNDJhMTU3LjEzIDE1Ny4xMyAwIDAgMS0uMDY2LTEuNDY1IDMzLjI5NiAzMy4yOTYgMCAwIDEtLjAxMi0uODU2VjEwLjVoLjk1NHY5ek0yODguMDU0IDE5LjVoLTEuMTY4bC00Ljc1LTcuNTZoLS4wNDdsLjA0MS42OWMuMDE2LjI1NC4wMjguNTI3LjAzNi44MTkuMDEyLjI4Ny4wMTguNTguMDE4Ljg4VjE5LjVoLS45NDF2LTloMS4xNjJsNC43MzEgNy41MzVoLjA0MmExNTguMzY2IDE1OC4zNjYgMCAwIDEtLjA2Ni0xLjQ2NSAzMy4wNjUgMzMuMDY1IDAgMCAxLS4wMTItLjg1NlYxMC41aC45NTR2OXoiLz48dGV4dCB4PSIxODYuMDI4IiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZvbnQtd2VpZ2h0OjcwMDtmaWxsOiM5OTkiPlZBUkNIQVIoOCk8L3RleHQ+PC9zdmc+PHN2ZyB4PSI2NTcuNDQ2IiB5PSI2NiI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgzMDIuMDU0djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6I2Q3ZDdkOSI+UsOpZi4gcHJvZHVpdDwvdGV4dD48cGF0aCBmaWxsPSIjRDdEN0Q5IiBkPSJNOTcuNTAyIDEwLjczNGEyLjk1MyAyLjk1MyAwIDEgMS0xLjEgNS42OTVsLS44NjguODY4aC0uNjU3di45ODRoLS45ODR2Ljk4NWgtMS45Njl2LTEuOTdsMi43NTItMi43NWEyLjk1MyAyLjk1MyAwIDAgMSAyLjgyNi0zLjgxem0wLS45ODRhMy45MzcgMy45MzcgMCAwIDAtMy45IDQuNDc3bC0yLjUxOCAyLjUxOGEuNDkzLjQ5MyAwIDAgMC0uMTQ0LjM0OHYyLjY2NWMwIC4yNzIuMjIuNDkyLjQ5Mi40OTJoMi45NTNjLjI3MiAwIC40OTItLjIyLjQ5Mi0uNDkydi0uNDkyaC40OTNjLjI3MSAwIC40OTItLjIyLjQ5Mi0uNDkzdi0uNDFsLjgyMS0uODIzYTMuOTM3IDMuOTM3IDAgMSAwIC44Mi03Ljc5em0wIDIuOTUzYS45ODQuOTg0IDAgMSAwIDEuOTcgMCAuOTg0Ljk4NCAwIDAgMC0xLjk3IDB6Ii8+PHBhdGggZmlsbD0iIzY2NiIgZD0iTTI3MC4wNTQgN2gyMHMyIDAgMiAydjEyczAgMi0yIDJoLTIwcy0yIDAtMi0yVjlzMC0yIDItMiIvPjxwYXRoIGZpbGw9IiNEN0Q3RDkiIGQ9Ik0yNzguODY1IDE5LjVoLTEuMTY4bC00Ljc1LTcuNTZoLS4wNDdsLjA0Mi42OWMuMDE2LjI1NC4wMjcuNTI3LjAzNS44MTkuMDEyLjI4Ny4wMTguNTguMDE4Ljg4VjE5LjVoLS45NDF2LTloMS4xNjJsNC43MzEgNy41MzVoLjA0MmExNTcuMTMgMTU3LjEzIDAgMCAxLS4wNjYtMS40NjUgMzMuMjk2IDMzLjI5NiAwIDAgMS0uMDEyLS44NTZWMTAuNWguOTU0djl6TTI4OC4wNTQgMTkuNWgtMS4xNjhsLTQuNzUtNy41NmgtLjA0N2wuMDQxLjY5Yy4wMTYuMjU0LjAyOC41MjcuMDM2LjgxOS4wMTIuMjg3LjAxOC41OC4wMTguODhWMTkuNWgtLjk0MXYtOWgxLjE2Mmw0LjczMSA3LjUzNWguMDQyYTE1OC4zNjYgMTU4LjM2NiAwIDAgMS0uMDY2LTEuNDY1IDMzLjA2NSAzMy4wNjUgMCAwIDEtLjAxMi0uODU2VjEwLjVoLjk1NHY5eiIvPjx0ZXh0IHg9IjE4Ni4wMjgiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6Izk5OSI+VkFSQ0hBUig4KTwvdGV4dD48L3N2Zz48c3ZnIHg9IjY1Ny40NDYiIHk9Ijk5Ij48cGF0aCBmaWxsPSIjMzczODNGIiBkPSJNMCAwaDMwMi4wNTR2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiNkN2Q3ZDkiPlF1YW50aXTDqTwvdGV4dD48dGV4dCB4PSIyMzkuNTUyIiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZpbGw6Izk5OSI+SU5URUdFUjwvdGV4dD48L3N2Zz48c3ZnIHg9IjEwMDkuNSI+PHBhdGggZmlsbD0iIzIyMiIgZD0iTTAgMGgyNjcuNDY1djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7Zm9udC13ZWlnaHQ6NzAwO2ZpbGw6I2ZmZiI+UFJPRFVJVDwvdGV4dD48L3N2Zz48c3ZnIHg9IjEwMDkuNSIgeT0iMzMiPjxwYXRoIGZpbGw9IiMzNzM4M0YiIGQ9Ik0wIDBoMjY3LjQ2NXYzM0gweiIvPjx0ZXh0IHg9IjEwIiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZvbnQtd2VpZ2h0OjcwMDtmaWxsOiNkN2Q3ZDkiPlLDqWYuIHByb2R1aXQ8L3RleHQ+PHBhdGggZmlsbD0iI0Q3RDdEOSIgZD0iTTk3LjUwMiAxMC43MzRhMi45NTMgMi45NTMgMCAxIDEtMS4xIDUuNjk1bC0uODY4Ljg2OGgtLjY1N3YuOTg0aC0uOTg0di45ODVoLTEuOTY5di0xLjk3bDIuNzUyLTIuNzVhMi45NTMgMi45NTMgMCAwIDEgMi44MjYtMy44MXptMC0uOTg0YTMuOTM3IDMuOTM3IDAgMCAwLTMuOSA0LjQ3N2wtMi41MTggMi41MThhLjQ5My40OTMgMCAwIDAtLjE0NC4zNDh2Mi42NjVjMCAuMjcyLjIyLjQ5Mi40OTIuNDkyaDIuOTUzYy4yNzIgMCAuNDkyLS4yMi40OTItLjQ5MnYtLjQ5MmguNDkzYy4yNzEgMCAuNDkyLS4yMi40OTItLjQ5M3YtLjQxbC44MjEtLjgyM2EzLjkzNyAzLjkzNyAwIDEgMCAuODItNy43OXptMCAyLjk1M2EuOTg0Ljk4NCAwIDEgMCAxLjk3IDAgLjk4NC45ODQgMCAwIDAtMS45NyAweiIvPjxwYXRoIGZpbGw9IiM2NjYiIGQ9Ik0yMzUuNDY1IDdoMjBzMiAwIDIgMnYxMnMwIDItMiAyaC0yMHMtMiAwLTItMlY5czAtMiAyLTIiLz48cGF0aCBmaWxsPSIjRDdEN0Q5IiBkPSJNMjQ0LjI3NyAxOS41aC0xLjE2OGwtNC43NS03LjU2aC0uMDQ3Yy4wMTEuMjAyLjAyNS40MzEuMDQxLjY5LjAxNi4yNTQuMDI4LjUyNy4wMzYuODE5LjAxMi4yODcuMDE4LjU4LjAxOC44OFYxOS41aC0uOTQydi05aDEuMTYybDQuNzMyIDcuNTM1aC4wNDJhMTU3LjEzIDE1Ny4xMyAwIDAgMS0uMDY2LTEuNDY1IDMzLjI5NiAzMy4yOTYgMCAwIDEtLjAxMi0uODU2VjEwLjVoLjk1NHY5ek0yNTMuNDY1IDE5LjVoLTEuMTY4bC00Ljc0OS03LjU2aC0uMDQ4bC4wNDIuNjljLjAxNi4yNTQuMDI4LjUyNy4wMzYuODE5LjAxMi4yODcuMDE4LjU4LjAxOC44OFYxOS41aC0uOTQydi05aDEuMTYybDQuNzMyIDcuNTM1aC4wNDFhMTU4LjM2NiAxNTguMzY2IDAgMCAxLS4wNjUtMS40NjUgMzMuMDY1IDMzLjA2NSAwIDAgMS0uMDEyLS44NTZWMTAuNWguOTUzdjl6Ii8+PHRleHQgeD0iMTUxLjQ0IiB5PSIxOS43NSIgc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O09wZW4gU2FucyZxdW90OyxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxM3B4O2ZvbnQtd2VpZ2h0OjcwMDtmaWxsOiM5OTkiPlZBUkNIQVIoOCk8L3RleHQ+PC9zdmc+PHN2ZyB4PSIxMDA5LjUiIHk9IjY2Ij48cGF0aCBmaWxsPSIjMzczODNGIiBkPSJNMCAwaDI2Ny40NjV2MzNIMHoiLz48dGV4dCB4PSIxMCIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiNkN2Q3ZDkiPkxpYmVsbMOpPC90ZXh0Pjx0ZXh0IHg9IjE3Ni45MiIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiM5OTkiPlZBUkNIQVIoNTApPC90ZXh0Pjwvc3ZnPjxzdmcgeD0iMTAwOS41IiB5PSI5OSI+PHBhdGggZmlsbD0iIzM3MzgzRiIgZD0iTTAgMGgyNjcuNDY1djMzSDB6Ii8+PHRleHQgeD0iMTAiIHk9IjE5Ljc1IiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7T3BlbiBTYW5zJnF1b3Q7LHNhbnMtc2VyaWY7Zm9udC1zaXplOjEzcHg7ZmlsbDojZDdkN2Q5Ij5Qcml4IHVuaXRhaXJlPC90ZXh0Pjx0ZXh0IHg9IjE2OC45NiIgeT0iMTkuNzUiIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtPcGVuIFNhbnMmcXVvdDssc2Fucy1zZXJpZjtmb250LXNpemU6MTNweDtmaWxsOiM5OTkiPkRFQ0lNQUwoMTAsMik8L3RleHQ+PC9zdmc+PC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Diagramme-relationnel-D2\">Diagramme relationnel D2<a class=\"anchor-link\" href=\"#Diagramme-relationnel-D2\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><a href=\"https://d2lang.com\">D2</a> est un langage de description de diagrammes de différents types. La prise en charge des diagrammes relationnels est minimale, mais le projet est jeune (actuellement en version 0.6.1, open source depuis novembre 2022). Son point fort est TALA, son algorithme de plongement <strong>propriétaire</strong>, que vous pouvez tester <a href=\"https://play.d2lang.com/?script=1JVBb9owFMfv-RRPOW0HOKBWmqg0KaLZlgkS5oZKVVVVHjWTt8QOjjmgivv4Js3n8BebYljjBDBh7NJj5Pzfe3-_n99zvTsvjDvXKApitw_PDoAuqg_5PHmU-HtCHAA3xVLQ6SIhbh9uPTT44qF3F7338Fy1oA_3maApFsvHX2R5BTMuCP3Byo-HVRmD8RTwEjPZeRKcSiNS7_KyEcqIpLUJJcyWOoxiCCfD4cpZOY47iEbj6MZHFkNCFbMuZFS9TAlMeZrxXBWmuw-nmdsTDzN5RsD5AjNJpSrcPgRh7H_2kfZ2rdZjD8X-yA9tDWOLtAtPqsiwkCQlTFoqaV522agD0rJTugx_NB5Gd2p9LjP7cpM0S_hSO6_lPdHWvXGnV6-EPGwQ-RRNUBjYCNGpMsF_EmuS9lj8exRdSs6nVBWydi2nMiVVATO-EIySBlbjQP0e-C0fzAksJbQci6rYVV70NiSNUfTVP4ry0UbsA2lH9BejVzRBkDzjLC9zWUdbjSW3BMndkoT8bxO1Rm-FJc2AIPMFzZsM3ESDQK1j66NujWKzHwLTnDMtxc273g0MqXoRVpeHGxIj79YLhkPr_P8vC-3srpblmgu4a9QFnY9QjVnzxFhw3UOLTKu3j7r-01G53ltWvVHV7kDWytqW2vdXNYG7tXvc5N2MhPqJqajVYy21kaUiV6sq4nfOnaqK_dPC1p9qJrR3Z2ra-zvsYPuEjvs03ktb_mqSlgb_BAAA__8%3D&amp;layout=tala&amp;theme=5&amp;sketch=0&amp;\">ici</a>. Celui-ci requérant une licence payante, si vous déférez le rendu, c'est le plongement par défaut (Dagre, celui de Mermaid) qui sera utilisé.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [82]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t d2\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_ddl.d2\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<pre><code class=\"language-d2\">d2\n\"Client\": { shape: sql_table\n  \"Réf. client\": VARCHAR(8) {constraint: PK}\n  \"Nom\":         VARCHAR(255) \n  \"Prénom\":      VARCHAR(255) \n  \"Adresse\":     VARCHAR(255) \n}\n\n\"Commande\": { shape: sql_table\n  \"Num. commande\": VARCHAR(8) {constraint: PK}\n  \"Date\":          DATE \n  \"Montant\":       DECIMAL(10,2) \n  \"Réf. client\":   VARCHAR(8) {constraint: [FK; NOT NULL]}\n}\n\n\"Inclure\": { shape: sql_table\n  \"Num. commande\": VARCHAR(8) {constraint: [PK; FK]}\n  \"Réf. produit\":  VARCHAR(8) {constraint: [PK; FK]}\n  \"Quantité\":      INTEGER \n}\n\n\"Produit\": { shape: sql_table\n  \"Réf. produit\":  VARCHAR(8) {constraint: PK}\n  \"Libellé\":       VARCHAR(50) \n  \"Prix unitaire\": DECIMAL(10,2) \n}\n\n\"Commande\".\"Réf. client\" -&gt; \"Client\".\"Réf. client\"\n\"Inclure\".\"Num. commande\" -&gt; \"Commande\".\"Num. commande\"\n\"Inclure\".\"Réf. produit\" -&gt; \"Produit\".\"Réf. produit\"\n\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [83]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t d2 --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_ddl.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIGQyVmVyc2lvbj0idjAuNi4zIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0IiB2aWV3Qm94PSIwIDAgMTAyNyA5MDYiPjxzdmcgaWQ9ImQyLXN2ZyIgY2xhc3M9ImQyLTE1NjM3MTc5MTEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiIgdmlld0JveD0iLTEwMSAtMTAxIDEwMjcgOTA2Ij48cmVjdCB4PSItMTAxLjAwMDAwMCIgeT0iLTEwMS4wMDAwMDAiIHdpZHRoPSIxMDI3LjAwMDAwMCIgaGVpZ2h0PSI5MDYuMDAwMDAwIiByeD0iMC4wMDAwMDAiIGNsYXNzPSIgZmlsbC1ONyIgc3Ryb2tlLXdpZHRoPSIwIiAvPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbCi5kMi0xNTYzNzE3OTExIC50ZXh0IHsKCWZvbnQtZmFtaWx5OiAiZDItMTU2MzcxNzkxMS1mb250LXJlZ3VsYXIiOwp9CkBmb250LWZhY2UgewoJZm9udC1mYW1pbHk6IGQyLTE1NjM3MTc5MTEtZm9udC1yZWd1bGFyOwoJc3JjOiB1cmwoImRhdGE6YXBwbGljYXRpb24vZm9udC13b2ZmO2Jhc2U2NCxkMDlHUmdBQkFBQUFBQkZZQUFvQUFBQUFHaVFBQWd1RkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQlBVeTh5QUFBQTlBQUFBR0FBQUFCZ1hkL1ZvMk50WVhBQUFBRlVBQUFBd2dBQUFRd0Z3QWQyWjJ4NVpnQUFBaGdBQUFwZEFBQU9LT2haMmp4b1pXRmtBQUFNZUFBQUFEWUFBQUEyRzRVZTMyaG9aV0VBQUF5d0FBQUFKQUFBQUNRS2hBWDFhRzEwZUFBQUROUUFBQUMyQUFBQXpGMjNDeUJzYjJOaEFBQU5qQUFBQUdnQUFBQm9XWlpkR20xaGVIQUFBQTMwQUFBQUlBQUFBQ0FBU3dEMmJtRnRaUUFBRGhRQUFBTWpBQUFJRkFiRFZVMXdiM04wQUFBUk9BQUFBQjBBQUFBZy85RUFNZ0FEQWdrQmtBQUZBQUFDaWdKWUFBQUFTd0tLQWxnQUFBRmVBRElCSXdBQUFnc0ZBd01FQXdJQ0JHQUFBdmNBQUFBREFBQUFBQUFBQUFCQlJFSlBBRUFBSVAvL0F1Ny9CZ0FBQTlnQkVTQUFBWjhBQUFBQUFlWUNsQUFBQUNBQUEzaWNoTTFMSzRSaEhNYmg2eld2Y1JybjgvbkJZSVl4cEpTTmhheGtKOW5icUNrTEtlVkxpV1R0OEZFc3JTVTdmeG4yYzIvdXpWVS9aQW95bE9TL3B5eko1WktxbXJwdE8zYnRPM1RzMUxtR1M5ZHV2RWNncVRUVjFyODZjT1RFbVlZTFYzOHEzaFJsOFIxZjhSa2Y4Um92OFJ4UDhSZ1BjUjkzY1J0N3pYN3JaZW8yYmFoWlZWRzFabDJiZ2x5N29nNmR1blRyVWRLclQ3OEJnNFlNR3pGcXpMZ0prNlpNbXpGcnpyeGt3YUlsWmN0VytBRUFBUC8vQVFBQS8vOUhIQzRmQUFCNG5IU1dmV3diOWYzSFA5K3ZIVi9UT0UwdTl2bnN4STd0dTlZWHgwNmMrT3c3SjNiT2laK1Nwa21jMkVrYkp5UjlJRzJTcHUydlRYKzBhaHRhb1phMmdnTG1TU0JXdXJJaEFkdlltSkNBQ2UyUElhaTY4VENHRUF4RUs4UWZGUnFEalNqVFJpSG42YzVPR3RENHkxSDA5ZWZoL1hsOTN2NUFHZVFBY0JBL0Fob29oeXFvQVFxQUo1M2tKaWZIc1lUSWl5SkxhMFFPa1VRT2ZTTG5FZG9jMEFxQ3RqWDJSZXpZcVZObzlDUitaSGxmKzVucDZUY21qeDZWNzd2eHVleEg3M3dPR0RRQTJJYnpVQTRrZ0lIZ09aZUxZM1U2allFM3NCeEx2R2wvdzE3anFOWldPVDYrUG5rOUovMGppdjV2YWtyYzM5YTJYeDdEK2VXRFY2OENBQ0FJRkpad0hiNElOb0F5eHVVS0JnU0I5NXRvd3VWaUdaMk9NcHBNdkY4UWFaME9aVEozYmVrN2s0M2NabTJxalRWS0U3eC9YUEwxMnB1NVhmcWh4K2YyUHA1cGRRaFdwdXRJSm5NczFzQUVtdndBZ0dFTUFBZHdIdFlwZGZJazd6ZFJSaDNMOFg0aEdIQ3g3TmpUajE5Njh0R1JMWWNQSHo2OEJlZWZ1L2prcnhQM0xpemNyZFkyQm9DdTR6eFVxSnBSVG9xbldNcEpqYUhqOGtmZmZJTmFjVDcxVHZkWDNhdHYzMWYxdVBXV1ZGL2V2SW56cWVzcCtlUFZmbDM0SWpoK3JGK2wzU0FiNUVtZER0MjI5V3pmd1BsdGlRbHJzeVhtaiswS0hwcGxPdzMzZm1pZkxiWE0xd3UxRzd1T1pCWWVwR3ArbVpULzd2U1Vhc0grbGJxVmFmTWtTenJKc1N4cUhSNlcvNHp6OHBmSXNId1FCZVUzVjJxSDUzRmVtYW55Zml5ckRLZ1VKNHJ6b0MvK24wYzhZV0ExQkRXVzFTQnk4dTB2SjE0L2hQUHl5Mmp6VFhrdkdybjczUlVkM3NKNUtDdmxwc2F5eUk3enl5OTN3MG91ZkNmT0svUG1TZDVnTXRHOElJZ0dwY0tBSUxLRWh0VndyTWxFa1dOVEovVzBYcXVuOUF1N0I5WnB0SUVGY1NHZzFSQTRMLytNU1RKTWtrR1R5d2ZSckhmTzg2ajhLelQ4cUdmT0t6KzJtcU1KNThGUXpFSHpMbGRRMFdBbDh0WXZ1N1VhSXIzMXEyNnRWb2szZGQ0L0YwRFo1WVBveVhPdE13SDVPY0RxbkhiamkxRDFBeklWZkhTY1gxRHhZVlJBVVYvbVZIZjNxVXoyWkUvUHlXeDRXOHZlMGRHOUxhUDY0U2RtWng4YkducHNkdmFKNGMzeFk1bmo5OTkvUEhNc0RxdGNWcWd6TXBhNFZNRmtTWElWelZkN0QwaG45KzNidFRXN2Jlc2t6bThjNlptZWtyOURQVjJwYmxHTkVTaU00OFA0SWxSQ0k4Q203OVZVeHJpNFpyeTJadUxXSnZXdDFvZzA0OGR0M2ZzaXhlcmJaMUwwU05ERVZGWlgrZHZpSjRhVmdvZFB4Sy9uNHV0SEg5cFI3R1V5bjlON3ZHWGFUbDM1YWg4T25JY05RSy9wUStGa2JTdHZ4MmZDZzRsbkppOGRQZENmeWZRZndIbDJLTkUzUWNxZklVcitBdVdpblYyQkloOVdBUFFkemdPaFJHT0RUb29sUDd1Q1ByMkNlMU9wNVplS2I3WVZsbkF6eml0ZXBrNkc1TW1pVHdqcW56b2Rpc2ZucEt3NzZmR20zSVBTWHIyd01JdnVrdTlNajd0YzQybDBXajQxdXlBQVVnZWh3WG1vQk9BMWExalV2UGRlYnJhbXpxQ3RzWkt6SSsvaXZIeXBmWGQ3Kys1MnRHdjVZSkVOOUZ1MENMV3dFWUJtRkRURWdMckFCS2NLVHBHc1lvYWNzc3JxVXIvV01mVEFUMGhQUTJPdnpjSGMzcDRiVEJBYVpzakVTdXl4blg3OTVxN0JFZEllWWgzR05wTjcvN2o4UWJ1MU1jYll6MVZGZk81TmdDRlRXRUxmNHF0Z0tMa0d4eElzeVZORU1WZVJ4K0xvQ2Nwa1FtNW1zME5EeERMWW1XN1l2aXU4UFJWSmg1UDJUdFlSMVR0dGZuejF0VkViZC9aUTlvaVVuQjRidkoxeEZLeDBVZGZtd2hMNkRWcFVadkRqM3FRQVZOTTVFK21hazFxU2xrYktaL01tdVd5Y2FUZHRkQTdxSS9PRG1ma0lRd3NHczI4a2xKMjJHVVdiVStIRVYxaENINjMwVU5STURjNEYrUld4eE9CcW92K01Id2p2RkJzbGh6YWJJRFRXUGt0bnhONVd6MFZkS2YzZHg5S0hwZnJhN0t2TG9UYXJPeG1YcmJRdkc5cDJPMkMxL2oraFJUQ0QvWHNkS0VBNlYvSFhPRldwRU4yMVY0cE9pUk83RVpaZktkdVdZc04xTm52NlRhU050dkZEK283NTlPQzh0REJUYVNudnY0MGlCV005Y3ZYMnAxV2Q2Z0ZRRkw5Zi9DMWxnMkl3VU5LSlpTalY5M2ZFWXNuTmRHTjFUWjAxTVQyTmZpNlY5ZmR1S3llaStzbit1RHdCVUNoQUVnQmV4QzloRjdRQWdBNWFGNG96eUJTVzRLLzRLbFFWVlZMUkxoWCtYTE03czZGY1N4QVY2MHo2dGlEZXMveUlnVVJJMG1xVjd3SGdyOUVpT05VdFZFQldTbHFoa1ZSYUpsWS9Nd2xDNCtqemhLSlZyZ0h2bHMwWmI3T1F5SGg5UWdMZFNMRytWcTg3c0hOQ2ZndTVFOUlXK1hMcG81Z0RmWWdXUzQ1VnlyRVNYVmNNeXc3NCs3c3ozcFpONFUxcXNKVkFyazN5WlNqTjZKOW9FYXFnN24vNjZxcUZvYXJ3ZERRNkhZN3NpVWIzUktMOS9WRnBZS0RFVjJRK016Z2ZTVXhuaDJkbWhyUFRvTzRJajc1Rml5VytibFZuMU9sWXhzWFJsR0h0amlpVk90T2V5VjNoN1NFbXp1Q2o2b3BFTnpxbHQvR0xJV3ZEdVVPWkkxSjk3Y2pUU1BlREhWRTBtRVNMcFd1aW1LVzBJVVVCTEQxdUcxMnROMWJaNHhaMFk3UlpXTitqMWZvbHVYVHZXQXRMNkRSYVZCeWJabHljcUdJWkRMaEtkbjFyM3hRWHArdXgwc0JmQXBPczI1SHd0TFE0K1RvbTFwaExOdzFZR3l5Q285bFQzMUxISnByY2FUMW5GUzNPSnJ1Rm9kZFhPb1B1Y05wQkJ3em1SaXR0b3lvcW5XSXpGMnRRODVzTFN5aUpEeWh1cmZMRkJrV1JWNkZkNWV5TGdZNmV2dlhKMDZlZGpaWDErbXFqVHovV2d5cWxzdlBuNC9KaVUydTVWaUlxMUZoYkNrdm9IWFJENGVGN3JKS2xsZjYwdnlmcmFYR0ZHVVVYcGsrL2N3SUY1QThURXVkQk9ibTJyNkVGRUd3QVFDK2dHMkFCNEVXT3Awc21MUElFelpadVNvTFk4Tk9IYzEwVjVrcHRoYWtpdlBYaFM3bnV5dG9OMmtxelBpWi9QbWRvTkJvYkRYTmYvK3VReVV0Ukh2cVF1bCtxRjJncXNVdUpEQVQ0MFRyMTk4cGJXRUp2NEh1Z1lrV0JRQW1UdGV4OXMyUC8vaDNiOSsvZkhrb2tRcUZrVXYvODVhZWVmZmFweTgvSFRsMjRjT0xFaFF1bjFQN1RBT2hsZkZLOWp4UWJDd3FDeUpNOGxYN28vNzFkdGRFekNmUkJjQjFkdlh3bFVaejlSZ0QwT3I1SElaOFBTcmlFSTdjS3FtTG9QTld3NDJ3cTB0R1FzUG9heHFYY252Z2RmYlVoeSs5YWR6eDRCeSttbWh3K2IzQjZKSExpWEJwcnV3R0JwYkNFL29CUGxsejFGazlxWklPVFlvbGI2L1czdmlsbmc2MHZGQjdxbFp3K201ZEMwWCtUZExOTnpBa2R1L1NDVTdBMnBlT3hYcVBCaXZqdTMrczNlRWFUeVozS0dRMGFjQmVXMEZWOEQ5akJDMjFxTG5WekZjKys1Ykk2Z2lvU3ExbDdpMmhLZ0t2T2ZqTXlLYkppUFN1MFpQanNUbXVEMGVaMzhCT2tnMjBQZXNQdVJGa28yWkp1ZHZGcGZkT2d2N0dydFZwcjZmRzM5cnAzOURyRHZpcHR0YmZENHh0b1FqTzJUdFlYQy9sY2ZsYStFbTExQjF3MWxwUTNtQ3pxM0ZWWWdsZGdYcmwvMTA3NFRndkxXc3dzcTJmcmJDeHJxMk9WdDc3Q1ZyZ0M4MUFEUUhPQ3dPa1lkczFYNGtaUEM4STZiR1kzV2h5YlVyOW9NVVFia00xYVp3ODBkZTRzK2ZVZ0tzZWZLRGNFclVxaGJCQmxOTkVmU0ttVXhMZTN0Ylcvc1B2YW1UUFhwOHpicjgzUFg5c09DRnlGUWJoVytnNm5LcVhNalRMcWN1cDdYa3FsWGlpOU5rOWRQM1BtV3RGMzRHbDBZK1ZHejJUUURia1dVT0dQdUJkRS9KTFNLN21tY0xQZGJqYmI3YmpYWmpIWDE1c3ROZ0JVdUlvNzRBRk5wUkpEdzRuMGhzYjcybkdIK3hrUi9nc0FBUC8vQVFBQS8vL0szeE16QUFBQUFBRUFBQUFDQzRWRk9ObTFYdzg4OVFBREErZ0FBQUFBMkYyZ29RQUFBQURkWmk4Mi9qcisyd2h2QThnQUFBQURBQUlBQUFBQUFBQUFBUUFBQTlqKzd3QUFDSmorT3Y0NkNHOEFBUUFBQUFBQUFBQUFBQUFBQUFBQUFETjRuQ3pMTVVvRFVSUkc0ZlAvVTlocEd5R0VnRUVJU2w3ekVFUXNSS3dzaE51STF3V0lDeEViN2UzZGgvVzRBbmRnS2I0bW1HcUVJZFVwRHA5ZnVhTUh6K2w4UnZVRDZUMVNQNlFmcVg0aHRVUDZrdFEzNlMvU3o2VGZxRDdaOXBUMGhLbWZ1SFVIK3FONlNhaG41U09LZmxscHdZdzFWd3hFZDA3NGdQQnMvS0Y3UXU5TUZVdzg1MW9mN0k2bWNhekdqUm9MTmZiVldMTGhnZzFGaFZEaGtEVUJ3eWNNL1Q4QUFBRC8vd0VBQVAvLzF5VXBHQUFBQUFBQUxBQXNBRkFBZ0FDZUFMUUF5QUQ2QVJJQkhnRTRBVWdCZWdHY0Fjd0I3Z0l3QWxnQ2FnS09BcW9DNGdNV0EwUURkZ09xQTh3RDJBUDBCQ1lFU0FSMEJLZ0V5QVVJQlM0RlVBVjhCWWdGcmdYR0JmQUdKQVo2QnBBR3NBYktCdVFHOEFjR0J4UUFBUUFBQURNQWpBQU1BR1lBQndBQkFBQUFBQUFBQUFBQUFBQUFBQVFBQTNpY25KVGRUaHRYRklVL0I5dHRWRFVYRllySURUcVhiWldNM1FpaUJLNU1DWXBWaEZPUDB4K3BxalI0eGo5aVBEUHlERkNxUGtDdit4WjlpMXoxT2ZvUVZhK3JzN3dOTnFvVWdSQ3d6cHk5OTFsbnI3VVBzTW0vYkZDclB3VCthdjVndU1aMmM4L3dBeDQxbnhyZTRManh0K0g2U2t5RHVQR2I0U1pmTnZxR1ArSjkvUS9ESDdOVC85bndRN2JxUjRZLzRYbDkwL0NuRzQ1L0REOWloL2NMWElPWC9HNjR4aGFGNFFkczhwUGhEUjVqTld0MUh0TTIzT0F6dGcwMzJRWUdUS2xJbVpJeHhqRml5cGh6NWlTVWhDVE1tVElpSWNiUnBVTktwYThaa1pCai9MOWZJMElxNWtTcU9LSENrUktTRWxFeXNZcS9LaXZuclU0Y2FUVzN2UTRWRXlKT2xYRkdSSVlqWjB4T1JzS1o2bFJVRk96Um9rWEpVSHdMS2tvQ1NxYWtCT1RNR2RPaXh4SEhESmd3cGNSeHBFcWVXVWpPaUlwTElwM3ZMTUozWmtoQ1JtbXN6c21JeGRPSlg2THNMc2M0ZWhTS1hhMTh2RmJoS1k3dmxPMjU1WXI5aWtDL2JvWForcmxMTmhFWDZtZXFycVRhdVpTQ0UrMzZjenQ4SzF5eGg3dFhmOWFaZkxoSHNmNVhxbnpLdWZTUHBWUW1KaG5PYmRFaGxJTkM5d1RIZ2RaZFFuWGtlN29NZUVPUGR3eTA3dENuVDRjVEJuUjVyZHdlZlJ4ZjArT0VRMlYwaFJkN1IzTE1DVC9pK0lhdVluenR4UHF6VUN6aEZ3cHpkeW1PYzkxalJxR2VlK2FCN3Byb2huZFgyTTlRdnVhT1VqbER6WkdQZE5JdjA1eEZqTTBWaFJqTzFNdWxOMHJyWDJ5T21Pa3VYdHViZlQ4TkZ6Wjd5eW0rSXRjTWU3Y3VPSG5sRm93K3BHcHd5ek9YK2dtSWlNazVWY1NRbkJrdEtxN0UreTBSNTZRNER0VzlONXFTaXM1MWpqL25TaTVKbUlsQmwweDE1aFQ2RzVsdlF1TStYUE85czdja1ZyNW5lblo5cS91YzR0U3JHNDNlcVh2THZkQzZuS3dvMERKVjh4VTNEY1UxTSs4bm1xbFYvcUZ5UzcxdU9jL29rMGoxVkRlNC9RNDhKNkRORHJ2c005RTVRKzFjMkJ2UjFqdlI1aFg3NnNFWmlhSkdjblZpRlhZSmVNRXV1N3ppeFZyTkRvY2MwR1AvRGh3WFdUME9lSDFyWjEyblpSVm5kZjRVbTdiNE9wNWRyMTdlVzYvUDcrRExMelJSTnk5alg5cjRibDlZdFJ2L254QXg4MXpjMXVxZDNCT0Mvd0FBQVAvL0FRQUEvLzhIVzB3d0FIaWNZbUJtQUlQLzV4aU1HTEFBQUFBQUFQLy9BUUFBLy84dkFRSURBQUFBIik7Cn1dXT48L3N0eWxlPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbLnNoYXBlIHsKICBzaGFwZS1yZW5kZXJpbmc6IGdlb21ldHJpY1ByZWNpc2lvbjsKICBzdHJva2UtbGluZWpvaW46IHJvdW5kOwp9Ci5jb25uZWN0aW9uIHsKICBzdHJva2UtbGluZWNhcDogcm91bmQ7CiAgc3Ryb2tlLWxpbmVqb2luOiByb3VuZDsKfQouYmxlbmQgewogIG1peC1ibGVuZC1tb2RlOiBtdWx0aXBseTsKICBvcGFjaXR5OiAwLjU7Cn0KCgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjF7ZmlsbDojMEEwRjI1O30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1OMntmaWxsOiM2NzZDN0U7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLU4ze2ZpbGw6Izk0OTlBQjt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjR7ZmlsbDojQ0ZEMkREO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1ONXtmaWxsOiNERUUxRUI7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLU42e2ZpbGw6I0VFRjFGODt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjd7ZmlsbDojRkZGRkZGO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1CMXtmaWxsOiMwRDMyQjI7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLUIye2ZpbGw6IzBEMzJCMjt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtQjN7ZmlsbDojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1CNHtmaWxsOiNFM0U5RkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLUI1e2ZpbGw6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtQjZ7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTJ7ZmlsbDojNEE2RkYzO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTR7ZmlsbDojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTV7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQjR7ZmlsbDojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQjV7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4xe3N0cm9rZTojMEEwRjI1O30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4ye3N0cm9rZTojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4ze3N0cm9rZTojOTQ5OUFCO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU40e3N0cm9rZTojQ0ZEMkREO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU41e3N0cm9rZTojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU42e3N0cm9rZTojRUVGMUY4O30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU43e3N0cm9rZTojRkZGRkZGO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIxe3N0cm9rZTojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIye3N0cm9rZTojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIze3N0cm9rZTojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI0e3N0cm9rZTojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI1e3N0cm9rZTojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI2e3N0cm9rZTojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUFBMntzdHJva2U6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLnN0cm9rZS1BQTR7c3Ryb2tlOiNFREYwRkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5zdHJva2UtQUE1e3N0cm9rZTojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUFCNHtzdHJva2U6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLnN0cm9rZS1BQjV7c3Ryb2tlOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU4xe2JhY2tncm91bmQtY29sb3I6IzBBMEYyNTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItTjJ7YmFja2dyb3VuZC1jb2xvcjojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1OM3tiYWNrZ3JvdW5kLWNvbG9yOiM5NDk5QUI7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU40e2JhY2tncm91bmQtY29sb3I6I0NGRDJERDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItTjV7YmFja2dyb3VuZC1jb2xvcjojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1ONntiYWNrZ3JvdW5kLWNvbG9yOiNFRUYxRjg7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU43e2JhY2tncm91bmQtY29sb3I6I0ZGRkZGRjt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQjF7YmFja2dyb3VuZC1jb2xvcjojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1CMntiYWNrZ3JvdW5kLWNvbG9yOiMwRDMyQjI7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLUIze2JhY2tncm91bmQtY29sb3I6I0UzRTlGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQjR7YmFja2dyb3VuZC1jb2xvcjojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1CNXtiYWNrZ3JvdW5kLWNvbG9yOiNFREYwRkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLUI2e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUEye2JhY2tncm91bmQtY29sb3I6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUE0e2JhY2tncm91bmQtY29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUE1e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUI0e2JhY2tncm91bmQtY29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUI1e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU4xe2NvbG9yOiMwQTBGMjU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1OMntjb2xvcjojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItTjN7Y29sb3I6Izk0OTlBQjt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU40e2NvbG9yOiNDRkQyREQ7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1ONXtjb2xvcjojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItTjZ7Y29sb3I6I0VFRjFGODt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU43e2NvbG9yOiNGRkZGRkY7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1CMXtjb2xvcjojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQjJ7Y29sb3I6IzBEMzJCMjt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUIze2NvbG9yOiNFM0U5RkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1CNHtjb2xvcjojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQjV7Y29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUI2e2NvbG9yOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1BQTJ7Y29sb3I6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUFBNHtjb2xvcjojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQUE1e2NvbG9yOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1BQjR7Y29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUFCNXtjb2xvcjojRjdGOEZFO30uYXBwZW5kaXggdGV4dC50ZXh0e2ZpbGw6IzBBMEYyNX0ubWR7LS1jb2xvci1mZy1kZWZhdWx0OiMwQTBGMjU7LS1jb2xvci1mZy1tdXRlZDojNjc2QzdFOy0tY29sb3ItZmctc3VidGxlOiM5NDk5QUI7LS1jb2xvci1jYW52YXMtZGVmYXVsdDojRkZGRkZGOy0tY29sb3ItY2FudmFzLXN1YnRsZTojRUVGMUY4Oy0tY29sb3ItYm9yZGVyLWRlZmF1bHQ6IzBEMzJCMjstLWNvbG9yLWJvcmRlci1tdXRlZDojMEQzMkIyOy0tY29sb3ItbmV1dHJhbC1tdXRlZDojRUVGMUY4Oy0tY29sb3ItYWNjZW50LWZnOiMwRDMyQjI7LS1jb2xvci1hY2NlbnQtZW1waGFzaXM6IzBEMzJCMjstLWNvbG9yLWF0dGVudGlvbi1zdWJ0bGU6IzY3NkM3RTstLWNvbG9yLWRhbmdlci1mZzpyZWQ7fS5za2V0Y2gtb3ZlcmxheS1CMXtmaWxsOnVybCgjc3RyZWFrcy1kYXJrZXIpO21peC1ibGVuZC1tb2RlOmxpZ2h0ZW59LnNrZXRjaC1vdmVybGF5LUIye2ZpbGw6dXJsKCNzdHJlYWtzLWRhcmtlcik7bWl4LWJsZW5kLW1vZGU6bGlnaHRlbn0uc2tldGNoLW92ZXJsYXktQjN7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUI0e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1CNXtmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktQjZ7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUFBMntmaWxsOnVybCgjc3RyZWFrcy1kYXJrKTttaXgtYmxlbmQtbW9kZTpvdmVybGF5fS5za2V0Y2gtb3ZlcmxheS1BQTR7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUFBNXtmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktQUI0e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1BQjV7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LU4xe2ZpbGw6dXJsKCNzdHJlYWtzLWRhcmtlcik7bWl4LWJsZW5kLW1vZGU6bGlnaHRlbn0uc2tldGNoLW92ZXJsYXktTjJ7ZmlsbDp1cmwoI3N0cmVha3MtZGFyayk7bWl4LWJsZW5kLW1vZGU6b3ZlcmxheX0uc2tldGNoLW92ZXJsYXktTjN7ZmlsbDp1cmwoI3N0cmVha3Mtbm9ybWFsKTttaXgtYmxlbmQtbW9kZTpjb2xvci1idXJufS5za2V0Y2gtb3ZlcmxheS1ONHtmaWxsOnVybCgjc3RyZWFrcy1ub3JtYWwpO21peC1ibGVuZC1tb2RlOmNvbG9yLWJ1cm59LnNrZXRjaC1vdmVybGF5LU41e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1ONntmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktTjd7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LmxpZ2h0LWNvZGV7ZGlzcGxheTogYmxvY2t9LmRhcmstY29kZXtkaXNwbGF5OiBub25lfV1dPjwvc3R5bGU+PGcgaWQ9IkNsaWVudCI+PGcgY2xhc3M9InNoYXBlIiA+PHJlY3QgeD0iNzUuMDAwMDAwIiB5PSI1MjQuMDAwMDAwIiB3aWR0aD0iMzAwLjAwMDAwMCIgaGVpZ2h0PSIxODAuMDAwMDAwIiBjbGFzcz0ic2hhcGUgc3Ryb2tlLU4xIGZpbGwtTjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MjsiIC8+PHJlY3QgeD0iNzUuMDAwMDAwIiB5PSI1MjQuMDAwMDAwIiB3aWR0aD0iMzAwLjAwMDAwMCIgaGVpZ2h0PSIzNi4wMDAwMDAiIGNsYXNzPSJjbGFzc19oZWFkZXIgZmlsbC1OMSIgLz48dGV4dCB4PSI4NS4wMDAwMDAiIHk9IjU0OS43NTAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjciIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjRweCI+Q2xpZW50PC90ZXh0Pjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNTgzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+PHRleHQgeD0iMTkxLjAwMDAwMCIgeT0iNTgzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5WQVJDSEFSKDgpPC90ZXh0Pjx0ZXh0IHg9IjM2NS4wMDAwMDAiIHk9IjU4My4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4Ij5QSzwvdGV4dD48bGluZSB4MT0iNzUuMDAwMDAwIiB4Mj0iMzc1LjAwMDAwMCIgeTE9IjU5Ni4wMDAwMDAiIHkyPSI1OTYuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Ob208L3RleHQ+PHRleHQgeD0iMTkxLjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5WQVJDSEFSKDI1NSk8L3RleHQ+PHRleHQgeD0iMzY1LjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9Ijc1LjAwMDAwMCIgeDI9IjM3NS4wMDAwMDAiIHkxPSI2MzIuMDAwMDAwIiB5Mj0iNjMyLjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSI4NS4wMDAwMDAiIHk9IjY1NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UHLDqW5vbTwvdGV4dD48dGV4dCB4PSIxOTEuMDAwMDAwIiB5PSI2NTUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoMjU1KTwvdGV4dD48dGV4dCB4PSIzNjUuMDAwMDAwIiB5PSI2NTUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCIgLz48bGluZSB4MT0iNzUuMDAwMDAwIiB4Mj0iMzc1LjAwMDAwMCIgeTE9IjY2OC4wMDAwMDAiIHkyPSI2NjguMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNjkxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5BZHJlc3NlPC90ZXh0Pjx0ZXh0IHg9IjE5MS4wMDAwMDAiIHk9IjY5MS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUigyNTUpPC90ZXh0Pjx0ZXh0IHg9IjM2NS4wMDAwMDAiIHk9IjY5MS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSI3NS4wMDAwMDAiIHgyPSIzNzUuMDAwMDAwIiB5MT0iNzA0LjAwMDAwMCIgeTI9IjcwNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iQ29tbWFuZGUiPjxnIGNsYXNzPSJzaGFwZSIgPjxyZWN0IHg9IjAuMDAwMDAwIiB5PSIyNDQuMDAwMDAwIiB3aWR0aD0iNDUwLjAwMDAwMCIgaGVpZ2h0PSIxODAuMDAwMDAwIiBjbGFzcz0ic2hhcGUgc3Ryb2tlLU4xIGZpbGwtTjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MjsiIC8+PHJlY3QgeD0iMC4wMDAwMDAiIHk9IjI0NC4wMDAwMDAiIHdpZHRoPSI0NTAuMDAwMDAwIiBoZWlnaHQ9IjM2LjAwMDAwMCIgY2xhc3M9ImNsYXNzX2hlYWRlciBmaWxsLU4xIiAvPjx0ZXh0IHg9IjEwLjAwMDAwMCIgeT0iMjY5Ljc1MDAwMCIgY2xhc3M9InRleHQgZmlsbC1ONyIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyNHB4Ij5Db21tYW5kZTwvdGV4dD48dGV4dCB4PSIxMC4wMDAwMDAiIHk9IjMwMy4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+TnVtLiBjb21tYW5kZTwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSIzMDMuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iMzAzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiPlBLPC90ZXh0PjxsaW5lIHgxPSIwLjAwMDAwMCIgeDI9IjQ1MC4wMDAwMDAiIHkxPSIzMTYuMDAwMDAwIiB5Mj0iMzE2LjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSIxMC4wMDAwMDAiIHk9IjMzOS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+RGF0ZTwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSIzMzkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPkRBVEU8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iMzM5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9IjAuMDAwMDAwIiB4Mj0iNDUwLjAwMDAwMCIgeTE9IjM1Mi4wMDAwMDAiIHkyPSIzNTIuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9IjEwLjAwMDAwMCIgeT0iMzc1LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Nb250YW50PC90ZXh0Pjx0ZXh0IHg9IjE3NC4wMDAwMDAiIHk9IjM3NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+REVDSU1BTCgxMCwyKTwvdGV4dD48dGV4dCB4PSI0NDAuMDAwMDAwIiB5PSIzNzUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCIgLz48bGluZSB4MT0iMC4wMDAwMDAiIHgyPSI0NTAuMDAwMDAwIiB5MT0iMzg4LjAwMDAwMCIgeTI9IjM4OC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iMTAuMDAwMDAwIiB5PSI0MTEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUIyIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlLDqWYuIGNsaWVudDwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSI0MTEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iNDExLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiPkZLLCBOT1QgTlVMTDwvdGV4dD48bGluZSB4MT0iMC4wMDAwMDAiIHgyPSI0NTAuMDAwMDAwIiB5MT0iNDI0LjAwMDAwMCIgeTI9IjQyNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iSW5jbHVyZSI+PGcgY2xhc3M9InNoYXBlIiA+PHJlY3QgeD0iMjYyLjAwMDAwMCIgeT0iMC4wMDAwMDAiIHdpZHRoPSIzNjguMDAwMDAwIiBoZWlnaHQ9IjE0NC4wMDAwMDAiIGNsYXNzPSJzaGFwZSBzdHJva2UtTjEgZmlsbC1ONyIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgLz48cmVjdCB4PSIyNjIuMDAwMDAwIiB5PSIwLjAwMDAwMCIgd2lkdGg9IjM2OC4wMDAwMDAiIGhlaWdodD0iMzYuMDAwMDAwIiBjbGFzcz0iY2xhc3NfaGVhZGVyIGZpbGwtTjEiIC8+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iMjUuNzUwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU43IiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjI0cHgiPkluY2x1cmU8L3RleHQ+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUIyIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPk51bS4gY29tbWFuZGU8L3RleHQ+PHRleHQgeD0iNDM2LjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNjIwLjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCI+UEssIEZLPC90ZXh0PjxsaW5lIHgxPSIyNjIuMDAwMDAwIiB4Mj0iNjMwLjAwMDAwMCIgeTE9IjcyLjAwMDAwMCIgeTI9IjcyLjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSIyNzIuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UsOpZi4gcHJvZHVpdDwvdGV4dD48dGV4dCB4PSI0MzYuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUig4KTwvdGV4dD48dGV4dCB4PSI2MjAuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4Ij5QSywgRks8L3RleHQ+PGxpbmUgeDE9IjI2Mi4wMDAwMDAiIHgyPSI2MzAuMDAwMDAwIiB5MT0iMTA4LjAwMDAwMCIgeTI9IjEwOC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iMTMxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5RdWFudGl0w6k8L3RleHQ+PHRleHQgeD0iNDM2LjAwMDAwMCIgeT0iMTMxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5JTlRFR0VSPC90ZXh0Pjx0ZXh0IHg9IjYyMC4wMDAwMDAiIHk9IjEzMS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSIyNjIuMDAwMDAwIiB4Mj0iNjMwLjAwMDAwMCIgeTE9IjE0NC4wMDAwMDAiIHkyPSIxNDQuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjwvZz48L2c+PGcgaWQ9IlByb2R1aXQiPjxnIGNsYXNzPSJzaGFwZSIgPjxyZWN0IHg9IjUxMC4wMDAwMDAiIHk9IjI2Mi4wMDAwMDAiIHdpZHRoPSIzMTUuMDAwMDAwIiBoZWlnaHQ9IjE0NC4wMDAwMDAiIGNsYXNzPSJzaGFwZSBzdHJva2UtTjEgZmlsbC1ONyIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgLz48cmVjdCB4PSI1MTAuMDAwMDAwIiB5PSIyNjIuMDAwMDAwIiB3aWR0aD0iMzE1LjAwMDAwMCIgaGVpZ2h0PSIzNi4wMDAwMDAiIGNsYXNzPSJjbGFzc19oZWFkZXIgZmlsbC1OMSIgLz48dGV4dCB4PSI1MjAuMDAwMDAwIiB5PSIyODcuNzUwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU43IiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjI0cHgiPlByb2R1aXQ8L3RleHQ+PHRleHQgeD0iNTIwLjAwMDAwMCIgeT0iMzIxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0Pjx0ZXh0IHg9IjY0Mi4wMDAwMDAiIHk9IjMyMS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUig4KTwvdGV4dD48dGV4dCB4PSI4MTUuMDAwMDAwIiB5PSIzMjEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCI+UEs8L3RleHQ+PGxpbmUgeDE9IjUxMC4wMDAwMDAiIHgyPSI4MjUuMDAwMDAwIiB5MT0iMzM0LjAwMDAwMCIgeTI9IjMzNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iNTIwLjAwMDAwMCIgeT0iMzU3LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5MaWJlbGzDqTwvdGV4dD48dGV4dCB4PSI2NDIuMDAwMDAwIiB5PSIzNTcuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoNTApPC90ZXh0Pjx0ZXh0IHg9IjgxNS4wMDAwMDAiIHk9IjM1Ny4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSI1MTAuMDAwMDAwIiB4Mj0iODI1LjAwMDAwMCIgeTE9IjM3MC4wMDAwMDAiIHkyPSIzNzAuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9IjUyMC4wMDAwMDAiIHk9IjM5My4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UHJpeCB1bml0YWlyZTwvdGV4dD48dGV4dCB4PSI2NDIuMDAwMDAwIiB5PSIzOTMuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPkRFQ0lNQUwoMTAsMik8L3RleHQ+PHRleHQgeD0iODE1LjAwMDAwMCIgeT0iMzkzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9IjUxMC4wMDAwMDAiIHgyPSI4MjUuMDAwMDAwIiB5MT0iNDA2LjAwMDAwMCIgeTI9IjQwNi4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iKENvbW1hbmRlIC0mZ3Q7IENsaWVudClbMF0iPjxtYXJrZXIgaWQ9Im1rLTM0ODgzNzgxMzQiIG1hcmtlcldpZHRoPSIxMC4wMDAwMDAiIG1hcmtlckhlaWdodD0iMTIuMDAwMDAwIiByZWZYPSI3LjAwMDAwMCIgcmVmWT0iNi4wMDAwMDAiIHZpZXdCb3g9IjAuMDAwMDAwIDAuMDAwMDAwIDEwLjAwMDAwMCAxMi4wMDAwMDAiIG9yaWVudD0iYXV0byIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIj4gPHBvbHlnb24gcG9pbnRzPSIwLjAwMDAwMCwwLjAwMDAwMCAxMC4wMDAwMDAsNi4wMDAwMDAgMC4wMDAwMDAsMTIuMDAwMDAwIiBjbGFzcz0iY29ubmVjdGlvbiBmaWxsLUIxIiBzdHJva2Utd2lkdGg9IjIiIC8+IDwvbWFya2VyPjxwYXRoIGQ9Ik0gMjI1LjAwMDAwMCA0MjYuMDAwMDAwIEMgMjI1LjAwMDAwMCA0NjQuMDAwMDAwIDIyNS4wMDAwMDAgNDg0LjAwMDAwMCAyMjUuMDAwMDAwIDUyMC4wMDAwMDAiIGZpbGw9Im5vbmUiIGNsYXNzPSJjb25uZWN0aW9uIHN0cm9rZS1CMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgbWFya2VyLWVuZD0idXJsKCNtay0zNDg4Mzc4MTM0KSIgbWFzaz0idXJsKCNkMi0xNTYzNzE3OTExKSIgLz48L2c+PGcgaWQ9IihJbmNsdXJlIC0mZ3Q7IENvbW1hbmRlKVswXSI+PHBhdGggZD0iTSAzMTQuMjQ3MTYyIDE0NC45NjMwOTggQyAyNDMuMTk5OTk3IDE4NC4wMDAwMDAgMjI1LjAwMDAwMCAyMDQuMDAwMDAwIDIyNS4wMDAwMDAgMjQwLjAwMDAwMCIgZmlsbD0ibm9uZSIgY2xhc3M9ImNvbm5lY3Rpb24gc3Ryb2tlLUIxIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjI7IiBtYXJrZXItZW5kPSJ1cmwoI21rLTM0ODgzNzgxMzQpIiBtYXNrPSJ1cmwoI2QyLTE1NjM3MTc5MTEpIiAvPjwvZz48ZyBpZD0iKEluY2x1cmUgLSZndDsgUHJvZHVpdClbMF0iPjxwYXRoIGQ9Ik0gNTc4LjI1MjgzOCAxNDQuOTYzMDk4IEMgNjQ5LjI5OTk4OCAxODQuMDAwMDAwIDY2Ny41MDAwMDAgMjA3LjYwMDAwNiA2NjcuNTAwMDAwIDI1OC4wMDAwMDAiIGZpbGw9Im5vbmUiIGNsYXNzPSJjb25uZWN0aW9uIHN0cm9rZS1CMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgbWFya2VyLWVuZD0idXJsKCNtay0zNDg4Mzc4MTM0KSIgbWFzaz0idXJsKCNkMi0xNTYzNzE3OTExKSIgLz48L2c+PG1hc2sgaWQ9ImQyLTE1NjM3MTc5MTEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9Ii0xMDEiIHk9Ii0xMDEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiI+CjxyZWN0IHg9Ii0xMDEiIHk9Ii0xMDEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiIgZmlsbD0id2hpdGUiPjwvcmVjdD4KCjwvbWFzaz48L3N2Zz48L3N2Zz4K\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Autres-conversions\">Autres conversions<a class=\"anchor-link\" href=\"#Autres-conversions\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Diagramme-de-classes-UML\">Diagramme de classes UML<a class=\"anchor-link\" href=\"#Diagramme-de-classes-UML\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>À tout seigneur tout honneur, Mocodo peut traduire votre MCD en UML. Ce formalisme graphique n'a, curieusement, pas de DSL textuel officiel. Nous nous rabattons donc sur le standard de fait, PlantUML :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [84]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp --title CCP -t uml:plantuml=- # '-' supprime un préambule par défaut qui ne nous intéresse pas ici\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_uml.puml\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<pre><code class=\"language-puml\">puml\n@startuml \"CCP\"\n\n!define Table(x) class \"x\" &lt;&lt; (T,#FFFFFF) &gt;&gt;\n!define pk(x) &lt;b&gt;x&lt;/b&gt;\n\nTable(\"Client\") {\n    {field} + pk(Réf. client) VARCHAR(8)\n    {field} + Nom         VARCHAR(255)\n    {field} + Prénom      VARCHAR(255)\n    {field} + Adresse     VARCHAR(255)\n}\n\n\"Client\" \"1\" --- \"*\" \"Commande\": \"Passer\"\n\nTable(\"Commande\") {\n    {field} + pk(Num. commande) VARCHAR(8)\n    {field} + Date          DATE\n    {field} + Montant       DECIMAL(10,2)\n}\n\n\"Commande\" \"*\" --- \"1..*\" \"Produit\": \"Inclure\"\n(\"Commande\", \"Produit\") .. \"Inclure\"\nTable(\"Inclure\") {\n    {field} + Quantité INTEGER\n}\n\nTable(\"Produit\") {\n    {field} + pk(Réf. produit)  VARCHAR(8)\n    {field} + Libellé       VARCHAR(50)\n    {field} + Prix unitaire DECIMAL(10,2)\n}\n\n@enduml\n\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [85]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t uml --defer --colors brewer+5\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_uml.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxNTlweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjEzMjZweDtoZWlnaHQ6MTU5cHg7YmFja2dyb3VuZDojRjdGN0Y3OyIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgMTMyNiAxNTkiIHdpZHRoPSIxMzI2cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48cmVjdCBmaWxsPSIjRjdGN0Y3IiBoZWlnaHQ9IjE1OSIgc3R5bGU9InN0cm9rZTpub25lO3N0cm9rZS13aWR0aDoxLjA7IiB3aWR0aD0iMTMyNiIgeD0iMCIgeT0iMCIvPjwhLS1jbGFzcyBDbGllbnQtLT48ZyBpZD0iZWxlbV9DbGllbnQiPjxyZWN0IGNvZGVMaW5lPSIyNCIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSIxMDUuMTg3NSIgaWQ9IkNsaWVudCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIzMiIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjIxOCIgeD0iNyIgeT0iMzYuNSIvPjxyZWN0IGNvZGVMaW5lPSIyNCIgZmlsbD0ibm9uZSIgaGVpZ2h0PSIxMDUuMTg3NSIgaWQ9IkNsaWVudCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PGVsbGlwc2UgY3g9Ijg1Ljc1IiBjeT0iMjMiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNODYuNTkzOCwyOS43NSBMODQuMTQwNiwyOS43NSBMODQuMTQwNiwxOS41IEw4MSwxOS41IEw4MSwxNy4zNTk0IEw4OS43MzQ0LDE3LjM1OTQgTDg5LjczNDQsMTkuNSBMODYuNTkzOCwxOS41IEw4Ni41OTM4LDI5Ljc1IFogIiBmaWxsPSIjMDAwMDAwIi8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE4IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjUyIiB4PSIxMDYuMjUiIHk9IjI5LjIzMTQiPkNsaWVudDwvdGV4dD48bGluZSBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHgxPSI4IiB4Mj0iMjI0IiB5MT0iMzkiIHkyPSIzOSIvPjxlbGxpcHNlIGN4PSIxOCIgY3k9IjUyLjY0ODQiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iODgiIHg9IjI3IiB5PSI1NS45OTUxIj5SJiMyMzM7Zi4mIzE2MDtjbGllbnQ8L3RleHQ+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4MCIgeD0iMTIzIiB5PSI1NS45OTUxIj5WQVJDSEFSKDgpPC90ZXh0PjxlbGxpcHNlIGN4PSIxOCIgY3k9IjY4Ljk0NTMiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxOTIiIHg9IjI3IiB5PSI3Mi4yOTIiPk5vbSYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwO1ZBUkNIQVIoMjU1KTwvdGV4dD48ZWxsaXBzZSBjeD0iMTgiIGN5PSI4NS4yNDIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTkyIiB4PSIyNyIgeT0iODguNTg4OSI+UHImIzIzMztub20mIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtWQVJDSEFSKDI1NSk8L3RleHQ+PGVsbGlwc2UgY3g9IjE4IiBjeT0iMTAxLjUzOTEiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxOTIiIHg9IjI3IiB5PSIxMDQuODg1NyI+QWRyZXNzZSYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwO1ZBUkNIQVIoMjU1KTwvdGV4dD48L2c+PCEtLWNsYXNzIENvbW1hbmRlLS0+PGcgaWQ9ImVsZW1fQ29tbWFuZGUiPjxyZWN0IGNvZGVMaW5lPSIzMyIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iQ29tbWFuZGUiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMzkyIiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMzIiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMzkyIiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMi41IiBzdHlsZT0ic3Ryb2tlOiM5MkM1REU7c3Ryb2tlLXdpZHRoOjEuNTsiIHdpZHRoPSIyNDIiIHg9IjM5MiIgeT0iNDQuNjUiLz48cmVjdCBjb2RlTGluZT0iMzMiIGZpbGw9Im5vbmUiIGhlaWdodD0iODguODkwNiIgaWQ9IkNvbW1hbmRlIiByeD0iMi41IiByeT0iMi41IiBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHdpZHRoPSIyNDIiIHg9IjM5MiIgeT0iMTUuMTUiLz48ZWxsaXBzZSBjeD0iNDU4LjI1IiBjeT0iMzEuMTUiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNNDU5LjA5MzgsMzcuOSBMNDU2LjY0MDYsMzcuOSBMNDU2LjY0MDYsMjcuNjUgTDQ1My41LDI3LjY1IEw0NTMuNSwyNS41MDk0IEw0NjIuMjM0NCwyNS41MDk0IEw0NjIuMjM0NCwyNy42NSBMNDU5LjA5MzgsMjcuNjUgTDQ1OS4wOTM4LDM3LjkgWiAiIGZpbGw9IiMwMDAwMDAiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTgiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTAxIiB4PSI0NzguNzUiIHk9IjM3LjM4MTQiPkNvbW1hbmRlPC90ZXh0PjxsaW5lIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgeDE9IjM5MyIgeDI9IjYzMyIgeTE9IjQ3LjE1IiB5Mj0iNDcuMTUiLz48ZWxsaXBzZSBjeD0iNDAzIiBjeT0iNjAuNzk4NCIgZmlsbD0ibm9uZSIgcng9IjMiIHJ5PSIzIiBzdHlsZT0ic3Ryb2tlOiMwMzgwNDg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ibW9ub3NwYWNlIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxMDQiIHg9IjQxMiIgeT0iNjQuMTQ1MSI+TnVtLiYjMTYwO2NvbW1hbmRlPC90ZXh0Pjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iODAiIHg9IjUyNCIgeT0iNjQuMTQ1MSI+VkFSQ0hBUig4KTwvdGV4dD48ZWxsaXBzZSBjeD0iNDAzIiBjeT0iNzcuMDk1MyIgZmlsbD0ibm9uZSIgcng9IjMiIHJ5PSIzIiBzdHlsZT0ic3Ryb2tlOiMwMzgwNDg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ibW9ub3NwYWNlIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjE0NCIgeD0iNDEyIiB5PSI4MC40NDIiPkRhdGUmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtEQVRFPC90ZXh0PjxlbGxpcHNlIGN4PSI0MDMiIGN5PSI5My4zOTIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMjE2IiB4PSI0MTIiIHk9Ijk2LjczODkiPk1vbnRhbnQmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtERUNJTUFMKDEwLDIpPC90ZXh0PjwvZz48IS0tY2xhc3MgUHJvZHVpdC0tPjxnIGlkPSJlbGVtX1Byb2R1aXQiPjxyZWN0IGNvZGVMaW5lPSI0NSIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iUHJvZHVpdCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMzIiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMTA3NyIgeT0iMTUuMTUiLz48cmVjdCBmaWxsPSIjOTJDNURFIiBoZWlnaHQ9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSI0NC42NSIvPjxyZWN0IGNvZGVMaW5lPSI0NSIgZmlsbD0ibm9uZSIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iUHJvZHVpdCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSIxNS4xNSIvPjxlbGxpcHNlIGN4PSIxMTYxLjc1IiBjeT0iMzEuMTUiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNMTE2Mi41OTM4LDM3LjkgTDExNjAuMTQwNiwzNy45IEwxMTYwLjE0MDYsMjcuNjUgTDExNTcsMjcuNjUgTDExNTcsMjUuNTA5NCBMMTE2NS43MzQ0LDI1LjUwOTQgTDExNjUuNzM0NCwyNy42NSBMMTE2Mi41OTM4LDI3LjY1IEwxMTYyLjU5MzgsMzcuOSBaICIgZmlsbD0iIzAwMDAwMCIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI2NCIgeD0iMTE4Mi4yNSIgeT0iMzcuMzgxNCI+UHJvZHVpdDwvdGV4dD48bGluZSBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHgxPSIxMDc4IiB4Mj0iMTMxOCIgeTE9IjQ3LjE1IiB5Mj0iNDcuMTUiLz48ZWxsaXBzZSBjeD0iMTA4OCIgY3k9IjYwLjc5ODQiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOTYiIHg9IjEwOTciIHk9IjY0LjE0NTEiPlImIzIzMztmLiYjMTYwO3Byb2R1aXQ8L3RleHQ+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4MCIgeD0iMTIwOSIgeT0iNjQuMTQ1MSI+VkFSQ0hBUig4KTwvdGV4dD48ZWxsaXBzZSBjeD0iMTA4OCIgY3k9Ijc3LjA5NTMiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIyMDAiIHg9IjEwOTciIHk9IjgwLjQ0MiI+TGliZWxsJiMyMzM7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7VkFSQ0hBUig1MCk8L3RleHQ+PGVsbGlwc2UgY3g9IjEwODgiIGN5PSI5My4zOTIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMjE2IiB4PSIxMDk3IiB5PSI5Ni43Mzg5Ij5Qcml4JiMxNjA7dW5pdGFpcmUmIzE2MDtERUNJTUFMKDEwLDIpPC90ZXh0PjwvZz48IS0tY2xhc3MgSW5jbHVyZS0tPjxnIGlkPSJlbGVtX0luY2x1cmUiPjxyZWN0IGNvZGVMaW5lPSI0MSIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI1Ni4yOTY5IiBpZD0iSW5jbHVyZSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMTU0IiB4PSI4MDAiIHk9Ijk2LjQ0Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIzMiIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMTU0IiB4PSI4MDAiIHk9Ijk2LjQ0Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjE1NCIgeD0iODAwIiB5PSIxMjUuOTQiLz48cmVjdCBjb2RlTGluZT0iNDEiIGZpbGw9Im5vbmUiIGhlaWdodD0iNTYuMjk2OSIgaWQ9IkluY2x1cmUiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjE1NCIgeD0iODAwIiB5PSI5Ni40NCIvPjxlbGxpcHNlIGN4PSI4NDIuNDUiIGN5PSIxMTIuNDQiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNODQzLjI5MzgsMTE5LjE5IEw4NDAuODQwNiwxMTkuMTkgTDg0MC44NDA2LDEwOC45NCBMODM3LjcsMTA4Ljk0IEw4MzcuNywxMDYuNzk5NCBMODQ2LjQzNDQsMTA2Ljc5OTQgTDg0Ni40MzQ0LDEwOC45NCBMODQzLjI5MzgsMTA4Ljk0IEw4NDMuMjkzOCwxMTkuMTkgWiAiIGZpbGw9IiMwMDAwMDAiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTgiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iNjEiIHg9Ijg2Mi41NSIgeT0iMTE4LjY3MTQiPkluY2x1cmU8L3RleHQ+PGxpbmUgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB4MT0iODAxIiB4Mj0iOTUzIiB5MT0iMTI4LjQ0IiB5Mj0iMTI4LjQ0Ii8+PGVsbGlwc2UgY3g9IjgxMSIgY3k9IjE0Mi4wODg0IiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTI4IiB4PSI4MjAiIHk9IjE0NS40MzUxIj5RdWFudGl0JiMyMzM7JiMxNjA7SU5URUdFUjwvdGV4dD48L2c+PGVsbGlwc2UgY3g9Ijg3NyIgY3k9IjU5LjU5IiBmaWxsPSIjMTgxODE4IiByeD0iMiIgcnk9IjIiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjwhLS1saW5rIENsaWVudCB0byBDb21tYW5kZS0tPjxnIGlkPSJsaW5rX0NsaWVudF9Db21tYW5kZSI+PHBhdGggY29kZUxpbmU9IjMxIiBkPSJNMjI1LjQ2LDU5LjU5IEMyNzYuOTYsNTkuNTkgMzM4LjY4LDU5LjU5IDM5MS42Miw1OS41OSAiIGZpbGw9Im5vbmUiIGlkPSJDbGllbnQtQ29tbWFuZGUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjQzIiB4PSIyODciIHk9IjU1LjY1NjkiPlBhc3NlcjwvdGV4dD48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4IiB4PSIyMzMuMDgzMSIgeT0iNzIuMTY1Ij4xPC90ZXh0Pjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjciIHg9IjM3Ny4wMTAxIiB5PSI3Mi4xMTc2Ij4qPC90ZXh0PjwvZz48IS0tbGluayBDb21tYW5kZSB0byBhcG9pbnQ4LS0+PGcgaWQ9ImxpbmtfQ29tbWFuZGVfYXBvaW50OCI+PHBhdGggZD0iTTYzNC4yOSw1OS41OSBDNzM0LjY5LDU5LjU5IDg2My4yOCw1OS41OSA4NzUuMTIsNTkuNTkgIiBmaWxsPSJub25lIiBpZD0iQ29tbWFuZGUtYXBvaW50OCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTMiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iNDIiIHg9IjY5NiIgeT0iNTUuNjU2OSI+SW5jbHVyZTwvdGV4dD48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI3IiB4PSI2NDEuODk0NCIgeT0iNzIuMTE3NiI+KjwvdGV4dD48L2c+PCEtLWxpbmsgYXBvaW50OCB0byBQcm9kdWl0LS0+PGcgaWQ9ImxpbmtfYXBvaW50OF9Qcm9kdWl0Ij48cGF0aCBkPSJNODc5LjQyLDU5LjU5IEM4OTIuNDMsNTkuNTkgOTkyLjI2LDU5LjU5IDEwNzYuNTcsNTkuNTkgIiBmaWxsPSJub25lIiBpZD0iYXBvaW50OC1Qcm9kdWl0IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIyMyIgeD0iMTA0NS44ODUiIHk9IjcyLjA5NCI+MS4uKjwvdGV4dD48L2c+PCEtLWxpbmsgYXBvaW50OCB0byBJbmNsdXJlLS0+PGcgaWQ9ImxpbmtfYXBvaW50OF9JbmNsdXJlIj48cGF0aCBkPSJNODc3LDYxLjg4IEM4NzcsNzMuMyA4NzcsODQuNzMgODc3LDk2LjE1ICIgZmlsbD0ibm9uZSIgaWQ9ImFwb2ludDgtSW5jbHVyZSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheTo3LjAsNy4wOyIvPjwvZz48IS0tU1JDPVtYUEpIUmplbTU4Umx5bklkeFd0UFE0UTBURXM0YTNCQUxnR01DT1BzeHlHZG5TQW5hTjRhckFlRm43Rm1PZENXQUltMXZqcDRFYi1FX18tUzRyeW5KQlg0Y0Q1OE82RmpHWXBlUVdMYUpRM05XeVFpVVNyeTM5QU0yX3MtU3JOMG9xTEV6Z0Ita2xTYndaanBwWDFJRDdGNUxleDBuODFIZUZkQnQwM1o2Y0YzYk5ITTJvd05MRENLTmhKQWJZQ3ZIeXFEYko1Mi1vV2VSRnhQZENTQllMUTZ4bU1MczQwOWZVNlF0VHdza2ttZTVqNXVhSVVNaDIySWhfYnBIRW9DWFNQZTdjSzZWb1hmMmhBck1uVjlDS3FIZGZMS2dvTURhTHJhVl9ETjFCelJQUnZOMVV4aE1pRUtQZ1dCZkRrdnh5SVRxeVl2OGtzR194aHhDMUxnSmlNZndEeDZOSk5xWURHVU5aRHB0dXUzWGV3cDdvQ280MW9iOEl3eUVNM05NeTlIaTdWdWQ0X0VUQmo5RjlpaTlycHU0cXU3Wi02cVNVVE1vQjVBZUxtYnIwdzJBWlJIc3VxaXFHalNvQklqNVRRblR5U2Z2R0JuMlRwU3QwM3ZQRHk3QWFzZlA0WS0wUGJPdndaOW1MeVBFLWJtZEFOTU84NVNpRlgwM052dVg4VG1EZ20wVGtCaTdzOUFPM1dPRk9URjNSX0xSMVV3SW5heG5KbGJsa1ZidVlUUWlPb1JORmo4bllCSkk5bVpzU3EzdU9CZDdLNjVtTjlWel9TaGl1Z3VzTXZXRDl1RFZtd2RrUEJZZ3FGRWl0clZ4WDROcGZWYllLU2VYM3RXdHdPNmhOaGwtSGVvUU15SFV5bEtvbENOXS0tPjwvZz48L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"ERD-avec-la-convention-Look-across\">ERD avec la convention <em>Look across</em><a class=\"anchor-link\" href=\"#ERD-avec-la-convention-Look-across\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.0.</strong> Force est de reconnaître que de nos jours, les MCD à la sauce Merise ne sont plus goûtés que par une poignée d'irréductibles Gaulois (et contractuellement leurs étudiants). Dans le cadre de son projet secret de domination planétaire, Mocodo commence à faire du pied à des notations mieux comprises du reste de l'univers.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Notation-de-Chen\">Notation de Chen<a class=\"anchor-link\" href=\"#Notation-de-Chen\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Un MCD peut être converti en un ERD (<em>Entity-Relationship Diagram</em>) dans la notation de Chen, sans ses attributs ou avec :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [86]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t chen --defer --colors ocean\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI3MHB0IiBoZWlnaHQ9IjEzMHB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI2OS41MCAxMzAuNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTI2LjQpIj4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTEyNi40IDI2NS41LC0xMjYuNCAyNjUuNSw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjU4Ljc1LC0xMjIuNCAwLC0xMjIuNCAwLC04Ni40IDU4Ljc1LC04Ni40IDU4Ljc1LC0xMjIuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOS4zOCIgeT0iLTk5LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMxMzExMTQiPkNsaWVudDwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNiMmJiYTQiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNjUuMzgsLTUwLjQgMTMuNywtMjUuMiA2NS4zNywwIDExNy4wNSwtMjUuMiA2NS4zOCwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2NS4zOCIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMyNzM2MGMiPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0zNy4zNiwtODYuMjdDNDIuODcsLTc0LjQ1IDUwLjIyLC01OC43IDU2LjAxLC00Ni4yOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1Ni4wMSIgeT0iLTYxLjYyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjE3My41LC0xMjIuNCA3Ny4yNSwtMTIyLjQgNzcuMjUsLTg2LjQgMTczLjUsLTg2LjQgMTczLjUsLTEyMi40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEyNS4zOCIgeT0iLTk5LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMxMzExMTQiPkNvbW1hbmRlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTExMS4yNywtODYuODhDMTAxLjUzLC03NC4zNSA4OC4zNiwtNTcuNCA3OC40OSwtNDQuNyIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0xMTIuODUsLTg1LjY1QzEwMy4xMSwtNzMuMTMgODkuOTQsLTU2LjE4IDgwLjA3LC00My40OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5Ny4wOCIgeT0iLTQ4LjU0IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPk48L3RleHQ+CjwvZz4KPCEtLSA0IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIwNy4zOCwtNTAuNCAxNTMuMjUsLTI1LjIgMjA3LjM3LDAgMjYxLjUsLTI1LjIgMjA3LjM4LC01MC40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIwNy4zOCIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMyNzM2MGMiPkluY2x1cmU8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzQgLS0+CjxnIGlkPSJlZGdlNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNMTQyLjg5LC04NS41NEMxNTYuNjcsLTcyLjU3IDE3NS40OCwtNTQuODUgMTg5LjEsLTQyLjAzIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTE0NC4yNiwtODYuOTlDMTU4LjA0LC03NC4wMiAxNzYuODUsLTU2LjMxIDE5MC40OCwtNDMuNDgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjM5IiB5PSItNTYuNjYiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TjwvdGV4dD4KPC9nPgo8IS0tIDUgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjYxLC0xMjIuNCAxOTEuNzUsLTEyMi40IDE5MS43NSwtODYuNCAyNjEsLTg2LjQgMjYxLC0xMjIuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjYuMzgiIHk9Ii05OS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5Qcm9kdWl0PC90ZXh0Pgo8L2c+CjwhLS0gNSYjNDU7JiM0NTs0IC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjUmIzQ1OyYjNDU7NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTIyMi4xNiwtODYuMjdDMjE5LjQsLTc1LjA3IDIxNS43OCwtNjAuMzUgMjEyLjgxLC00OC4yOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjUuMzUiIHk9Ii01OS4xOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjNzI2ZjgzIj5NPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [87]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t chen:attrs --defer --colors ocean\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjEzNjhwdCIgaGVpZ2h0PSIyMTJwdCIKIHZpZXdCb3g9IjAuMDAgMC4wMCAxMzY4LjM0IDIxMi4xMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAyMDguMSkiPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMjA4LjEgMTM2NC4zNCwtMjA4LjEgMTM2NC4zNCw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjI4Ni4yNywtMjA0LjEgMjI3LjUyLC0yMDQuMSAyMjcuNTIsLTE2OC4xIDI4Ni4yNywtMTY4LjEgMjg2LjI3LC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyNTYuOSIgeT0iLTE4MS40MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5DbGllbnQ8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8ZWxsaXBzZSBmaWxsPSIjYzBkNGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBjeD0iMzQuOSIgY3k9Ii0xMDIuMDUiIHJ4PSIzNC45IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzQuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPk5vbTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MyAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjI3LjI3LC0xNzkuMDlDMTkxLjEzLC0xNzEuMTQgMTI4LjcyLC0xNTUuMzQgNzguOSwtMTMyLjEgNzAuMjcsLTEyOC4wOCA2MS4zOSwtMTIyLjUzIDUzLjg5LC0xMTcuMzYiLz4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIxMzcuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI1MC4xNiIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzNy45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UHLDqW5vbTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7NCAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjMxLjY2LC0xNjcuN0MyMTAuNTEsLTE1My4xMiAxODAuNiwtMTMyLjUgMTYwLjI5LC0xMTguNDkiLz4KPC9nPgo8IS0tIDUgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NTwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIyNTYuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI1MS4yMSIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI1Ni45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+QWRyZXNzZTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7NSAtLT4KPGcgaWQ9ImVkZ2U0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjU2LjksLTE2Ny43QzI1Ni45LC0xNTMuNzggMjU2LjksLTEzNC4zNSAyNTYuOSwtMTIwLjQzIi8+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTExIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjM2NS45IiBjeT0iLTEwMi4wNSIgcng9IjM5LjQyIiByeT0iMjUuNDYiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTIuMDIiIHk9Ii0xMDMuNzUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgdGV4dC1kZWNvcmF0aW9uPSJ1bmRlcmxpbmUiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPlLDqWYuPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM0Ni4wMiIgeT0iLTg5Ljc1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIHRleHQtZGVjb3JhdGlvbj0idW5kZXJsaW5lIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5jbGllbnQ8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgZD0iTTI4MC4wMSwtMTY3LjdDMjk3Ljg5LC0xNTQuMjUgMzIyLjU5LC0xMzUuNjUgMzQwLjkyLC0xMjEuODYiLz4KPC9nPgo8IS0tIDYgLS0+CjxnIGlkPSJub2RlMTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjQ3NC45LC0xMjcuMjUgNDIzLjIyLC0xMDIuMDUgNDc0LjksLTc2Ljg1IDUyNi41OCwtMTAyLjA1IDQ3NC45LC0xMjcuMjUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDc0LjkiIHk9Ii05Ny4zOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMjczNjBjIj5QYXNzZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzYgLS0+CjxnIGlkPSJlZGdlMTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjEmIzQ1OyYjNDU7NjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTI4Ni41LC0xNzYuMjdDMzE4LjM2LC0xNjYuNDkgMzcwLjMxLC0xNDkuNzcgNDEzLjksLTEzMi4xIDQyNi4wNywtMTI3LjE3IDQzOS4yNywtMTIwLjk5IDQ1MC4yNywtMTE1LjYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDM3LjY4IiB5PSItMTI2LjQ3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPjE8L3RleHQ+CjwvZz4KPCEtLSA3IC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjc8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjczNS4wMiwtMjA0LjEgNjM4Ljc3LC0yMDQuMSA2MzguNzcsLTE2OC4xIDczNS4wMiwtMTY4LjEgNzM1LjAyLC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2ODYuOSIgeT0iLTE4MS40MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5Db21tYW5kZTwvdGV4dD4KPC9nPgo8IS0tIDkgLS0+CjxnIGlkPSJub2RlNyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+OTwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSI1NzkuOSIgY3k9Ii0xMDIuMDUiIHJ4PSIzNC45IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTc5LjkiIHk9Ii05Ny4zOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5EYXRlPC90ZXh0Pgo8L2c+CjwhLS0gNyYjNDU7JiM0NTs5IC0tPgo8ZyBpZD0iZWRnZTYiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7OTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGQ9Ik02NjQuMjEsLTE2Ny43QzY0NC43LC0xNTIuNzQgNjE2LjksLTEzMS40MyA1OTguNjQsLTExNy40MiIvPgo8L2c+CjwhLS0gMTAgLS0+CjxnIGlkPSJub2RlOCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTA8L3RpdGxlPgo8ZWxsaXBzZSBmaWxsPSIjYzBkNGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBjeD0iNjg2LjkiIGN5PSItMTAyLjA1IiByeD0iNTMuODQiIHJ5PSIxOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2ODYuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPk1vbnRhbnQ8L3RleHQ+CjwvZz4KPCEtLSA3JiM0NTsmIzQ1OzEwIC0tPgo8ZyBpZD0iZWRnZTciIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7MTA8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNNjg2LjksLTE2Ny43QzY4Ni45LC0xNTMuNzggNjg2LjksLTEzNC4zNSA2ODYuOSwtMTIwLjQzIi8+CjwvZz4KPCEtLSA4IC0tPgo8ZyBpZD0ibm9kZTEyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT44PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjgyNC45IiBjeT0iLTEwMi4wNSIgcng9IjY1Ljk0IiByeT0iMjUuNDYiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI4MDUuNCIgeT0iLTEwMy43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+TnVtLjwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3ODYuMjciIHk9Ii04OS43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+Y29tbWFuZGU8L3RleHQ+CjwvZz4KPCEtLSA3JiM0NTsmIzQ1OzggLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NyYjNDU7JiM0NTs4PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgZD0iTTcxNi4xNiwtMTY3LjdDNzM3LjY5LC0xNTQuOTEgNzY3LjAzLC0xMzcuNDYgNzg5LjgxLC0xMjMuOTIiLz4KPC9nPgo8IS0tIDcmIzQ1OyYjNDU7NiAtLT4KPGcgaWQ9ImVkZ2UxNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NyYjNDU7JiM0NTs2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNNjM4LjE1LC0xNzAuNTJDNjA4LjI3LC0xNjAuNTggNTY5LjM1LC0xNDYuOTcgNTM1LjUyLC0xMzMuMDMgNTIzLjMzLC0xMjggNTEwLjEzLC0xMjEuODIgNDk5LjEyLC0xMTYuNDMiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNNjM4Ljc4LC0xNjguNjJDNjA4LjkyLC0xNTguNjkgNTcwLjAxLC0xNDUuMDggNTM2LjI4LC0xMzEuMTggNTI0LjE4LC0xMjYuMTkgNTEwLjk4LC0xMjAgNTAwLC0xMTQuNjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTE5LjU2IiB5PSItMTExLjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPk48L3RleHQ+CjwvZz4KPCEtLSAxMSAtLT4KPGcgaWQ9Im5vZGUxNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9Ijk2Mi45LC0xMjcuMjUgOTA4Ljc3LC0xMDIuMDUgOTYyLjksLTc2Ljg1IDEwMTcuMDMsLTEwMi4wNSA5NjIuOSwtMTI3LjI1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9Ijk2Mi45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzI3MzYwYyI+SW5jbHVyZTwvdGV4dD4KPC9nPgo8IS0tIDcmIzQ1OyYjNDU7MTEgLS0+CjxnIGlkPSJlZGdlMTUiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7MTE8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik03MzUuMjUsLTE3NC43N0M3NzguOSwtMTY1LjcyIDg0NC40OSwtMTUwLjUzIDg5OS41NywtMTMxLjE2IDkxMi4zMywtMTI2LjY4IDkyNi4xMSwtMTIwLjQ5IDkzNy40NywtMTE1Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTczNS42NiwtMTc2LjczQzc3OS4zNSwtMTY3LjY2IDg0NC45NCwtMTUyLjQ3IDkwMC4yMywtMTMzLjA1IDkxMy4xNSwtMTI4LjUgOTI2LjkzLC0xMjIuMzEgOTM4LjM0LC0xMTYuOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5MjUuMjEiIHk9Ii0xMjYuNjgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TjwvdGV4dD4KPC9nPgo8IS0tIDEyIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjEyPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxMTcxLjUyLC0yMDQuMSAxMTAyLjI3LC0yMDQuMSAxMTAyLjI3LC0xNjguMSAxMTcxLjUyLC0xNjguMSAxMTcxLjUyLC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTM2LjkiIHk9Ii0xODEuNDMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzEzMTExNCI+UHJvZHVpdDwvdGV4dD4KPC9nPgo8IS0tIDE1IC0tPgo8ZyBpZD0ibm9kZTkiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE1PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjEwNzkuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI0NC44OSIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwNzkuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPkxpYmVsbMOpPC90ZXh0Pgo8L2c+CjwhLS0gMTImIzQ1OyYjNDU7MTUgLS0+CjxnIGlkPSJlZGdlOSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTEyNC44MSwtMTY3LjdDMTExNS4wMSwtMTUzLjU5IDExMDEuMjcsLTEzMy44MiAxMDkxLjU4LC0xMTkuODciLz4KPC9nPgo8IS0tIDE2IC0tPgo8ZyBpZD0ibm9kZTEwIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xNjwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIxMTkzLjkiIGN5PSItMTAyLjA1IiByeD0iNTEuMDkiIHJ5PSIzMC4wNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTkzLjkiIHk9Ii0xMDYiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UHJpeDwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTE5My45IiB5PSItODguNzUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+dW5pdGFpcmU8L3RleHQ+CjwvZz4KPCEtLSAxMiYjNDU7JiM0NTsxNiAtLT4KPGcgaWQ9ImVkZ2UxMCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTY8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTE0OC45OSwtMTY3LjdDMTE1Ni41LC0xNTYuODggMTE2Ni4zMywtMTQyLjc0IDExNzQuODcsLTEzMC40NCIvPgo8L2c+CjwhLS0gMTQgLS0+CjxnIGlkPSJub2RlMTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE0PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjEzMTEuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI0OC40NCIgcnk9IjI1LjQ2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI5OC4wMiIgeT0iLTEwMy43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UsOpZi48L3RleHQ+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI4NS42NSIgeT0iLTg5Ljc1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIHRleHQtZGVjb3JhdGlvbj0idW5kZXJsaW5lIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5wcm9kdWl0PC90ZXh0Pgo8L2c+CjwhLS0gMTImIzQ1OyYjNDU7MTQgLS0+CjxnIGlkPSJlZGdlOCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTE3MS44OCwtMTY5LjY5QzExOTUuMjEsLTE1OS4zIDEyMjYuNTIsLTE0NS4xNSAxMjUzLjksLTEzMi4xIDEyNjEuNjIsLTEyOC40MiAxMjY5Ljg4LC0xMjQuMzYgMTI3Ny42NiwtMTIwLjQ4Ii8+CjwvZz4KPCEtLSAxMiYjNDU7JiM0NTsxMSAtLT4KPGcgaWQ9ImVkZ2UxMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTE8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0xMTAyLjExLC0xNjguN0MxMDY4Ljc4LC0xNTIuOTggMTAxOS4yNCwtMTI5LjYyIDk4OS4xMiwtMTE1LjQyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwMDkuMTIiIHk9Ii0xMTAuODMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TTwvdGV4dD4KPC9nPgo8IS0tIDEzIC0tPgo8ZyBpZD0ibm9kZTE0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xMzwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjY2Q2YmEiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSI5NjIuOSIgY3k9Ii0xOCIgcng9IjU0Ljg5IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTYyLjkiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjNjA3NzM0Ij5RdWFudGl0w6k8L3RleHQ+CjwvZz4KPCEtLSAxMSYjNDU7JiM0NTsxMyAtLT4KPGcgaWQ9ImVkZ2UxMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTEmIzQ1OyYjNDU7MTM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNOTYyLjksLTc2LjQzQzk2Mi45LC02My41IDk2Mi45LC00Ny45NiA5NjIuOSwtMzYuMzEiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Notation-crow's-foot\">Notation <em>crow's foot</em><a class=\"anchor-link\" href=\"#Notation-crow's-foot\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans le même ordre d'idées, Mocodo peut générer des ERD dans l'astucieuse notation introduite en 1976 par Gordon Everest. Par défaut, le format du fichier intermédiaire est là encore Graphviz :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [88]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t crow --defer --colors brewer+3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_erd_crow.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjYyNHB0IiBoZWlnaHQ9IjMzMnB0Igogdmlld0JveD0iMC4wMCAwLjAwIDYyNC4wMCAzMzEuNTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMzI3LjUpIj4KPHBvbHlnb24gZmlsbD0iI2Y3ZjdmNyIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTMyNy41IDYyMCwtMzI3LjUgNjIwLDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzOSwtMTc2LjUgMzksLTMxOS41IDI2OSwtMzE5LjUgMjY5LC0xNzYuNSAzOSwtMTc2LjUiLz4KPHBvbHlnb24gZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjM5LC0yODguNSAzOSwtMzE5LjUgMjY5LC0zMTkuNSAyNjksLTI4OC41IDM5LC0yODguNSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTI4OC41IDM5LC0zMTkuNSAyNjksLTMxOS41IDI2OSwtMjg4LjUgMzksLTI4OC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI3Ljc1IiB5PSItMjk3LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+Q2xpZW50PC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTI2MC41IDM5LC0yODguNSA2NywtMjg4LjUgNjcsLTI2MC41IDM5LC0yNjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQzLjYyIiB5PSItMjY5LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlBLPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjg4LjUgNjcsLTI4OC41IDY3LC0yNjAuNSAxNTEsLTI2MC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzEuODgiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gY2xpZW50PC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjYwLjUgMjY5LC0yNjAuNSAyNjksLTI4OC41IDE1MSwtMjg4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzQiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM5LC0yMzIuNSAzOSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAzOSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MC43NSIgeT0iLTI0MS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAxNTEsLTIzMi41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzIiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+Tm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjMyLjUgMjY5LC0yMzIuNSAyNjksLTI2MC41IDE1MSwtMjYwLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTIwNC41IDM5LC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDM5LC0yMDQuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMjEzLjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTUxLC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTIxMy4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QcsOpbm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjA0LjUgMjY5LC0yMDQuNSAyNjksLTIzMi41IDE1MSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yMTMuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTE3Ni41IDM5LC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDM5LC0xNzYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMTg1LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTUxLC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDE1MSwtMTc2LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTE4NS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5BZHJlc3NlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMTc2LjUgMjY5LC0xNzYuNSAyNjksLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0xODUuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2Q5ZjBkMyIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjgsLTQgOCwtMTE5IDMwMCwtMTE5IDMwMCwtNCA4LC00Ii8+Cjxwb2x5Z29uIGZpbGw9IiNhNmRiYTAiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSI4LC04OCA4LC0xMTkgMzAwLC0xMTkgMzAwLC04OCA4LC04OCIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtODggOCwtMTE5IDMwMCwtMTE5IDMwMCwtODggOCwtODgiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxMDIuMjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPkNvbW1hbmRlPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtNjAgOCwtODggMzYsLTg4IDM2LC02MCA4LC02MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjEyLjYyIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC04OCAzNiwtODggMzYsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MC43NSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk51bS4gY29tbWFuZGU8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC02MCAzMDAsLTYwIDMwMCwtODggMTczLC04OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIwNSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlZBUkNIQVIoOCk8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI4LC0zMiA4LC02MCAzNiwtNjAgMzYsLTMyIDgsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTkuNzUiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE3MywtNjAgMzYsLTYwIDM2LC0zMiAxNzMsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDEiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EYXRlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE3MywtMzIgMzAwLC0zMiAzMDAsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIyNTkiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EQVRFPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtNCA4LC0zMiAzNiwtMzIgMzYsLTQgOCwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE5Ljc1IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+IDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIxNzMsLTMyIDM2LC0zMiAzNiwtNCAxNzMsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk1vbnRhbnQ8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC00IDMwMCwtNCAzMDAsLTMyIDE3MywtMzIiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzgiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5ERUNJTUFMKDEwLDIpPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7Jmd0OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7Jmd0OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM5OTcwYWIiIGQ9Ik0xNTQsLTE2Mi45NEMxNTQsLTE1NS45NSAxNTQsLTE0OC44OSAxNTQsLTE0MS45MyIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU5LC0xNzEuNzUgMTQ5LC0xNzEuNzUgMTQ5LC0xNjkuNzUgMTU5LC0xNjkuNzUgMTU5LC0xNzEuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIxNTQsLTE3Mi43NSAxNTQsLTE2Ny43NSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU5LC0xNjYuNzUgMTQ5LC0xNjYuNzUgMTQ5LC0xNjQuNzUgMTU5LC0xNjQuNzUgMTU5LC0xNjYuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIxNTQsLTE2Ny43NSAxNTQsLTE2Mi43NSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU0LC0xMzMuMDYgMTU4LjUsLTEyMy4wNiAxNTQsLTEyNy43MyAxNTQsLTEyMy40IDE1NCwtMTIzLjQgMTU0LC0xMjMuNCAxNTQsLTEyNy43MyAxNDkuNSwtMTIzLjA2IDE1NCwtMTMzLjA2Ii8+CjxlbGxpcHNlIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgY3g9IjE1NCIgY3k9Ii0xMzguNzgiIHJ4PSI0IiByeT0iNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIiIHk9Ii0xNDQuMDUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEuMDAiIGZpbGw9IiMxYjc4MzciPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjE4LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjE4LjUgMzU2LjUsLTIxOC41Ii8+Cjxwb2x5Z29uIGZpbGw9IiNhNmRiYTAiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDE0LjYyIiB5PSItMjU1LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+SW5jbHVyZTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1Ni41LC0yMTguNSAzNTYuNSwtMjQ2LjUgMzg0LjUsLTI0Ni41IDM4NC41LC0yMTguNSAzNTYuNSwtMjE4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNjEuMTIiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDYwLjUsLTI0Ni41IDM4NC41LC0yNDYuNSAzODQuNSwtMjE4LjUgNDYwLjUsLTIxOC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg5LjUiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UXVhbnRpdMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ2MC41LC0yMTguNSA1MzMuNSwtMjE4LjUgNTMzLjUsLTI0Ni41IDQ2MC41LC0yNDYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ2NS41IiB5PSItMjI3LjI1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPklOVEVHRVI8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmZ3Q7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmZ3Q7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLWRhc2hhcnJheT0iMSw1IiBkPSJNMzgxLjA3LC0yMDYuNDdDMzQ0Ljg5LC0xODMuNTMgMjk4Ljc4LC0xNTQuMyAyNTcuNTgsLTEyOC4xNyIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMzg1LjI1LC0yMDkuMTIgMzkxLjI5LC0yMTguMjcgMzg5Ljc2LC0yMTEuOTcgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzg5Ljc2LC0yMTEuOTcgMzk2LjExLC0yMTAuNjcgMzg1LjI1LC0yMDkuMTIiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjM4Ni4wNSwtMjAzLjcxIDM4MC43LC0yMTIuMTUgMzc5LjAxLC0yMTEuMDggMzg0LjM3LC0yMDIuNjQgMzg2LjA1LC0yMDMuNzEiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIzODQuMjIsLTIwOC40NyAzODAsLTIwNS43OSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMjQ3LjMsLTEyNy41OCAyNTIuNjYsLTExOS4xMyAyNTQuMzUsLTEyMC4yIDI0OC45OSwtMTI4LjY1IDI0Ny4zLC0xMjcuNTgiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIyNDkuMTQsLTEyMi44MiAyNTMuMzYsLTEyNS41Ii8+Cjxwb2x5Z29uIGZpbGw9IiM5OTcwYWIiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIyNTEuNTMsLTEzMC4yNSAyNTYuODgsLTEyMS44MSAyNTguNTcsLTEyMi44OCAyNTMuMjIsLTEzMS4zMyAyNTEuNTMsLTEzMC4yNSIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjI1My4zNiwtMTI1LjUgMjU3LjU4LC0xMjguMTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjk4LjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMWI3ODM3Ij5ERjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTIsLTQgMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC00IDM1MiwtNCIvPgo8cG9seWdvbiBmaWxsPSIjYTZkYmEwIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iMzUyLC04OCAzNTIsLTExOSA2MDgsLTExOSA2MDgsLTg4IDM1MiwtODgiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtODggMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC04OCAzNTIsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDQ4LjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPlByb2R1aXQ8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIzNTIsLTYwIDM1MiwtODggMzgwLC04OCAzODAsLTYwIDM1MiwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTYuNjIiIHk9Ii02OC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QSzwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI0ODEsLTg4IDM4MCwtODggMzgwLC02MCA0ODEsLTYwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg1IiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI0ODEsLTYwIDYwOCwtNjAgNjA4LC04OCA0ODEsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNTEzIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtMzIgMzUyLC02MCAzODAsLTYwIDM4MCwtMzIgMzUyLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDgxLC02MCAzODAsLTYwIDM4MCwtMzIgNDgxLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM4NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPkxpYmVsbMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ4MSwtMzIgNjA4LC0zMiA2MDgsLTYwIDQ4MSwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MDQiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5WQVJDSEFSKDUwKTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtNCAzNTIsLTMyIDM4MCwtMzIgMzgwLC00IDM1MiwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDgxLC0zMiAzODAsLTMyIDM4MCwtNCA0ODEsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzODQuNzUiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ4MSwtNCA2MDgsLTQgNjA4LC0zMiA0ODEsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDg2IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+REVDSU1BTCgxMCwyKTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyZndDs0IC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyZndDs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2UtZGFzaGFycmF5PSIxLDUiIGQ9Ik00NTQuNywtMTk1Ljg3QzQ1OC40MiwtMTc2LjI3IDQ2Mi43MywtMTUzLjU2IDQ2Ni43MiwtMTMyLjUiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ1My4wMiwtMjA0LjcxIDQ0Ni43NCwtMjEzLjcgNDUyLjAzLC0yMDkuOTUgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUyLjAzLC0yMDkuOTUgNDU1LjU4LC0yMTUuMzcgNDUzLjAyLC0yMDQuNzEiLz4KPGVsbGlwc2UgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBjeD0iNDU0LjA5IiBjeT0iLTE5OS4wOSIgcng9IjQiIHJ5PSI0Ii8+Cjxwb2x5Z29uIGZpbGw9IiM5OTcwYWIiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSI0NjMuNDMsLTEyMyA0NzMuMjYsLTEyNC44NyA0NzIuODksLTEyNi44MyA0NjMuMDYsLTEyNC45NyA0NjMuNDMsLTEyMyIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2OC41MywtMTIyLjk1IDQ2Ny42LC0xMjcuODYiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2Mi41LC0xMjcuOTIgNDcyLjMzLC0xMjkuNzggNDcxLjk1LC0xMzEuNzQgNDYyLjEzLC0xMjkuODggNDYyLjUsLTEyNy45MiIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2Ny42LC0xMjcuODYgNDY2LjY3LC0xMzIuNzgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDcyLjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMWI3ODM3Ij5ERjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il est également possible de demander une sortie au format Mermaid. Vous en avez un exemple dans l'introduction, nous ne le répétons pas ici. Le DSL de Mermaid est de plus haut niveau, non encombré d'informations de style. Cependant, le format Graphviz peut être préféré pour plusieurs raisons :</p>\n<ul>\n<li>on peut lui appliquer une palette de couleurs de Mocodo (cf. ci-dessus) ;</li>\n<li>il gère les accents ;</li>\n<li>il admet la virgule dans les types (Mermaid demande <a href=\"https://github.com/mermaid-js/mermaid/issues/1546\">actuellement</a> à transformer <code>DECIMAL(10,2)</code> en <code>DECIMAL(10-2)</code>) ;</li>\n<li>il peut produire de meilleurs plongements (notamment en jouant sur la valeur de l'option <code>--seed</code>) ;</li>\n<li>ceux-ci peuvent-être rectifiés à la main (quoique péniblement).</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Dictionnaire-des-donn%C3%A9es\">Dictionnaire des données<a class=\"anchor-link\" href=\"#Dictionnaire-des-donn%C3%A9es\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez extraire sous forme de table diverses informations sur les attributs de votre MCD.</p>\n<p>Un format possible est TSV. Dans ce cas, sous Jupyter Notebook, si la bibliothèque <code>pandas</code> est installée, elle sera rendue comme un <em>dataframe</em> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [89]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t data_dict:tsv\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_data_dict_3.tsv\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style type=\"text/css\">\n#T_83121 th {\n  text-align: left;\n}\n#T_83121_row0_col0, #T_83121_row0_col1, #T_83121_row0_col2, #T_83121_row1_col0, #T_83121_row1_col1, #T_83121_row1_col2, #T_83121_row2_col0, #T_83121_row2_col1, #T_83121_row2_col2, #T_83121_row3_col0, #T_83121_row3_col1, #T_83121_row3_col2, #T_83121_row4_col0, #T_83121_row4_col1, #T_83121_row4_col2, #T_83121_row5_col0, #T_83121_row5_col1, #T_83121_row5_col2, #T_83121_row6_col0, #T_83121_row6_col1, #T_83121_row6_col2, #T_83121_row7_col0, #T_83121_row7_col1, #T_83121_row7_col2, #T_83121_row8_col0, #T_83121_row8_col1, #T_83121_row8_col2, #T_83121_row9_col0, #T_83121_row9_col1, #T_83121_row9_col2, #T_83121_row10_col0, #T_83121_row10_col1, #T_83121_row10_col2 {\n  text-align: left;\n}\n</style>\n<table id=\"T_83121\">\n<thead>\n<tr>\n<th class=\"blank level0\"> </th>\n<th class=\"col_heading level0 col0\" id=\"T_83121_level0_col0\">Entité ou association</th>\n<th class=\"col_heading level0 col1\" id=\"T_83121_level0_col1\">Libellé de l'attribut</th>\n<th class=\"col_heading level0 col2\" id=\"T_83121_level0_col2\">Type</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<th class=\"row_heading level0 row0\" id=\"T_83121_level0_row0\">0</th>\n<td class=\"data row0 col0\" id=\"T_83121_row0_col0\">Client</td>\n<td class=\"data row0 col1\" id=\"T_83121_row0_col1\">Adresse</td>\n<td class=\"data row0 col2\" id=\"T_83121_row0_col2\">VARCHAR(255)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row1\" id=\"T_83121_level0_row1\">1</th>\n<td class=\"data row1 col0\" id=\"T_83121_row1_col0\">Client</td>\n<td class=\"data row1 col1\" id=\"T_83121_row1_col1\">Nom</td>\n<td class=\"data row1 col2\" id=\"T_83121_row1_col2\">VARCHAR(255)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row2\" id=\"T_83121_level0_row2\">2</th>\n<td class=\"data row2 col0\" id=\"T_83121_row2_col0\">Client</td>\n<td class=\"data row2 col1\" id=\"T_83121_row2_col1\">Prénom</td>\n<td class=\"data row2 col2\" id=\"T_83121_row2_col2\">VARCHAR(255)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row3\" id=\"T_83121_level0_row3\">3</th>\n<td class=\"data row3 col0\" id=\"T_83121_row3_col0\">Client</td>\n<td class=\"data row3 col1\" id=\"T_83121_row3_col1\">Réf. client</td>\n<td class=\"data row3 col2\" id=\"T_83121_row3_col2\">VARCHAR(8)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row4\" id=\"T_83121_level0_row4\">4</th>\n<td class=\"data row4 col0\" id=\"T_83121_row4_col0\">Commande</td>\n<td class=\"data row4 col1\" id=\"T_83121_row4_col1\">Date</td>\n<td class=\"data row4 col2\" id=\"T_83121_row4_col2\">DATE</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row5\" id=\"T_83121_level0_row5\">5</th>\n<td class=\"data row5 col0\" id=\"T_83121_row5_col0\">Commande</td>\n<td class=\"data row5 col1\" id=\"T_83121_row5_col1\">Montant</td>\n<td class=\"data row5 col2\" id=\"T_83121_row5_col2\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row6\" id=\"T_83121_level0_row6\">6</th>\n<td class=\"data row6 col0\" id=\"T_83121_row6_col0\">Commande</td>\n<td class=\"data row6 col1\" id=\"T_83121_row6_col1\">Num. commande</td>\n<td class=\"data row6 col2\" id=\"T_83121_row6_col2\">VARCHAR(8)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row7\" id=\"T_83121_level0_row7\">7</th>\n<td class=\"data row7 col0\" id=\"T_83121_row7_col0\">Inclure</td>\n<td class=\"data row7 col1\" id=\"T_83121_row7_col1\">Quantité</td>\n<td class=\"data row7 col2\" id=\"T_83121_row7_col2\">INTEGER</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row8\" id=\"T_83121_level0_row8\">8</th>\n<td class=\"data row8 col0\" id=\"T_83121_row8_col0\">Produit</td>\n<td class=\"data row8 col1\" id=\"T_83121_row8_col1\">Libellé</td>\n<td class=\"data row8 col2\" id=\"T_83121_row8_col2\">VARCHAR(50)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row9\" id=\"T_83121_level0_row9\">9</th>\n<td class=\"data row9 col0\" id=\"T_83121_row9_col0\">Produit</td>\n<td class=\"data row9 col1\" id=\"T_83121_row9_col1\">Prix unitaire</td>\n<td class=\"data row9 col2\" id=\"T_83121_row9_col2\">DECIMAL(10,2)</td>\n</tr>\n<tr>\n<th class=\"row_heading level0 row10\" id=\"T_83121_level0_row10\">10</th>\n<td class=\"data row10 col0\" id=\"T_83121_row10_col0\">Produit</td>\n<td class=\"data row10 col1\" id=\"T_83121_row10_col1\">Réf. produit</td>\n<td class=\"data row10 col2\" id=\"T_83121_row10_col2\">VARCHAR(8)</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le format par défaut est Markdown. Vous pouvez préciser en sous-sous-option tout ou partie des colonnes suivantes dans l'ordre où vous les souhaitez :</p>\n<ul>\n<li><code>label</code>: le libellé de l'attribut ;</li>\n<li><code>type</code> : son type ou un descriptif (auquel cas il conviendra de changer le nom de la colonne) ;</li>\n<li><code>box</code> : le nom de l'entité ou association où il se trouve.</li>\n</ul>\n<p>Entourez ces noms de colonnes de balises Markdown pour les mettre en forme (pas d'incidence en TSV). Faites-les suivre de <code>=\"Nom de colonne personnalisé\"</code> pour éviter la valeur par défaut (dépendante de l'option <code>language</code>). Dans l'exemple ci-dessous, les sous-sous-options se décodent ainsi :</p>\n<ul>\n<li><code>**box**=\"Entité ou association\"</code> : boîtes en colonne 1, en-tête personnalisé, cellules en gras ;</li>\n<li><code>label</code> : libellé des attributs en colonne 2 ;</li>\n<li>`<code>type</code>`<code>=</code>`<code>Type</code>` : types en colonne 3, en-tête personnalisé et cellules dans une police non proportionnelle.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [90]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t data_dict:**box**=\"Entité ou&lt;br&gt;association\",label,`type`=`\"Type de données\"`\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_data_dict_3.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\"><strong>Entité ou<br/>association</strong></th>\n<th style=\"text-align:left\">Libellé de l'attribut</th>\n<th style=\"text-align:left\"><code>Type de données</code></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><strong>Client</strong></td>\n<td style=\"text-align:left\">Adresse</td>\n<td style=\"text-align:left\"><code>VARCHAR(255)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Nom</td>\n<td style=\"text-align:left\"><code>VARCHAR(255)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Prénom</td>\n<td style=\"text-align:left\"><code>VARCHAR(255)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Réf. client</td>\n<td style=\"text-align:left\"><code>VARCHAR(8)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>Commande</strong></td>\n<td style=\"text-align:left\">Date</td>\n<td style=\"text-align:left\"><code>DATE</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Montant</td>\n<td style=\"text-align:left\"><code>DECIMAL(10,2)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Num. commande</td>\n<td style=\"text-align:left\"><code>VARCHAR(8)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>Inclure</strong></td>\n<td style=\"text-align:left\">Quantité</td>\n<td style=\"text-align:left\"><code>INTEGER</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>Produit</strong></td>\n<td style=\"text-align:left\">Libellé</td>\n<td style=\"text-align:left\"><code>VARCHAR(50)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Prix unitaire</td>\n<td style=\"text-align:left\"><code>DECIMAL(10,2)</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><strong>\"</strong></td>\n<td style=\"text-align:left\">Réf. produit</td>\n<td style=\"text-align:left\"><code>VARCHAR(8)</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Aménités.</strong></p>\n<ul>\n<li>Au format Markdown, les répétitions de cellules de la <em>première</em> colonne sont remplacées par un guillemet itératif.</li>\n<li>Le tableau est automatiquement trié selon sa première, puis éventuellement deuxième et troisième colonnes.</li>\n<li>Si une seule colonne est demandée, la ligne d'en-tête n'est pas générée et, en Markdown, c'est une liste qui est produite.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [91]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t data_dict:label\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_data_dict_1.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li>Adresse</li>\n<li>Date</li>\n<li>Libellé</li>\n<li>Montant</li>\n<li>Nom</li>\n<li>Num. commande</li>\n<li>Prix unitaire</li>\n<li>Prénom</li>\n<li>Quantité</li>\n<li>Réf. client</li>\n<li>Réf. produit</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveautés de la version 4.0.</strong></p>\n<ul>\n<li>Sélection, ordre et nommage des colonnes, mise en forme Markdown, tri, guillemets itératifs.</li>\n<li>Remplacement par un algorithme dédié du gabarit relationnel utilisé (abusivement) dans les versions antérieures.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"URL-de-partage\">URL de partage<a class=\"anchor-link\" href=\"#URL-de-partage\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez demander à encoder le texte-source de votre MCD dans un lien vers Mocodo online, qui le composera automatiquement dans la zone d'entrée :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [92]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t share\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_url.url\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>https://www.mocodo.net/?mcd=eNptkMEKgkAQhu89xRwLJDQQwtuySgm5mEgX6bDlBgu6xrYLvZLP4Ys1ahZYt_m_Yeb_Z2glhTIBZF17W8N1UFCcSEb3JFtuV2cHWFN_ycb3e5bqrlV_OCm1eDzEjC9SjlA74DKgg4UDnge0qWuuSrGYigCYrTHFW85yhNwgCkkeoUgaZXgfNYxonJDD0nOdDTrF6lpZLXA_--wffFPdlFbipUeLc9J0LRQxy6NdlGG-qTm-4T7Kmf9BXkRV9XMT9t3xF_IJVknDpRY_gV4LRG5Z\n\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Mocodo-pour-la-p%C3%A9dagogie\">Mocodo pour la pédagogie<a class=\"anchor-link\" href=\"#Mocodo-pour-la-p%C3%A9dagogie\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Vue-en-extension\">Vue en extension<a class=\"anchor-link\" href=\"#Vue-en-extension\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Un chiffre ou tiret bas à la fin du nom d'une boîte (entité ou association) est utilisé en interne pour distinguer cette boîte des autres, mais n'est pas affiché dans le diagramme conceptuel. Cela peut servir à produire une vue en extension d'un MCD.</p>\n<p>Voici par exemple le MCD que j'utilise en cours pour introduire la notion d'entité faible (à gauche, vue en compréhension, à droite vue en extension):</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [93]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nŒUVRE1: cote, titre, date de publication\n:::\nŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\n:\n  \nDF, 1N ŒUVRE1, _11 EXEMPLAIRE1\n::\nDF, XX ŒUVRE2, XX EXEMPLAIRE2\nDF, XX ŒUVRE2, XX EXEMPLAIRE3\nDF, XX ŒUVRE2, XX EXEMPLAIRE4\n\nEXEMPLAIRE1: numéro d'exemplaire, état, date d'achat\n::\nEXEMPLAIRE2: 1, bon état, 12/6/1975\nEXEMPLAIRE3: 2, bon état, 1/8/1977\nEXEMPLAIRE4: 3, reliure rongée, 3/4/2005\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3MTUiIGhlaWdodD0iMjk0IiB2aWV3Qm94PSIwIDAgNzE1IDI5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3MTUiIGhlaWdodD0iMjk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9Ijg0IiB5MT0iNTYiIHgyPSI4NCIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI4NCIgeTE9IjIzOCIgeDI9Ijg0IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iODQiIGN5PSIxNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iNzEiIHk9IjE1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iODkiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iODkiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9Ijg5IiB5MT0iMTg1IiB4Mj0iMTA3IiB5Mj0iMTg1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIERGMSAtLT4KPGc+Cgk8bGluZSB4MT0iNDc2IiB5MT0iNTYiIHgyPSIzMTMiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzEzIiB5MT0iMjM4IiB4Mj0iMzEzIiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMzEzIiBjeT0iMTQ3IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjMwMCIgeT0iMTUxLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzOTIuNDciIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+ICAgICA8L3RleHQ+Cgk8dGV4dCB4PSIzMTgiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+ICAgICA8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYyIC0tPgo8Zz4KCTxsaW5lIHgxPSI0NzYiIHkxPSI1NiIgeDI9IjQ3NiIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0NzYiIHkxPSIyMzgiIHgyPSI0NzYiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI0NzYiIGN5PSIxNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iNDYzIiB5PSIxNTEuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQ4MSIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjQ4MSIgeT0iMTgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjMgLS0+CjxnPgoJPGxpbmUgeDE9IjQ3NiIgeTE9IjU2IiB4Mj0iNjM5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjYzOSIgeTE9IjIzOCIgeDI9IjYzOSIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjYzOSIgY3k9IjE0NyIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI2MjYiIHk9IjE1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNTQxLjUzIiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0PgoJPHRleHQgeD0iNjQ0IiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBPRVVWUkUxIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE2IiB5PSI5IiB3aWR0aD0iMTM2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE2IiB5PSIzOSIgd2lkdGg9IjEzNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNiIgeT0iOSIgd2lkdGg9IjEzNiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNiIgeTE9IjM5IiB4Mj0iMTUyIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjUwIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsWSVVZSRTwvdGV4dD4KCTx0ZXh0IHg9IjI0IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb3RlPC90ZXh0PgoJPGxpbmUgeDE9IjI0IiB5MT0iNTkiIHgyPSI1MyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjQiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnRpdHJlPC90ZXh0PgoJPHRleHQgeD0iMjQiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIGRlIHB1YmxpY2F0aW9uPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBPRVVWUkUyIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM0OSIgeT0iOSIgd2lkdGg9IjI1NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNDkiIHk9IjM5IiB3aWR0aD0iMjU0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM0OSIgeT0iOSIgd2lkdGg9IjI1NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzNDkiIHkxPSIzOSIgeDI9IjYwMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0NDIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+xZJVVlJFPC90ZXh0PgoJPHRleHQgeD0iMzU3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij42MTIuTkFULjM0PC90ZXh0PgoJPGxpbmUgeDE9IjM1NyIgeTE9IjU5IiB4Mj0iNDM0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzNTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkrigJlhcHByZW5kcyDDoCBsaXJlIMOgIG1lcyBzb3VyaXMgYmxhbmNoZXM8L3RleHQ+Cgk8dGV4dCB4PSIzNTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tYWkgMTk3NTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVhFTVBMQUlSRTEgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTUwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIyMSIgd2lkdGg9IjE1MCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxOTEiIHdpZHRoPSIxNTAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjIyMSIgeDI9IjE1OSIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjUiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVYRU1QTEFJUkU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bcOpcm8gZOKAmWV4ZW1wbGFpcmU8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIyNDEiIHgyPSIxNTAiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIxNyIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOpdGF0PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZSBk4oCZYWNoYXQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVYRU1QTEFJUkUyIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI0NiIgeT0iMTkxIiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0NiIgeT0iMjIxIiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0NiIgeT0iMTkxIiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI0NiIgeTE9IjIyMSIgeDI9IjM4MCIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjU0IiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FWEVNUExBSVJFPC90ZXh0PgoJPHRleHQgeD0iMjU0IiB5PSIyMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+MTwvdGV4dD4KCTxsaW5lIHgxPSIyNTQiIHkxPSIyNDEiIHgyPSIyNjMiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNTQiIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ib24gw6l0YXQ8L3RleHQ+Cgk8dGV4dCB4PSIyNTQiIHk9IjI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+MTIvNi8xOTc1PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFWEVNUExBSVJFMyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0MDkiIHk9IjE5MSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MDkiIHk9IjIyMSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MDkiIHk9IjE5MSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0MDkiIHkxPSIyMjEiIHgyPSI1NDMiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQxNyIgeT0iMjEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RVhFTVBMQUlSRTwvdGV4dD4KCTx0ZXh0IHg9IjQxNyIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPjI8L3RleHQ+Cgk8bGluZSB4MT0iNDE3IiB5MT0iMjQxIiB4Mj0iNDI2IiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDE3IiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Ym9uIMOpdGF0PC90ZXh0PgoJPHRleHQgeD0iNDE3IiB5PSIyNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPjEvOC8xOTc3PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFWEVNUExBSVJFNCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1NzIiIHk9IjE5MSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NzIiIHk9IjIyMSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NzIiIHk9IjE5MSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1NzIiIHkxPSIyMjEiIHgyPSI3MDYiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU4MCIgeT0iMjEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RVhFTVBMQUlSRTwvdGV4dD4KCTx0ZXh0IHg9IjU4MCIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPjM8L3RleHQ+Cgk8bGluZSB4MT0iNTgwIiB5MT0iMjQxIiB4Mj0iNTg5IiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTgwIiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmVsaXVyZSByb25nw6llPC90ZXh0PgoJPHRleHQgeD0iNTgwIiB5PSIyNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPjMvNC8yMDA1PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo n'interdit pas la conversion en relationnel d'un tel MCD, mais celle-ci n'a aucun sens.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Si l'on veut garder les cardinalités sans les afficher, on peut les préfixer d'un <code>-</code>. Le résultat de la conversion en relationnel peut alors être interprété comme l'ensemble des lignes des différentes tables.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [94]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\n  \nDF, -1N ŒUVRE, -_11 EXEMPLAIRE1\nDF, -1N ŒUVRE, -_11 EXEMPLAIRE2\nDF, -1N ŒUVRE, -_11 EXEMPLAIRE3\n\nEXEMPLAIRE1: 1, bon état, 12/6/1975\nEXEMPLAIRE2: 2, bon état, 1/8/1977\nEXEMPLAIRE3: 3, reliure rongée, 3/4/2005\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NzgiIGhlaWdodD0iMjk0IiB2aWV3Qm94PSIwIDAgNDc4IDI5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NzgiIGhlaWdodD0iMjk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjIzOSIgeTE9IjU2IiB4Mj0iNzYiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzYiIHkxPSIyMzgiIHgyPSI3NiIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9Ijc2IiBjeT0iMTQ3IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjYzIiB5PSIxNTEuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE1NS40NyIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjgxIiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSI4MSIgeTE9IjE4NSIgeDI9Ijk5IiB5Mj0iMTg1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIERGMSAtLT4KPGc+Cgk8bGluZSB4MT0iMjM5IiB5MT0iNTYiIHgyPSIyMzkiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjM5IiB5MT0iMjM4IiB4Mj0iMjM5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjM5IiBjeT0iMTQ3IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjIyNiIgeT0iMTUxLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNDQiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+ICAgICA8L3RleHQ+Cgk8dGV4dCB4PSIyNDQiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjI0NCIgeTE9IjE4NSIgeDI9IjI2MiIgeTI9IjE4NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjIgLS0+CjxnPgoJPGxpbmUgeDE9IjIzOSIgeTE9IjU2IiB4Mj0iNDAyIiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQwMiIgeTE9IjIzOCIgeDI9IjQwMiIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjQwMiIgY3k9IjE0NyIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIzODkiIHk9IjE1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzA0LjUzIiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0PgoJPHRleHQgeD0iNDA3IiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSI0MDciIHkxPSIxODUiIHgyPSI0MjUiIHkyPSIxODUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IE9FVVZSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMTIiIHk9IjkiIHdpZHRoPSIyNTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTEyIiB5PSIzOSIgd2lkdGg9IjI1NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMTIiIHk9IjkiIHdpZHRoPSIyNTQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTEyIiB5MT0iMzkiIHgyPSIzNjYiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjA1IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsWSVVZSRTwvdGV4dD4KCTx0ZXh0IHg9IjEyMCIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+NjEyLk5BVC4zNDwvdGV4dD4KCTxsaW5lIHgxPSIxMjAiIHkxPSI1OSIgeDI9IjE5NyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTIwIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5K4oCZYXBwcmVuZHMgw6AgbGlyZSDDoCBtZXMgc291cmlzIGJsYW5jaGVzPC90ZXh0PgoJPHRleHQgeD0iMTIwIiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bWFpIDE5NzU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVYRU1QTEFJUkUxIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjE5MSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMjEiIHdpZHRoPSIxMzQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIyMjEiIHgyPSIxNDMiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FWEVNUExBSVJFPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4xPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMjQxIiB4Mj0iMjYiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIxNyIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmJvbiDDqXRhdDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIyNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPjEyLzYvMTk3NTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVhFTVBMQUlSRTIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTcyIiB5PSIxOTEiIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTcyIiB5PSIyMjEiIHdpZHRoPSIxMzQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTcyIiB5PSIxOTEiIHdpZHRoPSIxMzQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTcyIiB5MT0iMjIxIiB4Mj0iMzA2IiB5Mj0iMjIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODAiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVYRU1QTEFJUkU8L3RleHQ+Cgk8dGV4dCB4PSIxODAiIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4yPC90ZXh0PgoJPGxpbmUgeDE9IjE4MCIgeTE9IjI0MSIgeDI9IjE4OSIgeTI9IjI0MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1kYXNoYXJyYXk9IjQiLz4KCTx0ZXh0IHg9IjE4MCIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmJvbiDDqXRhdDwvdGV4dD4KCTx0ZXh0IHg9IjE4MCIgeT0iMjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4xLzgvMTk3NzwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVhFTVBMQUlSRTMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzM1IiB5PSIxOTEiIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzM1IiB5PSIyMjEiIHdpZHRoPSIxMzQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzM1IiB5PSIxOTEiIHdpZHRoPSIxMzQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzM1IiB5MT0iMjIxIiB4Mj0iNDY5IiB5Mj0iMjIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNDMiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVYRU1QTEFJUkU8L3RleHQ+Cgk8dGV4dCB4PSIzNDMiIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4zPC90ZXh0PgoJPGxpbmUgeDE9IjM0MyIgeTE9IjI0MSIgeDI9IjM1MiIgeTI9IjI0MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1kYXNoYXJyYXk9IjQiLz4KCTx0ZXh0IHg9IjM0MyIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnJlbGl1cmUgcm9uZ8OpZTwvdGV4dD4KCTx0ZXh0IHg9IjM0MyIgeT0iMjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4zLzQvMjAwNTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>EXEMPLAIRE</strong> (<u><em>#612.NAT.34</em></u>, <u>1</u>, bon état, 12/6/1975)</li>\n<li><strong>EXEMPLAIRE</strong> (<u><em>#612.NAT.34</em></u>, <u>2</u>, bon état, 1/8/1977)</li>\n<li><strong>EXEMPLAIRE</strong> (<u><em>#612.NAT.34</em></u>, <u>3</u>, reliure rongée, 3/4/2005)</li>\n<li><strong>ŒUVRE</strong> (<u>612.NAT.34</u>, J'apprends à lire à mes souris blanches, mai 1975)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"MCD-interactif\">MCD interactif<a class=\"anchor-link\" href=\"#MCD-interactif\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Afficher-des-explications-au-survol\">Afficher des explications au survol<a class=\"anchor-link\" href=\"#Afficher-des-explications-au-survol\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut être incluse dans le texte-source en annotant les pattes correspondantes. Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [95]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N [Une commande inclut au moins un produit.] Commande, 0N [Un produit peut être commandé un nombre quelconque de fois.] Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N [Un client peut passer zéro (prospect) ou plusieurs commandes.] Client, 11 [Une commande est passée par un et un seul client.] Commande\nClient: réf. client, nom, adresse\nParrainer, 01 [Un client peut avoir été parrainé ou non.] Client, 0N [Un client peut parrainer d'autres clients.] Client : date parrainage\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2OTEiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgNjkxIDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2OTEiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBJTkNMVVJFIC0tPgo8ZyBjbGFzcz0icGFnZV8wX2VhY2JkZmUzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMzA3IiB5MT0iNTYiIHgyPSIxNzUiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NiIgeTE9IjU2IiB4Mj0iMTc1IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjA0IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtODYgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMTggNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNDYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIODYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTMyIiB5PSIyNyIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTMyIiB5MT0iNTUiIHgyPSIyMTgiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEzOSIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJCTx0ZXh0IHg9IjEzOSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVhbnRpdMOpPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjIzIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfZWFjYmRmZTMoZXZ0LCdVbmUgY29tbWFuZGUgaW5jbHV0IGF1IG1vaW5zIHVuIHByb2R1aXQuJykiIG9ubW91c2VvdXQ9ImhpZGVfZWFjYmRmZTMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjEwOCIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93X2VhY2JkZmUzKGV2dCwnVW4gcHJvZHVpdCBwZXV0IMOqdHJlIGNvbW1hbmTDqSB1biBub21icmUgcXVlbGNvbnF1ZSBkZSBmb2lzLicpIiBvbm1vdXNlb3V0PSJoaWRlX2VhY2JkZmUzKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8ZyBjbGFzcz0icGFnZV8wX2VhY2JkZmUzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNTA0IiB5MT0iNTYiIHgyPSI0MTYiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDciIHkxPSI1NiIgeDI9IjQxNiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iNDE2IiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iNDAzIiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDQxIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfZWFjYmRmZTMoZXZ0LCdVbiBjbGllbnQgcGV1dCBwYXNzZXIgesOpcm8gKHByb3NwZWN0KSBvdSBwbHVzaWV1cnMgY29tbWFuZGVzLicpIiBvbm1vdXNlb3V0PSJoaWRlX2VhY2JkZmUzKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSIzNzIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd19lYWNiZGZlMyhldnQsJ1VuZSBjb21tYW5kZSBlc3QgcGFzc8OpZSBwYXIgdW4gZXQgdW4gc2V1bCBjbGllbnQuJykiIG9ubW91c2VvdXQ9ImhpZGVfZWFjYmRmZTMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVJSQUlORVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZWFjYmRmZTMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik01MDQgNTYgQzUzMy42NyAyNCA1NzQuNjcgMjQgNjI3IDU2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTUwNCA1NiBDNTM0LjMzIDg4IDU3NS4zMyA4OCA2MjcgNTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNjY4IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTEwIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNjgyIDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINTg2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDExMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI1NzIiIHk9IjI3IiB3aWR0aD0iMTEwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNTcyIiB5MT0iNTUiIHgyPSI2ODIiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjU4MCIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QYXJyYWluZXI8L3RleHQ+CgkJPHRleHQgeD0iNTc5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIHBhcnJhaW5hZ2U8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI1NDgiIHk9IjQ5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd19lYWNiZGZlMyhldnQsJ1VuIGNsaWVudCBwZXV0IGF2b2lyIMOpdMOpIHBhcnJhaW7DqSBvdSBub24uJykiIG9ubW91c2VvdXQ9ImhpZGVfZWFjYmRmZTMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsMTwvdGV4dD4KCTx0ZXh0IHg9IjU0OCIgeT0iNzEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93X2VhY2JkZmUzKGV2dCwnVW4gY2xpZW50IHBldXQgcGFycmFpbmVyIGTigJlhdXRyZXMgY2xpZW50cy4nKSIgb25tb3VzZW91dD0iaGlkZV9lYWNiZGZlMyhldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8ZyBjbGFzcz0icGFnZV8wX2VhY2JkZmUzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI5NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTAzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIwIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2R1aXQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iODkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZWFjYmRmZTMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjI0NyIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNDciIHk9IjM5IiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0NyIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNDciIHkxPSIzOSIgeDI9IjM2NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjAiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIyNTUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMjU1IiB5MT0iNTkiIHgyPSIzNTkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI1NSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjI1NSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm1vbnRhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lYWNiZGZlMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNDY1IiB5PSI5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDY1IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ2NSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ2NSIgeTE9IjM5IiB4Mj0iNTQzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3NCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSI0NzMiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSI0NzMiIHkxPSI1OSIgeDI9IjUzMiIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDczIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub208L3RleHQ+Cgk8dGV4dCB4PSI0NzMiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hZHJlc3NlPC90ZXh0Pgo8L2c+Cgo8IS0tIE5vdGVzIC0tPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc2hvd19lYWNiZGZlMyhldnQsIHRleHQpIHsKCQl2YXIgcG9zID0gKGV2dC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ5IikgPCA2NykgPyAiYm90dG9tIiA6ICJ0b3AiOwoJCXZhciBub3RlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocG9zICsgIl9ub3RlX2VhY2JkZmUzIik7CgkJbm90ZS50ZXh0Q29udGVudCA9IHRleHQ7CgkJbm90ZS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJ2aXNpYmxlIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocG9zICsgIl9vdmVybGF5X2VhY2JkZmUzIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJfQoJZnVuY3Rpb24gaGlkZV9lYWNiZGZlMyhldnQpIHsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidG9wX25vdGVfZWFjYmRmZTMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidG9wX292ZXJsYXlfZWFjYmRmZTMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm90dG9tX25vdGVfZWFjYmRmZTMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm90dG9tX292ZXJsYXlfZWFjYmRmZTMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCX0KXV0+Cjwvc2NyaXB0Pgo8cmVjdCBpZD0idG9wX292ZXJsYXlfZWFjYmRmZTMiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjQwIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuNyIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjx0ZXh0IGlkPSJ0b3Bfbm90ZV9lYWNiZGZlMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzQ1IiB5PSIyNCIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+CjxyZWN0IGlkPSJib3R0b21fb3ZlcmxheV9lYWNiZGZlMyIgeD0iMCIgeT0iNzIiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjQwIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuNyIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjx0ZXh0IGlkPSJib3R0b21fbm90ZV9lYWNiZGZlMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzQ1IiB5PSI5NiIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.3.</strong> Avec l'option <code>-t prompt:cards</code>, Mocodo compose un <em>prompt</em> à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec de telles descriptions. Ce <em>prompt</em> est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les explications générées par <a href=\"https://chat.deepseek.com\">DeepSeek</a> pour le MCD de la page d'accueil de Mocodo online :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [96]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [Un employé peut diriger zéro ou un projet.] EMPLOYÉ, 01 [Un projet est dirigé par au plus un employé.] PROJET\nREQUÉRIR, 1N [Un projet requiert au moins une pièce.] PROJET, 0N [Une pièce peut être requise par plusieurs projets.] PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [Une pièce peut être composée de plusieurs autres pièces.] PIÈCE, 0N [Une pièce peut entrer dans la composition de plusieurs autres pièces.] PIÈCE: quantité\n\nDF, _11 [Un ayant-droit est associé à un et un seul employé.] AYANT-DROIT, 0N [Un employé peut avoir plusieurs ayants-droit.] EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N [Un projet est fourni par au moins une société.] PROJET, 1N [Une pièce est fournie par au moins une société.] PIÈCE, 1N [Une société fournit au moins une pièce pour un projet.] SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 [Un employé appartient à un et un seul département.] EMPLOYÉ, 1N [Un département emploie au moins un employé.] DÉPARTEMENT\nTRAVAILLER, 0N [Un employé peut travailler sur plusieurs projets.] EMPLOYÉ, 1N [Un projet implique au moins un employé.] PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N&lt; [Une société peut en contrôler une autre.] SOCIÉTÉ, 01 [Une société est contrôlée par au plus une autre société.] SOCIÉTÉ\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NjQiIGhlaWdodD0iMjc2IiB2aWV3Qm94PSIwIDAgNzY0IDI3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3NjQiIGhlaWdodD0iMjc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBESVJJR0VSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMjUwIiB5MT0iMTM4IiB4Mj0iMjUwIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNDAxIiB5MT0iMTM4IiB4Mj0iMjUwIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjgyIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtOTIgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yOTYgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyMTggYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIOTIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjA0IiB5PSIxOCIgd2lkdGg9IjkyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMjA0IiB5MT0iNDYiIHgyPSIyOTYiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIxMiIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ESVJJR0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjU1IiB5PSI5MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbiBlbXBsb3nDqSBwZXV0IGRpcmlnZXIgesOpcm8gb3UgdW4gcHJvamV0LicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSIzMzMiIHk9IjEyMi4yMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbiBwcm9qZXQgZXN0IGRpcmlnw6kgcGFyIGF1IHBsdXMgdW4gZW1wbG95w6kuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVFVRVJJUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF83YWRiYmU4YyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjQwMSIgeTE9IjEzOCIgeDI9IjQwMSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU0NSIgeTE9IjQ3IiB4Mj0iNDAxIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDQzIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtMTEyIFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDU3IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzU5IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDExMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNDUiIHk9IjE4IiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzQ1IiB5MT0iNDYiIHgyPSI0NTciIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1MyIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SRVFVw4lSSVI8L3RleHQ+CgkJPHRleHQgeD0iMzUyIiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdMOpIHJlcXVpc2U8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0MDYiIHk9IjkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuIHByb2pldCByZXF1aWVydCBhdSBtb2lucyB1bmUgcGnDqGNlLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4xLE48L3RleHQ+Cgk8dGV4dCB4PSI0NzYiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuZSBwacOoY2UgcGV1dCDDqnRyZSByZXF1aXNlIHBhciBwbHVzaWV1cnMgcHJvamV0cy4nKSIgb25tb3VzZW91dD0iaGlkZV83YWRiYmU4YyhldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTVBPU0VSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8cGF0aCBkPSJNNTQ1IDQ3IEM1NzYgMTUgNjI0LjMzIDE1IDY5MCA0NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik01NDUgNDcgQzU3NiA3OSA2MjQuMzMgNzkgNjkwIDQ3IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTczNiAxOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFY0NiBoLTEyMCBWMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTc1MCA0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDY0NCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjQ2IEgxMjAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNjMwIiB5PSIxOCIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjYzMCIgeTE9IjQ2IiB4Mj0iNzUwIiB5Mj0iNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI2MzciIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q09NUE9TRVI8L3RleHQ+CgkJPHRleHQgeD0iNjM3IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI1OTUiIHk9IjQwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuZSBwacOoY2UgcGV1dCDDqnRyZSBjb21wb3PDqWUgZGUgcGx1c2lldXJzIGF1dHJlcyBwacOoY2VzLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI1OTUiIHk9IjYyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuZSBwacOoY2UgcGV1dCBlbnRyZXIgZGFucyBsYSBjb21wb3NpdGlvbiBkZSBwbHVzaWV1cnMgYXV0cmVzIHBpw6hjZXMuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnIGNsYXNzPSJwYWdlXzBfN2FkYmJlOGMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSI4NiIgeTE9IjQ3IiB4Mj0iODYiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjUwIiB5MT0iMTM4IiB4Mj0iODYiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI4NiIgY3k9IjEzOCIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI3MyIgeT0iMTQyLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI5MSIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuIGF5YW50LWRyb2l0IGVzdCBhc3NvY2nDqSDDoCB1biBldCB1biBzZXVsIGVtcGxvecOpLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iOTEiIHkxPSIxMDMiIHgyPSIxMDkiIHkyPSIxMDMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzQiIHk9IjE1NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbiBlbXBsb3nDqSBwZXV0IGF2b2lyIHBsdXNpZXVycyBheWFudHMtZHJvaXQuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBGT1VSTklSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNDAxIiB5MT0iMTM4IiB4Mj0iNTQ1IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU0NSIgeTE9IjQ3IiB4Mj0iNTQ1IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU0NSIgeTE9IjIyOSIgeDI9IjU0NSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik01ODEgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTEwMCBWMTIzIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01OTUgMTM3IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINTA5IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTM3IEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDk1IiB5PSIxMDkiIHdpZHRoPSIxMDAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI0OTUiIHkxPSIxMzciIHgyPSI1OTUiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI1MDMiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZPVVJOSVI8L3RleHQ+CgkJPHRleHQgeD0iNTAyIiB5PSIxNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXTDqSBmb3VybmllPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDUxIiB5PSIxNTQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzdhZGJiZThjKGV2dCwnVW4gcHJvamV0IGVzdCBmb3VybmkgcGFyIGF1IG1vaW5zIHVuZSBzb2Npw6l0w6kuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjU1MCIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuZSBwacOoY2UgZXN0IGZvdXJuaWUgcGFyIGF1IG1vaW5zIHVuZSBzb2Npw6l0w6kuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjU1MCIgeT0iMTgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuZSBzb2Npw6l0w6kgZm91cm5pdCBhdSBtb2lucyB1bmUgcGnDqGNlIHBvdXIgdW4gcHJvamV0LicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRU1QTE9ZRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfN2FkYmJlOGMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIyNTAiIHkxPSIxMzgiIHgyPSIyNTAiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iODYiIHkxPSIyMjkiIHgyPSIyNTAiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjk0IDIwMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMjggaC0xMTYgVjIxNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzA4IDIyOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIwNiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOCBIMTE2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE5MiIgeT0iMjAwIiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTkyIiB5MT0iMjI4IiB4Mj0iMzA4IiB5Mj0iMjI4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMjAwIiB5PSIyMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FTVBMT1lFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIyNyIgeT0iMTkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuIGVtcGxvecOpIGFwcGFydGllbnQgw6AgdW4gZXQgdW4gc2V1bCBkw6lwYXJ0ZW1lbnQuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjE2OCIgeT0iMjQ1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd183YWRiYmU4YyhldnQsJ1VuIGTDqXBhcnRlbWVudCBlbXBsb2llIGF1IG1vaW5zIHVuIGVtcGxvecOpLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVFJBVkFJTExFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF83YWRiYmU4YyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjI1MCIgeTE9IjEzOCIgeDI9IjQwMSIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI0MDEiIHkxPSIxMzgiIHgyPSI0MDEiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDUxIDIwMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMjggaC0xMjggVjIxNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDY1IDIyOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM1MSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOCBIMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMzNyIgeT0iMjAwIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzM3IiB5MT0iMjI4IiB4Mj0iNDY1IiB5Mj0iMjI4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzQ0IiB5PSIyMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5UUkFWQUlMTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzA3IiB5PSIxNjYuMCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbiBlbXBsb3nDqSBwZXV0IHRyYXZhaWxsZXIgc3VyIHBsdXNpZXVycyBwcm9qZXRzLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI0MDYiIHk9IjE5MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbiBwcm9qZXQgaW1wbGlxdWUgYXUgbW9pbnMgdW4gZW1wbG95w6kuJykiIG9ubW91c2VvdXQ9ImhpZGVfN2FkYmJlOGMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDT05UUk9MRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfN2FkYmJlOGMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik01NDUgMjI5IEM1ODQgMTk3IDYzMi4zMyAxOTcgNjkwIDIyOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwb2x5Z29uIHBvaW50cz0iNjI0Ljk5IDIwNS45MiA2MTIuMzQgMjEwLjM5IDYxNy4wNSAyMDQuOTMgNjEzLjgzIDE5OC40OCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8cGF0aCBkPSJNNTQ1IDIyOSBDNTgzLjMzIDI2MSA2MzEuNjcgMjYxIDY5MCAyMjkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNzQxIDIwMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMjggaC0xMzAgVjIxNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNzU1IDIyOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDYzOSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOCBIMTMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjYyNSIgeT0iMjAwIiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNjI1IiB5MT0iMjI4IiB4Mj0iNzU1IiB5Mj0iMjI4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNjMyIiB5PSIyMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT05UUsOUTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNjAxIiB5PSIyMjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzdhZGJiZThjKGV2dCwnVW5lIHNvY2nDqXTDqSBwZXV0IGVuIGNvbnRyw7RsZXIgdW5lIGF1dHJlLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI2MDEiIHk9IjI0NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfN2FkYmJlOGMoZXZ0LCdVbmUgc29jacOpdMOpIGVzdCBjb250csO0bMOpZSBwYXIgYXUgcGx1cyB1bmUgYXV0cmUgc29jacOpdMOpLicpIiBvbm1vdXNlb3V0PSJoaWRlXzdhZGJiZThjKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFZQU5UX0RST0lUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIxNiIgeT0iOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNiIgeT0iMzkiIHdpZHRoPSIxNDAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTYiIHk9IjkiIHdpZHRoPSIxNDAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTYiIHkxPSIzOSIgeDI9IjE1NiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BWUFOVC1EUk9JVDwvdGV4dD4KCTx0ZXh0IHg9IjI0IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gYXlhbnQtZHJvaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMjQiIHkxPSI1OSIgeDI9IjEyNSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMjQiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpZW48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBJRUNFIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSI1MDAiIHk9IjkiIHdpZHRoPSI5MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MDAiIHk9IjM5IiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTAwIiB5PSI5IiB3aWR0aD0iOTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTAwIiB5MT0iMzkiIHgyPSI1OTAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTE3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBJw4hDRTwvdGV4dD4KCTx0ZXh0IHg9IjUwOCIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gcGnDqGNlPC90ZXh0PgoJPGxpbmUgeDE9IjUwOCIgeTE9IjU5IiB4Mj0iNTY2IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1MDgiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpYmVsbMOpIHBpw6hjZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRU1QTE9ZRSAtLT4KPGcgY2xhc3M9InBhZ2VfMF83YWRiYmU4YyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iMTk4IiB5PSIxMDAiIHdpZHRoPSIxMDQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTk4IiB5PSIxMzAiIHdpZHRoPSIxMDQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTk4IiB5PSIxMDAiIHdpZHRoPSIxMDQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTk4IiB5MT0iMTMwIiB4Mj0iMzAyIiB5Mj0iMTMwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMDYiIHk9IjEyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVNUExPWcOJPC90ZXh0PgoJPHRleHQgeD0iMjA2IiB5PSIxNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bWF0cmljdWxlPC90ZXh0PgoJPGxpbmUgeDE9IjIwNiIgeTE9IjE1MCIgeDI9IjI2NSIgeTI9IjE1MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIwNiIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBlbXBsb3nDqTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIzNTYiIHk9IjEwMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTMwIiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSIxMDAiIHdpZHRoPSI5MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzNTYiIHkxPSIxMzAiIHgyPSI0NDYiIHkyPSIxMzAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM2NSIgeT0iMTIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPSkVUPC90ZXh0PgoJPHRleHQgeD0iMzY0IiB5PSIxNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBwcm9qZXQ8L3RleHQ+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTUwIiB4Mj0iNDM4IiB5Mj0iMTUwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSIxNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHByb2pldDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREVQQVJURU1FTlQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfN2FkYmJlOGMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjE5MSIgd2lkdGg9IjE1NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMjEiIHdpZHRoPSIxNTQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTU0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIyMjEiIHgyPSIxNjMiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ew4lQQVJURU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gZMOpcGFydGVtZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMjQxIiB4Mj0iMTMyIiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTT0NJRVRFIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzdhZGJiZThjIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSI0OTQiIHk9IjE5MSIgd2lkdGg9IjEwMiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0OTQiIHk9IjIyMSIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0OTQiIHk9IjE5MSIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTQiIHkxPSIyMjEiIHgyPSI1OTYiIHkyPSIyMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjUwNSIgeT0iMjEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U09DScOJVMOJPC90ZXh0PgoJPHRleHQgeD0iNTAyIiB5PSIyMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBzb2Npw6l0w6k8L3RleHQ+Cgk8bGluZSB4MT0iNTAyIiB5MT0iMjQxIiB4Mj0iNTgyIiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTAyIiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmFpc29uIHNvY2lhbGU8L3RleHQ+CjwvZz4KCjwhLS0gTm90ZXMgLS0+CjxzY3JpcHQgdHlwZT0idGV4dC9lY21hc2NyaXB0Ij4KPCFbQ0RBVEFbCglmdW5jdGlvbiBzaG93XzdhZGJiZThjKGV2dCwgdGV4dCkgewoJCXZhciBwb3MgPSAoZXZ0LnRhcmdldC5nZXRBdHRyaWJ1dGUoInkiKSA8IDIzMSkgPyAiYm90dG9tIiA6ICJ0b3AiOwoJCXZhciBub3RlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocG9zICsgIl9ub3RlXzdhZGJiZThjIik7CgkJbm90ZS50ZXh0Q29udGVudCA9IHRleHQ7CgkJbm90ZS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJ2aXNpYmxlIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocG9zICsgIl9vdmVybGF5XzdhZGJiZThjIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJfQoJZnVuY3Rpb24gaGlkZV83YWRiYmU4YyhldnQpIHsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidG9wX25vdGVfN2FkYmJlOGMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidG9wX292ZXJsYXlfN2FkYmJlOGMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm90dG9tX25vdGVfN2FkYmJlOGMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm90dG9tX292ZXJsYXlfN2FkYmJlOGMiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJoaWRkZW4iKTsKCX0KXV0+Cjwvc2NyaXB0Pgo8cmVjdCBpZD0idG9wX292ZXJsYXlfN2FkYmJlOGMiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjQwIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuNyIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjx0ZXh0IGlkPSJ0b3Bfbm90ZV83YWRiYmU4YyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzgyIiB5PSIyNCIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+CjxyZWN0IGlkPSJib3R0b21fb3ZlcmxheV83YWRiYmU4YyIgeD0iMCIgeT0iMjM2IiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0iYm90dG9tX25vdGVfN2FkYmJlOGMiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM4MiIgeT0iMjYwIiBmaWxsPSIjRkZGRkZGIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjE2IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le résultat est en général plus qu'honorable, mais demande à être relu attentivement pour vérifier l'adhérence au MCD original, corriger d'éventuelles hallucinations ou apporter des précisions. Ci-dessus, en l'occurrence, une société peut en contrôler <em>plusieurs autres</em> (et non <em>une autre</em>).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Différence syntaxique entre rôles et explications.</strong> Remarquez que la syntaxe est la même que pour les rôles, qui sont en plus utilisés lors du passage au relationnel. Comment Mocodo fait-il la différence ? En appliquant les règles suivantes :</p>\n<ul>\n<li>si la note de patte commence par <code>+</code> ou <code>-</code>, ou qu'elle ne contient aucun espace, c'est un rôle.</li>\n<li>sinon, c'est une description de cardinalité.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Explication de contraintes.</strong> Le même principe s'applique aux contraintes (survolez le Ⓘ) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [97]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nProjet: num. projet, nom projet\n:\nFournir, 1N Projet, 1N Pièce, 1N Société: quantité\nSociété: num. société, raison sociale\n\nRequérir, 1N Projet, 0N Pièce: quantité\n:\nPièce: réf. pièce, libellé pièce\n\n(I) [Toute pièce fournie doit avoir été requise.] ..Pièce, -&gt;Requérir, --Fournir, Projet\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOTciIGhlaWdodD0iMTg1IiB2aWV3Qm94PSIwIDAgMzk3IDE4NSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzOTciIGhlaWdodD0iMTg1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IElfQ09OU1RSQUlOVF8jMSAtLT4KPGcgY2xhc3M9InBhZ2VfMF81YTMzOWY5MiBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjIxMiIgeTE9IjEzOCIgeDI9IjEzNS41IiB5Mj0iOTIuNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cgk8cG9seWdvbiBwb2ludHM9IjEwNy43NiAxMDkgMTE1LjAgOTcuNzEgMTE0LjYzIDEwNC45MSAxMjEuMTQgMTA4LjAyIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSI1OSIgeTE9IjEzOCIgeDI9IjEzNS41IiB5Mj0iOTIuNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMTIiIHkxPSI0NyIgeDI9IjEzNS41IiB5Mj0iOTIuNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjEzNS41IiBjeT0iOTIuNSIgcj0iMTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGIiBvbm1vdXNlb3Zlcj0ic2hvd181YTMzOWY5MihldnQsJ1RvdXRlIHBpw6hjZSBmb3VybmllIGRvaXQgYXZvaXIgw6l0w6kgcmVxdWlzZS4nKSIgb25tb3VzZW91dD0iaGlkZV81YTMzOWY5MihldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgoJCTx0ZXh0IHg9IjEzMyIgeT0iOTYuNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgc3R5bGU9InBvaW50ZXItZXZlbnRzOiBub25lOyI+STwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBGT1VSTklSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzVhMzM5ZjkyIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNTkiIHkxPSI0NyIgeDI9IjIxMiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIxMiIgeTE9IjEzOCIgeDI9IjIxMiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMzNyIgeTE9IjQ3IiB4Mj0iMjEyIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQzIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtOTAgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNTcgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxODEgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIOTAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTY3IiB5PSIxOCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTY3IiB5MT0iNDYiIHgyPSIyNTciIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3NSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Gb3VybmlyPC90ZXh0PgoJCTx0ZXh0IHg9IjE3NCIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVhbnRpdMOpPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA5IiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjE3IiB5PSI5MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjYyIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJFUVVFUklSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzVhMzM5ZjkyIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNTkiIHkxPSI0NyIgeDI9IjU5IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIxMiIgeTE9IjEzOCIgeDI9IjU5IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTk1IDEwOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxMzcgaC0xMDAgVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTA5IDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIzIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTM3IEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTA5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjEzNyIgeDI9IjEwOSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3IiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SZXF1w6lyaXI8L3RleHQ+CgkJPHRleHQgeD0iMTYiIHk9IjE1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2NCIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIxNDMiIHk9IjE1NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9KRVQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNWEzMzlmOTIgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjE0IiB5PSI5IiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTQiIHk9IjM5IiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTQiIHk9IjkiIHdpZHRoPSI5MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNCIgeTE9IjM5IiB4Mj0iMTA0IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2pldDwvdGV4dD4KCTx0ZXh0IHg9IjIyIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIHByb2pldDwvdGV4dD4KCTxsaW5lIHgxPSIyMiIgeTE9IjU5IiB4Mj0iOTYiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIyIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gcHJvamV0PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTT0NJRVRFIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzVhMzM5ZjkyIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIyODYiIHk9IjkiIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjg2IiB5PSIzOSIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyODYiIHk9IjkiIHdpZHRoPSIxMDIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjg2IiB5MT0iMzkiIHgyPSIzODgiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzAzIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNvY2nDqXTDqTwvdGV4dD4KCTx0ZXh0IHg9IjI5NCIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBzb2Npw6l0w6k8L3RleHQ+Cgk8bGluZSB4MT0iMjk0IiB5MT0iNTkiIHgyPSIzNzQiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI5NCIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cmFpc29uIHNvY2lhbGU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBJRUNFIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzVhMzM5ZjkyIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIxNjciIHk9IjEwMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE2NyIgeT0iMTMwIiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY3IiB5PSIxMDAiIHdpZHRoPSI5MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNjciIHkxPSIxMzAiIHgyPSIyNTciIHkyPSIxMzAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4OCIgeT0iMTIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGnDqGNlPC90ZXh0PgoJPHRleHQgeD0iMTc1IiB5PSIxNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gcGnDqGNlPC90ZXh0PgoJPGxpbmUgeDE9IjE3NSIgeTE9IjE1MCIgeDI9IjIzMyIgeTI9IjE1MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3NSIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpYmVsbMOpIHBpw6hjZTwvdGV4dD4KPC9nPgoKPCEtLSBOb3RlcyAtLT4KPHNjcmlwdCB0eXBlPSJ0ZXh0L2VjbWFzY3JpcHQiPgo8IVtDREFUQVsKCWZ1bmN0aW9uIHNob3dfNWEzMzlmOTIoZXZ0LCB0ZXh0KSB7CgkJdmFyIHBvcyA9IChldnQudGFyZ2V0LmdldEF0dHJpYnV0ZSgieSIpIDwgMTQwKSA/ICJib3R0b20iIDogInRvcCI7CgkJdmFyIG5vdGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwb3MgKyAiX25vdGVfNWEzMzlmOTIiKTsKCQlub3RlLnRleHRDb250ZW50ID0gdGV4dDsKCQlub3RlLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCQlkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwb3MgKyAiX292ZXJsYXlfNWEzMzlmOTIiKS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsICJ2aXNpYmxlIik7Cgl9CglmdW5jdGlvbiBoaWRlXzVhMzM5ZjkyKGV2dCkgewoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ0b3Bfbm90ZV81YTMzOWY5MiIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgImhpZGRlbiIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ0b3Bfb3ZlcmxheV81YTMzOWY5MiIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgImhpZGRlbiIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJib3R0b21fbm90ZV81YTMzOWY5MiIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgImhpZGRlbiIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJib3R0b21fb3ZlcmxheV81YTMzOWY5MiIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgImhpZGRlbiIpOwoJfQpdXT4KPC9zY3JpcHQ+CjxyZWN0IGlkPSJ0b3Bfb3ZlcmxheV81YTMzOWY5MiIgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNDAiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC43IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHRleHQgaWQ9InRvcF9ub3RlXzVhMzM5ZjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxOTgiIHk9IjI0IiBmaWxsPSIjRkZGRkZGIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjE2IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHJlY3QgaWQ9ImJvdHRvbV9vdmVybGF5XzVhMzM5ZjkyIiB4PSIwIiB5PSIxNDUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjQwIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuNyIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjx0ZXh0IGlkPSJib3R0b21fbm90ZV81YTMzOWY5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTk4IiB5PSIxNjkiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Limitations.</strong></p>\n<ul>\n<li>Non pris en charge par les éditeurs de SVG comme Inkscape.</li>\n<li>Ne semble pas fonctionner dans une page HTML statique (comme la version HTML de ce document sous GitHub).</li>\n<li>Nécessite de faire confiance à un notebook (Trust notebook) pour s'afficher à la réouverture.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9voiler-un-MCD-par-%C3%A9tapes\">Dévoiler un MCD par étapes<a class=\"anchor-link\" href=\"#D%C3%A9voiler-un-MCD-par-%C3%A9tapes\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 3.</strong> Il est possible de faire apparaître progressivement les différentes « boîtes » constituant un MCD. Pour cela, il suffit d'indenter (décaler vers la droite à l'aide d'espaces ou de tabulations) au moins une ligne. Les éléments correspondants seront alors répartis sur autant de « calques » qu'il y a de niveaux d'indentations.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Voici par exemple un exercice consistant en la description du « réel perçu » d'une entreprise de VPC :</p>\n<blockquote>\n<ol>\n<li>Un produit est connu par une référence, un libellé et un prix unitaire.</li>\n<li>Toute commande inclut un produit ou plusieurs, chacun en une certaine quantité.</li>\n<li>Un client peut passer zéro (<em>client potentiel</em>) ou plusieurs commandes.</li>\n<li>Un client peut entrer dans la base par parrainage d'un autre client.</li>\n</ol>\n</blockquote>\n<p>L'enseignant peut le présenter pas à pas en suivant les étapes de l'énoncé :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [98]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --colors ocean\n      Parrainer, 01 Client, 0N Client : date parrainage\nProduit: Réf. produit, Libellé, Prix unitaire\n  Inclure, 1N Commande, 0N Produit: Quantité\n \n    Client: Réf. client, Nom, Prénom, Adresse\n    DF, 0N Client, 11 Commande\n  Commande: Num. commande, Date, Montant\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODUiIGhlaWdodD0iMjc4IiB2aWV3Qm94PSIwIDAgMzg1IDI3OCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODUiIGhlaWdodD0iMjM4IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVJSQUlORVIgLS0+CjxnIGNsYXNzPSJwYWdlXzNfMDc0M2QyOTggZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJoaWRkZW4iPgoJPHBhdGggZD0iTTY0IDE3NCBDMjYuNjcgMTI0IDI2LjY3IDg0LjY3IDY0IDU2IiBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTY0IDE3NCBDMTAyLjY3IDEyNCAxMDIuNjcgODQuNjcgNjQgNTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTA1IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTEwIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTE5IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjMgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTEwIiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjkiIHk9IjI3IiB3aWR0aD0iMTEwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjU1IiB4Mj0iMTE5IiB5Mj0iNTUiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNyIgeT0iNDguMyIgZmlsbD0iIzI3MzYwYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QYXJyYWluZXI8L3RleHQ+CgkJPHRleHQgeD0iMTYiIHk9IjczLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGUgcGFycmFpbmFnZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQyIiB5PSIxMTEiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsMTwvdGV4dD4KCTx0ZXh0IHg9IjY4IiB5PSIxMTEiIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBJTkNMVVJFIC0tPgo8ZyBjbGFzcz0icGFnZV8xXzA3NDNkMjk4IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0iaGlkZGVuIj4KCTxsaW5lIHgxPSIzMTQiIHkxPSIxNzQiIHgyPSIzMTQiIHkyPSI1NiIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxOTUiIHkxPSI1NiIgeDI9IjMxNCIgeTI9IjU2IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM0MyAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTg2IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2IyYmJhNCIgc3Ryb2tlPSIjYjJiYmE0IiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzU3IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjg1IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDg2IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI3MSIgeT0iMjciIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI3MSIgeTE9IjU1IiB4Mj0iMzU3IiB5Mj0iNTUiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyNzgiIHk9IjQ4LjMiIGZpbGw9IiMyNzM2MGMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIyNzgiIHk9IjczLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMxOSIgeT0iMTE5IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDciIHk9IjcyIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8ZyBjbGFzcz0icGFnZV8yXzA3NDNkMjk4IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0iaGlkZGVuIj4KCTxsaW5lIHgxPSI2NCIgeTE9IjE3NCIgeDI9IjE5NSIgeTI9IjE3NCIgc3Ryb2tlPSIjNzI2ZjgzIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMTQiIHkxPSIxNzQiIHgyPSIxOTUiIHkyPSIxNzQiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIxOTUiIGN5PSIxNzQiIHI9IjIwIiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjYjJiYmE0Ii8+CgkJPHRleHQgeD0iMTgyIiB5PSIxNzguOCIgZmlsbD0iIzI3MzYwYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEwOCIgeT0iMTkwIiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMjkiIHk9IjE5MCIgZmlsbD0iIzcyNmY4MyIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzA3NDNkMjk4IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIxNDgiIHk9IjkiIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNDgiIHk9IjM5IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTQ4IiB5PSI5IiB3aWR0aD0iOTQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTQ4IiB5MT0iMzkiIHgyPSIyNDIiIHkyPSIzOSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTU5IiB5PSIzMC4zIiBmaWxsPSIjMTMxMTE0IiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2R1aXQ8L3RleHQ+Cgk8dGV4dCB4PSIxNTYiIHk9IjU2LjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIHByb2R1aXQ8L3RleHQ+Cgk8bGluZSB4MT0iMTU2IiB5MT0iNTkiIHgyPSIyMzEiIHkyPSI1OSIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE1NiIgeT0iNzMuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TGliZWxsw6k8L3RleHQ+Cgk8dGV4dCB4PSIxNTYiIHk9IjkwIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnIGNsYXNzPSJwYWdlXzJfMDc0M2QyOTggZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJoaWRkZW4iPgoJPGc+CgkJPHJlY3QgeD0iMjUiIHk9IjExOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI1IiB5PSIxNDkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNSIgeT0iMTE5IiB3aWR0aD0iNzgiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI1IiB5MT0iMTQ5IiB4Mj0iMTAzIiB5Mj0iMTQ5IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNCIgeT0iMTQwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMzMiIHk9IjE2Ni4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMzMiIHkxPSIxNjkiIHgyPSI5NSIgeTI9IjE2OSIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMzIiB5PSIxODMuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Tm9tPC90ZXh0PgoJPHRleHQgeD0iMzMiIHk9IjIwMC4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iMzMiIHk9IjIxNyIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnIGNsYXNzPSJwYWdlXzFfMDc0M2QyOTggZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJoaWRkZW4iPgoJPGc+CgkJPHJlY3QgeD0iMjUyIiB5PSIxMjciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjUyIiB5PSIxNTciIHdpZHRoPSIxMjQiIGhlaWdodD0iNjQiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjUyIiB5PSIxMjciIHdpZHRoPSIxMjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjUyIiB5MT0iMTU3IiB4Mj0iMzc2IiB5Mj0iMTU3IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjciIHk9IjE0OC4zIiBmaWxsPSIjMTMxMTE0IiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbW1hbmRlPC90ZXh0PgoJPHRleHQgeD0iMjYwIiB5PSIxNzQuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyNjAiIHkxPSIxNzciIHgyPSIzNjgiIHkyPSIxNzciIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNjAiIHk9IjE5MS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjYwIiB5PSIyMDgiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk1vbnRhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gUGFnZXIgLS0+CjxjaXJjbGUgY3g9IjE2Mi41IiBjeT0iMjU4IiByPSI1IiBmaWxsPSJncmF5IiBpZD0icGFnZXJfZG90XzBfMDc0M2QyOTgiIGNsYXNzPSJwYWdlcl9kb3QiIHN0cm9rZS13aWR0aD0iMCIgb25jbGljaz0ic3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8wNzQzZDI5OChldnQsMCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ii8+CjxjaXJjbGUgY3g9IjE4Mi41IiBjeT0iMjU4IiByPSI1IiBmaWxsPSJsaWdodGdyYXkiIGlkPSJwYWdlcl9kb3RfMV8wNzQzZDI5OCIgY2xhc3M9InBhZ2VyX2RvdCIgc3Ryb2tlLXdpZHRoPSIwIiBvbmNsaWNrPSJzd2l0Y2hfcGFnZV92aXNpYmlsaXR5XzA3NDNkMjk4KGV2dCwxKSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiLz4KPGNpcmNsZSBjeD0iMjAyLjUiIGN5PSIyNTgiIHI9IjUiIGZpbGw9ImxpZ2h0Z3JheSIgaWQ9InBhZ2VyX2RvdF8yXzA3NDNkMjk4IiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMDc0M2QyOTgoZXZ0LDIpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8Y2lyY2xlIGN4PSIyMjIuNSIgY3k9IjI1OCIgcj0iNSIgZmlsbD0ibGlnaHRncmF5IiBpZD0icGFnZXJfZG90XzNfMDc0M2QyOTgiIGNsYXNzPSJwYWdlcl9kb3QiIHN0cm9rZS13aWR0aD0iMCIgb25jbGljaz0ic3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8wNzQzZDI5OChldnQsMykiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ii8+CjxzY3JpcHQgdHlwZT0idGV4dC9lY21hc2NyaXB0Ij4KPCFbQ0RBVEFbCglmdW5jdGlvbiBzd2l0Y2hfcGFnZV92aXNpYmlsaXR5XzA3NDNkMjk4KGV2dCwgcGFnZSkgewoJCWZvciAodmFyIGkgPSAwOyBpIDwgNDsgaSsrKSB7CgkJCWNvbXBvbmVudHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGBwYWdlXyR7aX1fMDc0M2QyOThgKTsKCQkJZm9yICh2YXIgaiA9IDA7IGogPCBjb21wb25lbnRzLmxlbmd0aDsgaisrKSB7CgkJCQljb21wb25lbnRzW2pdLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgaSA8PSBwYWdlID8gInZpc2libGUiIDogImhpZGRlbiIpOwoJCQl9OwoJCQlkb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChgcGFnZXJfZG90XyR7aX1fMDc0M2QyOThgKTsKCQkJZG90LnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgaSA8PSBwYWdlID8gImdyYXkiIDogImxpZ2h0Z3JheSIpOwoJCX0KCX0KXV0+Cjwvc2NyaXB0Pgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Remarques.</strong></p>\n<ul>\n<li><p>Pas de règle sur la taille de l'indentation. Pour Mocodo, autant de niveaux d'indentation distincts, autant de calques.</p>\n</li>\n<li><p>Les différents calques sont codés directement dans le SVG. L'interaction ne nécessite donc aucun logiciel spécifique.</p>\n</li>\n<li><p>Sous Mocodo online, le MCD est toujours présenté entièrement dévoilé. Cela permet de voir directement le résultat d'une modification du texte-source.</p>\n</li>\n<li><p>Pour ajouter facilement de l'interactivité à un MCD existant :</p>\n<ol>\n<li>commencez par indenter au maximum toutes les lignes ;</li>\n<li>effacez l'indentation des lignes du premier calque ;</li>\n<li>décalez votre curseur de $n$ caractères vers la droite ;</li>\n<li>placez-vous tour à tour sur les lignes à intégrer au deuxième calque et effacez les espaces surnuméraires ;</li>\n<li>recommencez à l'étape 3 jusqu'au dernier calque.</li>\n</ol>\n<p>Depuis la version 4.0, l'éditeur de Mocodo online vous permet de créer des curseurs multiples, ce qui simplifie encore ces opérations.</p>\n</li>\n</ul>\n<p><strong>Limitations.</strong></p>\n<ul>\n<li>Pas de granularité plus fine que la ligne (entité ou association avec toutes ses pattes et cardinalités).</li>\n<li>Pas de prise en charge des touches directionnelles. Cela serait sans doute possible, mais difficilement compatible avec la présence de plusieurs MCD interactifs sur une même page (comme dans cette documentation).</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Éviter qu'une interaction sur un SVG ne s'applique à un autre.</strong></p>\n<p>Dans le cas très rare où plusieurs SVG interactifs générés <strong>à partir du même texte-source</strong> coexistent sur une même page web, une interaction opérée sur l'un s'applique également à tous les autres. Par exemple, cliquer sur l'un des ronds gris de l'une des figures ci-dessous agira sur les deux figures :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [99]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nFOO: foo\n  BAR: bar\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNTkiIGhlaWdodD0iMTE4IiB2aWV3Qm94PSIwIDAgMTU5IDExOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNTkiIGhlaWdodD0iNzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBGT08gLS0+CjxnIGNsYXNzPSJwYWdlXzBfMWNhZjc4NDAgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI2NSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5GT088L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Zm9vPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSIzOSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBCQVIgLS0+CjxnIGNsYXNzPSJwYWdlXzFfMWNhZjc4NDAgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJoaWRkZW4iPgoJPGc+CgkJPHJlY3QgeD0iOTQiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NCIgeT0iMzkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NCIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijk0IiB5MT0iMzkiIHgyPSIxNTAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTAzIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkJBUjwvdGV4dD4KCTx0ZXh0IHg9IjEwMiIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YmFyPC90ZXh0PgoJPGxpbmUgeDE9IjEwMiIgeTE9IjU5IiB4Mj0iMTIzIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gUGFnZXIgLS0+CjxjaXJjbGUgY3g9IjY5LjUiIGN5PSI5OCIgcj0iNSIgZmlsbD0iZ3JheSIgaWQ9InBhZ2VyX2RvdF8wXzFjYWY3ODQwIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDAoZXZ0LDApIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8Y2lyY2xlIGN4PSI4OS41IiBjeT0iOTgiIHI9IjUiIGZpbGw9ImxpZ2h0Z3JheSIgaWQ9InBhZ2VyX2RvdF8xXzFjYWY3ODQwIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDAoZXZ0LDEpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8xY2FmNzg0MChldnQsIHBhZ2UpIHsKCQlmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykgewoJCQljb21wb25lbnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShgcGFnZV8ke2l9XzFjYWY3ODQwYCk7CgkJCWZvciAodmFyIGogPSAwOyBqIDwgY29tcG9uZW50cy5sZW5ndGg7IGorKykgewoJCQkJY29tcG9uZW50c1tqXS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsIGkgPD0gcGFnZSA/ICJ2aXNpYmxlIiA6ICJoaWRkZW4iKTsKCQkJfTsKCQkJZG90ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYHBhZ2VyX2RvdF8ke2l9XzFjYWY3ODQwYCk7CgkJCWRvdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIGkgPD0gcGFnZSA/ICJncmF5IiA6ICJsaWdodGdyYXkiKTsKCQl9Cgl9Cl1dPgo8L3NjcmlwdD4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [100]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nFOO: foo\n  BAR: bar\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNTkiIGhlaWdodD0iMTE4IiB2aWV3Qm94PSIwIDAgMTU5IDExOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNTkiIGhlaWdodD0iNzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBGT08gLS0+CjxnIGNsYXNzPSJwYWdlXzBfMWNhZjc4NDAgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI2NSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5GT088L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Zm9vPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSIzOSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBCQVIgLS0+CjxnIGNsYXNzPSJwYWdlXzFfMWNhZjc4NDAgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJoaWRkZW4iPgoJPGc+CgkJPHJlY3QgeD0iOTQiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NCIgeT0iMzkiIHdpZHRoPSI1NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NCIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijk0IiB5MT0iMzkiIHgyPSIxNTAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTAzIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkJBUjwvdGV4dD4KCTx0ZXh0IHg9IjEwMiIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YmFyPC90ZXh0PgoJPGxpbmUgeDE9IjEwMiIgeTE9IjU5IiB4Mj0iMTIzIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gUGFnZXIgLS0+CjxjaXJjbGUgY3g9IjY5LjUiIGN5PSI5OCIgcj0iNSIgZmlsbD0iZ3JheSIgaWQ9InBhZ2VyX2RvdF8wXzFjYWY3ODQwIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDAoZXZ0LDApIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8Y2lyY2xlIGN4PSI4OS41IiBjeT0iOTgiIHI9IjUiIGZpbGw9ImxpZ2h0Z3JheSIgaWQ9InBhZ2VyX2RvdF8xXzFjYWY3ODQwIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDAoZXZ0LDEpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8xY2FmNzg0MChldnQsIHBhZ2UpIHsKCQlmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykgewoJCQljb21wb25lbnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShgcGFnZV8ke2l9XzFjYWY3ODQwYCk7CgkJCWZvciAodmFyIGogPSAwOyBqIDwgY29tcG9uZW50cy5sZW5ndGg7IGorKykgewoJCQkJY29tcG9uZW50c1tqXS5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidmlzaWJpbGl0eSIsIGkgPD0gcGFnZSA/ICJ2aXNpYmxlIiA6ICJoaWRkZW4iKTsKCQkJfTsKCQkJZG90ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYHBhZ2VyX2RvdF8ke2l9XzFjYWY3ODQwYCk7CgkJCWRvdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIGkgPD0gcGFnZSA/ICJncmF5IiA6ICJsaWdodGdyYXkiKTsKCQl9Cgl9Cl1dPgo8L3NjcmlwdD4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ce problème trahit une « collision » : différents éléments du <a href=\"https://fr.wikipedia.org/wiki/Document_Object_Model\">DOM</a> se sont vus attribuer la même empreinte (obtenue par hachage du texte-source). La solution est de passer un entier discriminant qui, par concaténation, fera de ces empreintes de véritables identifiants.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [101]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --uid_suffix 1\nFOO: foo\n  BAR: bar\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNTkiIGhlaWdodD0iMTE4IiB2aWV3Qm94PSIwIDAgMTU5IDExOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNTkiIGhlaWdodD0iNzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBGT08gLS0+CjxnIGNsYXNzPSJwYWdlXzBfMWNhZjc4NDBfMSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjY1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZPTzwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5mb288L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjM5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IEJBUiAtLT4KPGcgY2xhc3M9InBhZ2VfMV8xY2FmNzg0MF8xIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0iaGlkZGVuIj4KCTxnPgoJCTxyZWN0IHg9Ijk0IiB5PSI5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOTQiIHk9IjM5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOTQiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5NCIgeTE9IjM5IiB4Mj0iMTUwIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEwMyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5CQVI8L3RleHQ+Cgk8dGV4dCB4PSIxMDIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmJhcjwvdGV4dD4KCTxsaW5lIHgxPSIxMDIiIHkxPSI1OSIgeDI9IjEyMyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIFBhZ2VyIC0tPgo8Y2lyY2xlIGN4PSI2OS41IiBjeT0iOTgiIHI9IjUiIGZpbGw9ImdyYXkiIGlkPSJwYWdlcl9kb3RfMF8xY2FmNzg0MF8xIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDBfMShldnQsMCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ii8+CjxjaXJjbGUgY3g9Ijg5LjUiIGN5PSI5OCIgcj0iNSIgZmlsbD0ibGlnaHRncmF5IiBpZD0icGFnZXJfZG90XzFfMWNhZjc4NDBfMSIgY2xhc3M9InBhZ2VyX2RvdCIgc3Ryb2tlLXdpZHRoPSIwIiBvbmNsaWNrPSJzd2l0Y2hfcGFnZV92aXNpYmlsaXR5XzFjYWY3ODQwXzEoZXZ0LDEpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8xY2FmNzg0MF8xKGV2dCwgcGFnZSkgewoJCWZvciAodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7CgkJCWNvbXBvbmVudHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGBwYWdlXyR7aX1fMWNhZjc4NDBfMWApOwoJCQlmb3IgKHZhciBqID0gMDsgaiA8IGNvbXBvbmVudHMubGVuZ3RoOyBqKyspIHsKCQkJCWNvbXBvbmVudHNbal0uc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCBpIDw9IHBhZ2UgPyAidmlzaWJsZSIgOiAiaGlkZGVuIik7CgkJCX07CgkJCWRvdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGBwYWdlcl9kb3RfJHtpfV8xY2FmNzg0MF8xYCk7CgkJCWRvdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIGkgPD0gcGFnZSA/ICJncmF5IiA6ICJsaWdodGdyYXkiKTsKCQl9Cgl9Cl1dPgo8L3NjcmlwdD4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [102]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --uid_suffix 2\nFOO: foo\n  BAR: bar\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNTkiIGhlaWdodD0iMTE4IiB2aWV3Qm94PSIwIDAgMTU5IDExOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxNTkiIGhlaWdodD0iNzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBGT08gLS0+CjxnIGNsYXNzPSJwYWdlXzBfMWNhZjc4NDBfMiBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU2IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjY1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZPTzwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5mb288L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjM5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IEJBUiAtLT4KPGcgY2xhc3M9InBhZ2VfMV8xY2FmNzg0MF8yIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0iaGlkZGVuIj4KCTxnPgoJCTxyZWN0IHg9Ijk0IiB5PSI5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOTQiIHk9IjM5IiB3aWR0aD0iNTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOTQiIHk9IjkiIHdpZHRoPSI1NiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5NCIgeTE9IjM5IiB4Mj0iMTUwIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEwMyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5CQVI8L3RleHQ+Cgk8dGV4dCB4PSIxMDIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmJhcjwvdGV4dD4KCTxsaW5lIHgxPSIxMDIiIHkxPSI1OSIgeDI9IjEyMyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIFBhZ2VyIC0tPgo8Y2lyY2xlIGN4PSI2OS41IiBjeT0iOTgiIHI9IjUiIGZpbGw9ImdyYXkiIGlkPSJwYWdlcl9kb3RfMF8xY2FmNzg0MF8yIiBjbGFzcz0icGFnZXJfZG90IiBzdHJva2Utd2lkdGg9IjAiIG9uY2xpY2s9InN3aXRjaF9wYWdlX3Zpc2liaWxpdHlfMWNhZjc4NDBfMihldnQsMCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ii8+CjxjaXJjbGUgY3g9Ijg5LjUiIGN5PSI5OCIgcj0iNSIgZmlsbD0ibGlnaHRncmF5IiBpZD0icGFnZXJfZG90XzFfMWNhZjc4NDBfMiIgY2xhc3M9InBhZ2VyX2RvdCIgc3Ryb2tlLXdpZHRoPSIwIiBvbmNsaWNrPSJzd2l0Y2hfcGFnZV92aXNpYmlsaXR5XzFjYWY3ODQwXzIoZXZ0LDEpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyIvPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc3dpdGNoX3BhZ2VfdmlzaWJpbGl0eV8xY2FmNzg0MF8yKGV2dCwgcGFnZSkgewoJCWZvciAodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7CgkJCWNvbXBvbmVudHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGBwYWdlXyR7aX1fMWNhZjc4NDBfMmApOwoJCQlmb3IgKHZhciBqID0gMDsgaiA8IGNvbXBvbmVudHMubGVuZ3RoOyBqKyspIHsKCQkJCWNvbXBvbmVudHNbal0uc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCBpIDw9IHBhZ2UgPyAidmlzaWJsZSIgOiAiaGlkZGVuIik7CgkJCX07CgkJCWRvdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGBwYWdlcl9kb3RfJHtpfV8xY2FmNzg0MF8yYCk7CgkJCWRvdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIGkgPD0gcGFnZSA/ICJncmF5IiA6ICJsaWdodGdyYXkiKTsKCQl9Cgl9Cl1dPgo8L3NjcmlwdD4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Explications-du-passage-au-relationnel\">Explications du passage au relationnel<a class=\"anchor-link\" href=\"#Explications-du-passage-au-relationnel\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les gabarits de conversion en MLD (à savoir <code>html</code>, <code>markdown</code>, <code>latex</code> et <code>text</code>) admettent une sous-sous-option <code>e</code> qui accompagne le résultat par des explications détaillées du mécanisme de passage :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [103]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t markdown:e\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><p><strong>Client</strong> (<u>Réf. client</u>, Nom, Prénom, Adresse)</p>\n<ul>\n<li>Le champ <em>Réf. client</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Client</em>.</li>\n<li>Les champs <em>Nom</em>, <em>Prénom</em> et <em>Adresse</em> étaient déjà de simples attributs de l'entité <em>Client</em>.</li>\n</ul>\n</li>\n<li><p><strong>Commande</strong> (<u>Num. commande</u>, Date, Montant, <em>#Réf. client</em>)</p>\n<ul>\n<li>Le champ <em>Num. commande</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Commande</em>.</li>\n<li>Les champs <em>Date</em> et <em>Montant</em> étaient déjà de simples attributs de l'entité <em>Commande</em>.</li>\n<li>Le champ <em>Réf. client</em> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <em>Passer</em> à partir de l'entité <em>Client</em> en perdant son caractère identifiant.</li>\n</ul>\n</li>\n<li><p><strong>Inclure</strong> (<u><em>#Num. commande</em></u>, <u><em>#Réf. produit</em></u>, Quantité)</p>\n<ul>\n<li>Le champ <em>Num. commande</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Commande</em>.</li>\n<li>Le champ <em>Réf. produit</em> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <em>Produit</em>.</li>\n<li>Le champ <em>Quantité</em> était déjà un simple attribut de l'association <em>Inclure</em>.</li>\n</ul>\n</li>\n<li><p><strong>Produit</strong> (<u>Réf. produit</u>, Libellé, Prix unitaire)</p>\n<ul>\n<li>Le champ <em>Réf. produit</em> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <em>Produit</em>.</li>\n<li>Les champs <em>Libellé</em> et <em>Prix unitaire</em> étaient déjà de simples attributs de l'entité <em>Produit</em>.</li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Nous avons essayé d'être aussi précis que possible, tout en « factorisant » avec soin les lignes consécutives suseptibles de l'être. Vous pouvez adapter ces explications à votre enseignement en modifiant une copie du gabarit <code>html-ce.yaml</code>, dont les autres sont dérivés.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"MCD-%C3%A0-compl%C3%A9ter\">MCD à compléter<a class=\"anchor-link\" href=\"#MCD-%C3%A0-compl%C3%A9ter\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les MCD à trous sont des exercices classiques d'introduction aux bases de données.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Supprimer-le-marquage-d'un-identifiant\">Supprimer le marquage d'un identifiant<a class=\"anchor-link\" href=\"#Supprimer-le-marquage-d'un-identifiant\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour éviter le marquage automatique du premier attribut d'une entité comme identifiant, il suffit de le préfixer par un tiret bas (<code>_</code>) : ce caractère est donc un commutateur, qui souligne un attribut non souligné par défaut, et désouligne un attribut souligné par défaut.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [104]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: _Réf. client, Nom, Prénom, Adresse\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: _Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: _Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjMwIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSIxNjYiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDIiIHkxPSI2NCIgeDI9IjE2NiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5NiAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjEwIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iMzUiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjYzIiB4Mj0iMjEwIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjkiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTYiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMzAyIiB5MT0iNjQiIHgyPSI0NDMiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NzEiIHkxPSI2NCIgeDI9IjQ0MyIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ3OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTk4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDkyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDA4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM5NCIgeT0iMzUiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM5NCIgeTE9IjYzIiB4Mj0iNDkyIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0MDIiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSI0MDEiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM3MCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ5NyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0xJRU5UPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIzOSIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjM5IiB5PSI0NyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzkiIHk9IjE3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIzOSIgeTE9IjQ3IiB4Mj0iMzY1IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI0OCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01NQU5ERTwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjI0NyIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk1vbnRhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0RVSVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNTIxIiB5PSIxNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MjEiIHk9IjQ3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUyMSIgeT0iMTciIHdpZHRoPSIxMDAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTIxIiB5MT0iNDciIHgyPSI2MjEiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTMwIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0RVSVQ8L3RleHQ+Cgk8dGV4dCB4PSI1MjkiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIHByb2R1aXQ8L3RleHQ+Cgk8dGV4dCB4PSI1MjkiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTI5IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Masquer-un-couple-de-cardinalit%C3%A9s\">Masquer un couple de cardinalités<a class=\"anchor-link\" href=\"#Masquer-un-couple-de-cardinalit%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez masquer n'importe quelles cardinalités en les remplaçant par <code>XX</code> ou en les préfixant d'un <code>-</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [105]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: Réf. client, Nom, Prénom, Adresse\nPASSER, XX CLIENT, XX COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, -1N COMMANDE, -0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjMwIDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNjQiIHgyPSIxNjYiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDIiIHkxPSI2NCIgeDI9IjE2NiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5NiAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjEwIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iMzUiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjYzIiB4Mj0iMjEwIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjkiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjIxNiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIElOQ0xVUkUgLS0+CjxnPgoJPGxpbmUgeDE9IjMwMiIgeTE9IjY0IiB4Mj0iNDQzIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTcxIiB5MT0iNjQiIHgyPSI0NDMiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NzggMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC05OCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ5MiA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQwOCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg5OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzOTQiIHk9IjM1IiB3aWR0aD0iOTgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzOTQiIHkxPSI2MyIgeDI9IjQ5MiIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNDAyIiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPklOQ0xVUkU8L3RleHQ+CgkJPHRleHQgeD0iNDAxIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5RdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzNzAiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iODQiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI5MyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI3OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjM5IiB5PSIxNyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzkiIHk9IjQ3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIzOSIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjM5IiB5MT0iNDciIHgyPSIzNjUiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjQ4IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTU1BTkRFPC90ZXh0PgoJPHRleHQgeD0iMjQ3IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjI0NyIgeTE9IjY3IiB4Mj0iMzU1IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNDciIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyNDciIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Nb250YW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUyMSIgeT0iMTciIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTIxIiB5PSI0NyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MjEiIHk9IjE3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjUyMSIgeTE9IjQ3IiB4Mj0iNjIxIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjUzMCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QUk9EVUlUPC90ZXh0PgoJPHRleHQgeD0iNTI5IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjUyOSIgeTE9IjY3IiB4Mj0iNjA0IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1MjkiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTI5IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Nouveauté de la version 4.0.</strong> Si la cardinalité comporte un et un seul <code>X</code>, l'autre caractère sera affiché tout seul.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Masquer-un-attribut\">Masquer un attribut<a class=\"anchor-link\" href=\"#Masquer-un-attribut\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez mettre deux virgules consécutives pour réserver la place d'un attribut manquant. Les espaces insécables sont préservés, ce qui permet de réserver plus d'espace horizontal, cf. ci-dessous premier attribut vide de INCLURE.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [106]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nCLIENT: Réf. client,,, \nPASSER, XX CLIENT, XX COMMANDE\nCOMMANDE: , Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité,,,,\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzAiIGhlaWdodD0iMTQ0IiB2aWV3Qm94PSIwIDAgNjMwIDE0NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzAiIGhlaWdodD0iMTQ0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjUxIiB5MT0iNzIiIHgyPSIxNjYiIHkyPSI3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDIiIHkxPSI3MiIgeDI9IjE2NiIgeTI9IjcyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5NiA0MyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY3MSBoLTg4IFY1NyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjEwIDcxIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTM2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNzEgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyMiIgeT0iNDMiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEyMiIgeTE9IjcxIiB4Mj0iMjEwIiB5Mj0iNzEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjkiIHk9IjY0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFTU0VSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTgiIHk9Ijg4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjIxNiIgeT0iODgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIElOQ0xVUkUgLS0+CjxnPgoJPGxpbmUgeDE9IjMwMiIgeTE9IjcyIiB4Mj0iNDQzIiB5Mj0iNzIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTcxIiB5MT0iNzIiIHgyPSI0NDMiIHkyPSI3MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NzggOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzNyBoLTk4IFYyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDkyIDM3IHY4NCBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDA4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzcgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM5NCIgeT0iOSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjEyNiIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM5NCIgeTE9IjM3IiB4Mj0iNDkyIiB5Mj0iMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0MDIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU5DTFVSRTwvdGV4dD4KCQk8dGV4dCB4PSI0MDEiIHk9IjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM3MCIgeT0iODgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ5NyIgeT0iODgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjE3IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iNDciIHdpZHRoPSI4NCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxNyIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iNDciIHgyPSI5MyIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNjciIHgyPSI3OSIgeTI9IjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBDT01NQU5ERSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMzkiIHk9IjI1IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIzOSIgeT0iNTUiIHdpZHRoPSIxMjYiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjM5IiB5PSIyNSIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMzkiIHkxPSI1NSIgeDI9IjM2NSIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNDgiIHk9IjQ2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q09NTUFOREU8L3RleHQ+Cgk8dGV4dCB4PSIyNDciIHk9Ijg5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyNDciIHk9IjEwNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1MjEiIHk9IjI1IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUyMSIgeT0iNTUiIHdpZHRoPSIxMDAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTIxIiB5PSIyNSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1MjEiIHkxPSI1NSIgeDI9IjYyMSIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MzAiIHk9IjQ2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPRFVJVDwvdGV4dD4KCTx0ZXh0IHg9IjUyOSIgeT0iNzIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI1MjkiIHkxPSI3NSIgeDI9IjYwNCIgeTI9Ijc1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTI5IiB5PSI4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjUyOSIgeT0iMTA2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Régression de la version 4.0.</strong> Les espaces insécables ne sont plus préservés. Il n'y a donc plus d'autre moyen de réserver davantage d'espace horizontal que d'employer le style <code>blank</code> (paragraphe suivant).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Ne-faire-appara%C3%AEtre-que-le-squelette-du-sch%C3%A9ma-conceptuel\">Ne faire apparaître que le squelette du schéma conceptuel<a class=\"anchor-link\" href=\"#Ne-faire-appara%C3%AEtre-que-le-squelette-du-sch%C3%A9ma-conceptuel\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez transformer en exercice à trous n'importe quel MCD en rendant complètement transparentes les couleurs des attributs, associations et cardinalités. Le style <code>blank</code> a été prédéfini à cet effet:</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [107]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp --colors=blank\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTk0IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1OTQiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyODUiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSJub25lIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDAiIHk9IjgwIiBmaWxsPSJub25lIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMjg1IiB5MT0iNjQiIHgyPSI0MTkiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzgiIHkxPSI2NCIgeDI9IjQxOSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0OCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTg2IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDYyIDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzkwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDg2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM3NiIgeT0iMzUiIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM3NiIgeTE9IjYzIiB4Mj0iNDYyIiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzODMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSIzODMiIHk9IjgxLjEiIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM1MiIgeT0iODAiIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2NyIgeT0iODAiIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iODciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSJub25lIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0ibm9uZSIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzQ3IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzOCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjIzMSIgeT0iNjQuMSIgZmlsbD0ibm9uZSIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzEiIHkxPSI2NyIgeDI9IjMzOSIgeTI9IjY3IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjMxIiB5PSI4MS4xIiBmaWxsPSJub25lIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMjMxIiB5PSI5OCIgZmlsbD0ibm9uZSIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTEiIHk9IjE3IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDkxIiB5PSI0NyIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5MSIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTEiIHkxPSI0NyIgeDI9IjU4NSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDIiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iNjQuMSIgZmlsbD0ibm9uZSIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSI0OTkiIHkxPSI2NyIgeDI9IjU3NCIgeTI9IjY3IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDk5IiB5PSI4MS4xIiBmaWxsPSJub25lIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQ5OSIgeT0iOTgiIGZpbGw9Im5vbmUiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Attention, n'utilisez cette méthode que pour la projection : l'information textuelle est toujours présente, susceptible d'être sélectionnée et collée ailleurs. Vous pouvez bien sûr empêcher cette possibilité en convertissant le SVG en PNG, mais le plus simple est d'appliquer une réécriture <code>empty</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [108]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t empty # équivalent de \"delete:types,notes,attrs,cards\"\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1NzYiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTc2IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1NzYiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQQVNTRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNjQiIHgyPSIxNTUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNzgiIHkxPSI2NCIgeDI9IjE1NSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE4MCAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTc4IFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTk0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMzUiIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjExNiIgeTE9IjYzIiB4Mj0iMTk0IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMjMiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjIwMCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIElOQ0xVUkUgLS0+CjxnPgoJPGxpbmUgeDE9IjI3OCIgeTE9IjY0IiB4Mj0iNDA1IiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTIyIiB5MT0iNjQiIHgyPSI0MDUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00MzQgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC04NiBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ0OCA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM3NiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg4NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNjIiIHk9IjM1IiB3aWR0aD0iODYiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzNjIiIHkxPSI2MyIgeDI9IjQ0OCIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzY5IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkluY2x1cmU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzMzgiIHk9IjgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjQ1NCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNzgiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI4NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTciIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0NyIgd2lkdGg9IjExMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE3IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMyIgeTE9IjQ3IiB4Mj0iMzMzIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzMSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0NzciIHk9IjE3IiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDc3IiB5PSI0NyIgd2lkdGg9IjkwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ3NyIgeT0iMTciIHdpZHRoPSI5MCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0NzciIHkxPSI0NyIgeDI9IjU2NyIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0ODYiIHk9IjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZHVpdDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo \nClient:  ,  ,  ,  \nPasser, XX Client, XX Commande\nCommande:  ,  ,  \nInclure, XX Commande, XX Produit:  \nProduit:  ,  ,\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Obfuscation-d'un-MCD-donn%C3%A9\">Obfuscation d'un MCD donné<a class=\"anchor-link\" href=\"#Obfuscation-d'un-MCD-donn%C3%A9\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Obfusquer un MCD consiste à vider celui-ci de sa sémantique de surface en substituant des chaînes aléatoires à tous les libellés. Cela permet de créer des exemples d'illustration de telle ou telle notion « pure » sans risquer de voir son public se focaliser sur des détails-métier (c'est l'équivalent de la <a href=\"https://fr.wikipedia.org/wiki/Variable_m%C3%A9tasyntaxique\">variable méta-syntaxique</a> <code>foobar</code> dans le contexte de la pédagogie de la programmation).</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [109]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp --seed=1 --select mcd -t obfuscate  # raccourci pour \"obfuscate:labels\"\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1ODYiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTg2IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1ODYiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBMSUJFTExVTSAtLT4KPGc+Cgk8bGluZSB4MT0iNTgiIHkxPSI2NCIgeDI9IjE4NSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI5NSIgeTE9IjY0IiB4Mj0iMTg1IiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjIwIDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtOTggVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMzQgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNTAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTM2IiB5PSIzNSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTM2IiB5MT0iNjMiIHgyPSIyMzQiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE0MyIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5MaWJlbGx1bTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjExMiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjI0MCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBNVUxJRVJFUyAtLT4KPGc+Cgk8bGluZSB4MT0iMjk1IiB5MT0iNjQiIHgyPSI0MDYiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzEiIHkxPSI2NCIgeDI9IjQwNiIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ0MiAzNSBhMTQgMTQgOTAgMCAxIDE0IDE0IFY2MyBoLTEwMCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ1NiA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM3MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSIzNSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM1NiIgeTE9IjYzIiB4Mj0iNDU2IiB5Mj0iNjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzNjQiIHk9IjU2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TXVsaWVyZXM8L3RleHQ+CgkJPHRleHQgeD0iMzYzIiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5DYXJ1czwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMzMiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ2MSIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgU0NSSVBUQU0gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iOTgiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMDciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U2NyaXB0YW08L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+U3BpY3VsYTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNjAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QZXJzZXF1aXR1cjwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EZWZlbnNvcjwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkZyb250ZW08L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEZVSVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjYzIiB5PSIxNyIgd2lkdGg9IjY0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI2MyIgeT0iNDciIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjMiIHk9IjE3IiB3aWR0aD0iNjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjYzIiB5MT0iNDciIHgyPSIzMjciIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjc2IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZ1aXQ8L3RleHQ+Cgk8dGV4dCB4PSIyNzEiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFydGVzPC90ZXh0PgoJPGxpbmUgeDE9IjI3MSIgeTE9IjY3IiB4Mj0iMzA3IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNzEiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxlcG9yaXM8L3RleHQ+Cgk8dGV4dCB4PSIyNzEiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Tb2NpaXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFRIRUFUUk8gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNDg1IiB5PSIxNyIgd2lkdGg9IjkyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ4NSIgeT0iNDciIHdpZHRoPSI5MiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0ODUiIHk9IjE3IiB3aWR0aD0iOTIiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDg1IiB5MT0iNDciIHgyPSI1NzciIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDk0IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRoZWF0cm88L3RleHQ+Cgk8dGV4dCB4PSI0OTMiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlJlcGVyaXJpPC90ZXh0PgoJPGxpbmUgeDE9IjQ5MyIgeTE9IjY3IiB4Mj0iNTQ0IiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0OTMiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlNlcnBlbnRlczwvdGV4dD4KCTx0ZXh0IHg9IjQ5MyIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFtaXNzdW08L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>En argument, vous pouvez ajouter le chemin d'un fichier texte quelconque où puiser les mots de substitution. Par exemple, le texte du <code>README</code> de ce projet :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [110]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t obfuscate:labels=../../README.md --seed=1 --select mcd\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NzYiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjc2IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2NzYiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBOT1RFQk9PSyAtLT4KPGc+Cgk8bGluZSB4MT0iNjYiIHkxPSI2NCIgeDI9IjIwMyIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMzMiIgeTE9IjY0IiB4Mj0iMjAzIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQwIDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtMTAyIFY0OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjU0IDYzIHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTY2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNjMgSDEwMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTIiIHk9IjM1IiB3aWR0aD0iMTAyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTUyIiB5MT0iNjMiIHgyPSIyNTQiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE1OSIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ob3RlYm9vazwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEyOCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjI2MCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBFU1BFQ0UgLS0+CjxnPgoJPGxpbmUgeDE9IjMzMiIgeTE9IjY0IiB4Mj0iNDQ5IiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTkyIiB5MT0iNjQiIHgyPSI0NDkiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NzQgMzUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjMgaC03OCBWNDkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ4OCA2MyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQyNCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjYzIEg3OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI0MTAiIHk9IjM1IiB3aWR0aD0iNzgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI0MTAiIHkxPSI2MyIgeDI9IjQ4OCIgeTI9IjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNDE4IiB5PSI1Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVzcMOoY2U8L3RleHQ+CgkJPHRleHQgeD0iNDE3IiB5PSI4MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5UZXh0ZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM4NiIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ5MyIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgVkVSU0lPTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTQiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjEyMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5WZXJzaW9uPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkNhcmRpbmFsaXTDqXM8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjkyIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RMOpY29tcG9zaXRpb248L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UmVsYXRpb25uZWxsZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk1hc3RlcjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQUZGSUNIRUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjgzIiB5PSIxNyIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI4MyIgeT0iNDciIHdpZHRoPSI5OCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyODMiIHk9IjE3IiB3aWR0aD0iOTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjgzIiB5MT0iNDciIHgyPSIzODEiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjkyIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFmZmljaMOpZTwvdGV4dD4KCTx0ZXh0IHg9IjI5MSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Qm9udXM8L3RleHQ+Cgk8bGluZSB4MT0iMjkxIiB5MT0iNjciIHgyPSIzMzAiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI5MSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+SW5jbHVhbnQ8L3RleHQ+Cgk8dGV4dCB4PSIyOTEiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Tdmc8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNQRUNJQUxJU0FUSU9OIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUxNyIgeT0iMTciIHdpZHRoPSIxNTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTE3IiB5PSI0NyIgd2lkdGg9IjE1MCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MTciIHk9IjE3IiB3aWR0aD0iMTUwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjUxNyIgeTE9IjQ3IiB4Mj0iNjY3IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjUyNiIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TcMOpY2lhbGlzYXRpb248L3RleHQ+Cgk8dGV4dCB4PSI1MjUiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOJZ2FsZW1lbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNTI1IiB5MT0iNjciIHgyPSI1ODkiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjUyNSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RMOpbMOpZ3XDqTwvdGV4dD4KCTx0ZXh0IHg9IjUyNSIgeT0iOTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkV4cG9ydGF0aW9uPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo essaie d'abord de trouver ce fichier à l'endroit indiqué. En cas d'échec, il le cherche (avec extension <code>.txt</code> facultative) parmi ceux distribués avec le logiciel, à savoir:</p>\n<ul>\n<li><code>\"lorem.txt\"</code> (6464 mots) : le <a href=\"https://fr.wikipedia.org/wiki/Faux-texte\">faux-texte</a> le plus courant, augmenté d'une sélection des 10000 mots latins les plus courants <a href=\"https://kyle-p-johnson.com/blog/2015/04/23/most-common-greek-latin-words.html\">compilés par Kyle P. Johnson</a>, le tout privé de ses doublons et des mots de moins de 3 lettres (<code>\"lorem_ipsum.txt\"</code> avant la version 4.0).</li>\n<li><code>\"fr.txt\"</code> (3396 mots) : une liste des 4000 mots français les plus courants, privée de ceux comportant une apostrophe ou moins de 4 lettres. Source : <a href=\"http://wortschatz.uni-leipzig.de/index.html\">http://wortschatz.uni-leipzig.de/index.html</a> <em>via</em> <a href=\"https://fr.wiktionary.org/wiki/Wiktionnaire:Listes_de_fr%C3%A9quence\">Wikitionary</a>. Nouveauté de la version 4.0.</li>\n<li><code>\"fr5.txt\"</code> (464 mots): la liste de <code>\"fr.txt\"</code>, restreinte aux mots de 5 lettres. Nouveauté de la version 4.0.</li>\n<li><code>\"en4.txt\"</code> (640 mots): une sélection (SFW) de mots anglais de quatre lettres (<code>\"four_letter_words.txt\"</code> avant la version 4.0).</li>\n<li><code>\"disparition.txt\"</code> (7489 mots) : le lexique du <a href=\"https://fr.wikipedia.org/wiki/La_Disparition_(roman)\">célèbre roman lipogrammatique</a> de Georges Perec, privé des mots de moins de 4 lettres.</li>\n</ul>\n<p>En cas de nouvel échec, il se rabat sur <code>\"lorem.txt\"</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> L'algorithme s'assure que la <a href=\"https://fr.wikipedia.org/wiki/Distance_de_Damerau-Levenshtein\">distance de Damerau-Levenshtein</a> entre deux libellés de substitution quelconques est d'au moins 3. En clair, cela signifie que, si vous donnez en examen un exercice de conversion en relationnel basé sur un tel MCD, les erreurs de transcription d'un étudiant stressé, inattentif, illettré, dyslexique, roublard, ou tout cela à la fois, ne devraient pas vous empêcher de lui octroyer les points qui lui reviennent.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Croissance-stochastique\">Croissance stochastique<a class=\"anchor-link\" href=\"#Croissance-stochastique\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez créer un MCD partiellement aléatoire à partir d'un MCD donné en lui ajoutant un nombre <code>n</code> d'associations (avec les entités nécessaires) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [111]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t grow:n=4 arrange --seed=1 --select mcd\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MjciIGhlaWdodD0iNDI4IiB2aWV3Qm94PSIwIDAgNTI3IDQyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1MjciIGhlaWdodD0iNDI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBURVJOQUlSRV85XyAtLT4KPGc+Cgk8bGluZSB4MT0iMjE3IiB5MT0iNDciIHgyPSIyMTciIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTM4IiB4Mj0iMjE3IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9Ijc1IiB5MT0iMTM4IiB4Mj0iMjE3IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI1OSAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtMTEyIFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI3MyAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzUgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDExMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNjEiIHk9IjEwOSIgd2lkdGg9IjExMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE2MSIgeTE9IjEzNyIgeDI9IjI3MyIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE2OCIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VGVybmFpcmUgOTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIyMiIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyNzkiIHk9IjE1NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMTI2IiB5PSIxNTQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBURVJOQUlSRV83XyAtLT4KPGc+Cgk8bGluZSB4MT0iNzUiIHkxPSIxMzgiIHgyPSI3NSIgeTI9IjI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMTciIHkxPSIyNDYiIHgyPSI3NSIgeTI9IjI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik0yMTcgMzcyIEMyMDcuMDIgMzEzLjQxIDE1OS42OSAyNzEuNDEgNzUgMjQ2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTExNyAyMTcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjQ1IGgtMTEyIFYyMzEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTEzMSAyNDUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzMyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI0NSBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE5IiB5PSIyMTciIHdpZHRoPSIxMTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxOSIgeTE9IjI0NSIgeDI9IjEzMSIgeTI9IjI0NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjI2IiB5PSIyMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5UZXJuYWlyZSA3PC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iODAiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMTU0IiB5PSIyNjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjE2MS40OCIgeT0iMzE3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUEFTU0VSIC0tPgo8Zz4KCTxsaW5lIHgxPSIyMTciIHkxPSIyNDYiIHgyPSIzNjQiIHkyPSIyNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTM4IiB4Mj0iMzY0IiB5Mj0iMjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM4OSAyMTcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjQ1IGgtNzggVjIzMSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDAzIDI0NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDMzOSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI0NSBINzgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzI1IiB5PSIyMTciIHdpZHRoPSI3OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjMyNSIgeTE9IjI0NSIgeDI9IjQwMyIgeTI9IjI0NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMzMiIgeT0iMjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGFzc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjYxIiB5PSIyNjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM0MSIgeT0iMjAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gSU5DTFVSRSAtLT4KPGc+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTM4IiB4Mj0iNDc1IiB5Mj0iMjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTIxNyAzNzIgQzE5Ny45NSAzNDMuMTQgMjgzLjk1IDMwMS4xNCA0NzUgMjQ2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTUwNCAyMTcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjQ1IGgtODYgVjIzMSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNTE4IDI0NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQ0NiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI0NSBIODYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDMyIiB5PSIyMTciIHdpZHRoPSI4NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQzMiIgeTE9IjI0NSIgeDI9IjUxOCIgeTI9IjI0NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQzOSIgeT0iMjM4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5jbHVyZTwvdGV4dD4KCQk8dGV4dCB4PSI0MzkiIHk9IjI2My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5RdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzOTUuMjQiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjY5IiB5PSIzMzIuMTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSRUZMRVhJVkVfMTFfIC0tPgo8Zz4KCTxwYXRoIGQ9Ik0yMTcgMzcyIEMxODIuMzMgNDA0IDEzNSA0MDQgNzUgMzcyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTIxNyAzNzIgQzE4MyAzNDAgMTM1LjY3IDM0MCA3NSAzNzIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTI3IDM0MyBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzNzEgaC0xMzIgVjM1NyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTQxIDM3MSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIzIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzcxIEgxMzIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzQzIiB3aWR0aD0iMTMyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM3MSIgeDI9IjE0MSIgeTI9IjM3MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3IiB5PSIzNjQuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6lmbGV4aXZlIDExPC90ZXh0PgoJCTx0ZXh0IHg9IjE2IiB5PSIzODkuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YXQgMTEgMTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE0NiIgeT0iMzg3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIxNDciIHk9IjM2NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJFRkxFWElWRV8xMF8gLS0+CjxnPgoJPHBhdGggZD0iTTIxNyAzNzIgQzI0OS4zMyAzNDAgMjk4LjMzIDM0MCAzNjQgMzcyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTIxNyAzNzIgQzI0OS4zMyA0MDQgMjk4LjMzIDQwNCAzNjQgMzcyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQxNiAzNDMgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzcxIGgtMTMyIFYzNTcgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQzMCAzNzEgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzMTIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYzNzEgSDEzMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyOTgiIHk9IjM0MyIgd2lkdGg9IjEzMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI5OCIgeTE9IjM3MSIgeDI9IjQzMCIgeTI9IjM3MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMwNiIgeT0iMzY0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UsOpZmxleGl2ZSAxMDwvdGV4dD4KCQk8dGV4dCB4PSIzMDUiIHk9IjM4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdCAxMCAxPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjY5IiB5PSIzNjUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjI2OSIgeT0iMzg3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVElURV84XyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNzEiIHk9IjkiIHdpZHRoPSI5MiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNzEiIHk9IjM5IiB3aWR0aD0iOTIiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTcxIiB5PSI5IiB3aWR0aD0iOTIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTcxIiB5MT0iMzkiIHgyPSIyNjMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgwIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVudGl0w6kgODwvdGV4dD4KCTx0ZXh0IHg9IjE3OSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQgOCAxPC90ZXh0PgoJPGxpbmUgeDE9IjE3OSIgeTE9IjU5IiB4Mj0iMjE1IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzkiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF0IDggMjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRU5USVRFXzZfIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI5IiB5PSI5MSIgd2lkdGg9IjkyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5IiB5PSIxMjEiIHdpZHRoPSI5MiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyOSIgeT0iOTEiIHdpZHRoPSI5MiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyOSIgeTE9IjEyMSIgeDI9IjEyMSIgeTI9IjEyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzgiIHk9IjExMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVudGl0w6kgNjwvdGV4dD4KCTx0ZXh0IHg9IjM3IiB5PSIxMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQgNiAxPC90ZXh0PgoJPGxpbmUgeDE9IjM3IiB5MT0iMTQxIiB4Mj0iNzMiIHkyPSIxNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzNyIgeT0iMTU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF0IDYgMjwvdGV4dD4KCTx0ZXh0IHg9IjM3IiB5PSIxNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF0IDYgMzwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzAyIiB5PSI5MSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMDIiIHk9IjEyMSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMDIiIHk9IjkxIiB3aWR0aD0iMTI0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMwMiIgeTE9IjEyMSIgeDI9IjQyNiIgeTI9IjEyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzE3IiB5PSIxMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21tYW5kZTwvdGV4dD4KCTx0ZXh0IHg9IjMxMCIgeT0iMTM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMzEwIiB5MT0iMTQxIiB4Mj0iNDE4IiB5Mj0iMTQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzEwIiB5PSIxNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjMxMCIgeT0iMTcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Nb250YW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc4IiB5PSIxOTEiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNzgiIHk9IjIyMSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3OCIgeT0iMTkxIiB3aWR0aD0iNzgiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE3OCIgeTE9IjIyMSIgeDI9IjI1NiIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTg3IiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSIxODYiIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMTg2IiB5MT0iMjQxIiB4Mj0iMjQ4IiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTg2IiB5PSIyNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Tm9tPC90ZXh0PgoJPHRleHQgeD0iMTg2IiB5PSIyNzIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE4NiIgeT0iMjg5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5BZHJlc3NlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE3MCIgeT0iMzI1IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTcwIiB5PSIzNTUiIHdpZHRoPSI5NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNzAiIHk9IjMyNSIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE3MCIgeTE9IjM1NSIgeDI9IjI2NCIgeTI9IjM1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgxIiB5PSIzNDYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iMTc4IiB5PSIzNzIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIxNzgiIHkxPSIzNzUiIHgyPSIyNTMiIHkyPSIzNzUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzgiIHk9IjM4OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5MaWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3OCIgeT0iNDA2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<ul>\n<li><p>Des sous-options pré-définies (données ci-dessous avec leur valeur par défaut après le <code>=</code>) permettent de spécifier finement le nombre désiré :</p>\n<ul>\n<li>d'associations réflexives (<code>arity_1=2</code>) ;</li>\n<li>d'associations ternaires (<code>arity_3=2</code>) ;</li>\n<li>d'associations quaternaires (<code>arity_4=0</code>) ;</li>\n<li>d'associations doubles, i.e., associant le même couple d'entités (<code>doubles=1</code>) ;</li>\n<li>d'identifiants composites (<code>composites=1</code>) ;</li>\n<li>d'attributs maximum par entité (<code>ent_attrs=4</code>) ;</li>\n<li>d'attributs maximum par association (<code>assoc_attrs=2</code>).</li>\n</ul>\n</li>\n<li><p>On ne peut pas préciser directement le nombre d'associations binaires : si le nombre total des autres associations spécifiées n'arrivent pas à <code>n</code>, elles viennent en complément.</p>\n</li>\n<li><p>Des sous-options de forme plus ou moins libre décrivent les cardinalités. Par exemple, <code>_11-*N=2</code> créera deux entités faibles et <code>/*N-*N</code> un agrégat. Les associations de complément sont <code>*N-*N</code>.</p>\n</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Avec la sous-option <code>from_scratch</code>, le MCD de départ est vide. À titre d'exemple, voici la transformation complexe invoquée par Mocodo online pour créer un MCD d'entraînement à la conversion au relationnel, accompagné de cette dernière. Notez la création de rôles par défaut : ils permettent de simuler le rétablissement de la sémantique des associations disparues.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [ ]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> --seed=2 --mld -t grow:from_scratch,arity_3=1,_11-*N=1 obfuscate create:roles lower:roles arrange\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il n'est pas impossible que le MCD résultant soit incorrect (p. ex., apparition d'une identification relative circulaire), mais les contrôles effectués <em>a priori</em> et <em>a posteriori</em> devraient dans la majorité des cas produire quelque chose de raisonnable.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"G%C3%A9n%C3%A9ration-d'un-QR-code\">Génération d'un QR code<a class=\"anchor-link\" href=\"#G%C3%A9n%C3%A9ration-d'un-QR-code\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Impressionnez votre public en accompagnant l'option <code>-t share</code> de <code>--defer</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [112]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t share --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_url.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMTAwOCIgaGVpZ2h0PSIxMDA4Ij4KCTwhLS0gQ3JlYXRlZCB3aXRoIGh0dHBzOi8vYXBpLnFyc2VydmVyLmNvbSAoUVIgQ29kZSBBUEksIHNlZSBnb1FSLm1lL2FwaSBmb3IgaW5mb3JtYXRpb24pIC0tPgoJPHRpdGxlPlFSIENvZGU8L3RpdGxlPgoJPGRlc2M+aHR0cHM6Ly93d3cubW9jb2RvLm5ldC8/bWNkPWVOcHRrTUVLZ2tBUWh1ODl4UndMSkRRUXd0dXlTZ201bUVnWDZiRGxCZ3U2eHJZTHZaTFA0WXMxYWhaWXRfbV9ZZWJfWjJnbGhUSUJaRjE3VzhOMVVGQ2NTRWIzSkZ0dVYyY0hXRk5feWNiM2U1YnFybFZfT0NtMWVEekVqQzlTamxBNzRES2dnNFVEbmdlMHFXdXVTckdZaWdDWXJUSEZXODV5aE53Z0Nra2VvVWdhWlhnZk5ZeG9uSkREMG5PZERUckY2bHBaTFhBXy0td2ZmRlBkbEZiaXBVZUxjOUowTFJReHk2TmRsR0ctcVRtLTRUN0ttZjlCWGtSVjlYTVQ5dDN4Rl9JSlZrbkRwUllfZ1Y0TFJHNVo8L2Rlc2M+Cgk8cmVjdCBzdHlsZT0iZmlsbDpyZ2IoMjU1LCAyNTUsIDI1NSk7ZmlsbC1vcGFjaXR5OjEiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMDA4IiBoZWlnaHQ9IjEwMDgiIC8+Cgk8ZyBpZD0iZWxlbWVudHMiPgoJCTxwYXRoIHN0eWxlPSJmaWxsOnJnYigwLCAwLCAwKSIgZD0iTSAxNiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDExMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDExMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5MiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDE0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCwxNDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDE0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwxNjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDE2MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwxNzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwyMDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsMjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCwyMDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMjI0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwyNzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsMjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDI4OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsMjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMzIwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDMzNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzNTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDM1MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDM2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsMzY4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDM4NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQwMCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0MTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDQxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw0MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw0NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQ0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDQ2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDUxMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw1MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDUyOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDU0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDU2MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw1NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw1OTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw1OTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDYwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDYyNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNjI0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsNjQwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw2NDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY1NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDY3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw2NzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDY4OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDcwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDczNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDc1MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDc4NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDgwMCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw4MTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw4MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDgzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDg0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsODQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDg4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsODgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDg4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsODgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw5MTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDkxMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDkyOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsOTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsOTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw5NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDk3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw5NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDk3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogIiAvPgoJPC9nPgo8L3N2Zz4K\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Limitation.</strong> Comme il faut un mobile pour scanner ce QR code, et que Mocodo online n'est pas vraiment adapté aux mobiles, l'intérêt réel de cette fonctionnalité est pour l'instant discutable.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Biblioth%C3%A8que-de-MCD-en-ligne\">Bibliothèque de MCD en ligne<a class=\"anchor-link\" href=\"#Biblioth%C3%A8que-de-MCD-en-ligne\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous avez créé avec Mocodo toute une bibliothèque de MCD, certains pour illustrer des points de votre cours, d'autres comme solutions d'exercices. À partir de la version 4.1, vous pouvez donner accès à tel ou tel de ces MCD en communiquant simplement son nom à vos étudiants.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Acc%C3%A8s-sous-Mocodo-online\">Accès sous Mocodo online<a class=\"anchor-link\" href=\"#Acc%C3%A8s-sous-Mocodo-online\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour comprendre le fonctionnement, accédons à un MCD de la bibliothèque par défaut : copiez-collez la chaîne <code>def_weak-974e</code> comme titre du MCD dans l'onglet <em>Entrée</em> de <a href=\"https://www.mocodo.net\">Mocodo online</a>. Le texte-source est mis à jour avec le contenu d'un fichier <code>def_weak-974e.mcd</code> stocké en ligne :</p>\n<p><img alt=\"\" src=\"examples/lib_demo.png\"/></p>\n<p><strong>Remarques.</strong></p>\n<ul>\n<li>Vous avez sans doute déjà utilisé cette fonctionnalité sans le savoir en parcourant le tutoriel, dont les MCD, appelés <code>tuto-0000</code>, <code>tuto-0001</code>, etc., sont récupérés de la même manière.</li>\n<li>Tous les noms de fichiers de la bibliothèque par défaut se terminent par un code de quatre caractères alphanumériques : cette disposition évite qu'un utilisateur ne tombe dessus par hasard, et protège certains MCD (typiquement, les solutions d'exercices) de la curiosité naturelle des étudiants. Au moment de la correction, je leur donne simplement le nom complet, et ils récupèrent directement la solution, ce qui dégage du temps pour des activités plus éducatives que la recopie.</li>\n</ul>\n<p>Bien sûr, la plupart des MCD de la bibliothèque par défaut n'intéressent que mon enseignement, et n'ont pas vocation à être diffusés au-delà du cercle très select des <em>happy few</em> qui en bénéficient.<br>\nPour mettre votre propre bibliothèque à la disposition de vos propres étudiants :</br></p>\n<ol>\n<li>placez-la dans un répertoire dédié d'un serveur sur lequel vous avez les droits ;</li>\n<li>copiez-collez l'URL de ce répertoire dans le champ <em>Bibliothèque de MCD</em> (onglet <em>Options</em>). Désormais, c'est à cette adresse que Mocodo essaiera de trouver les MCD quand vous mettrez à jour leur titre ;</li>\n<li>vos étudiants devront eux-mêmes avoir renseigné le champ en question, ce qui peut poser des problèmes à certains. Facilitez-leur la tâche en leur donnant le lien suivant (tout ce qui suit <code>lib=</code> doit bien sûr être remplacé par l'adresse de votre répertoire distant) :</li>\n</ol>\n<pre><code>https://www.mocodo.net/?lib=https://your_server.com/path/to/your/mcd/directory\n</code></pre>\n<p>Ils n'auront plus qu'à cliquer pour remplir automatiquement le champ approprié, lequel persistera dans les cookies de leur navigateur.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Acc%C3%A8s-sous-terminal-ou-Jupyter-Notebook\">Accès sous terminal ou Jupyter Notebook<a class=\"anchor-link\" href=\"#Acc%C3%A8s-sous-terminal-ou-Jupyter-Notebook\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'option <code>--input</code> (ou <code>-i</code>) est surchargée pour aller chercher un MCD sur internet s'il ne se trouve pas dans le répertoire local. Pour commencer la démonstration, assurons-nous que le fichier en question n'existe pas en local :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [113]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">path</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s2\">\"def_weak-974e.mcd\"</span><span class=\"p\">)</span>\n<span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">unlink</span><span class=\"p\">(</span><span class=\"n\">missing_ok</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">()</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[113]:</div>\n<div class=\"jp-RenderedText jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>False</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Récupérons-le de façon transparente dans la bibliothèque par défaut (avec ou sans extension <code>.mcd</code>) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [114]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i def_weak-974e.mcd\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNDQiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMzQ0IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNDQiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjYxIiB5MT0iNTYiIHgyPSIxNjIiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNzMiIHkxPSI1NiIgeDI9IjE2MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTYyIiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTQ5IiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTE4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTg4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjE4OCIgeTE9Ijc0IiB4Mj0iMjA2IiB5Mj0iNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IE9FVVZSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTEzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk9FdXZyZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Db3RlIG9ldXZyZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iOTciIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5UaXRyZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZSBwYXJ1dGlvbjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVhFTVBMQUlSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMTEiIHk9IjkiIHdpZHRoPSIxMjQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjExIiB5PSIzOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTEiIHk9IjkiIHdpZHRoPSIxMjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjExIiB5MT0iMzkiIHgyPSIzMzUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjIyIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkV4ZW1wbGFpcmU8L3RleHQ+Cgk8dGV4dCB4PSIyMTkiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gZXhlbXBsYWlyZTwvdGV4dD4KCTxsaW5lIHgxPSIyMTkiIHkxPSI1OSIgeDI9IjMyNyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMjE5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5FdGF0IGR1IGxpdnJlPC90ZXh0PgoJPHRleHQgeD0iMjE5IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZSBk4oCZYWNoYXQ8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez qu'au passage, pour le rendre disponible hors ligne, le fichier a été sauvegardé sur votre machine :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [115]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">()</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[115]:</div>\n<div class=\"jp-RenderedText jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>True</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> Si le paramètre de <code>-i</code> est un chemin de la forme <code>path/to/file.mcd</code> (avec ou sans extension <code>.mcd</code>), c'est la dernière partie du chemin (à savoir <code>file.mcd</code>) qui sera récupérée sur le serveur. Par contre, c'est le chemin complet qui déterminera l'emplacement de la sauvegarde.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour utiliser votre propre répertoire distant, passez son URL à l'option <code>--lib</code> :</p>\n<pre><code>mocodo -i your_diagram.mcd --lib https://your_server.com/path/to/your/mcd/directory\n</code></pre>\n<p>Nous vous conseillons d'ajouter cette option dans votre fichier de paramètres personnalisé <code>params.json</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Compl%C3%A9ments-sur-l'aspect-visuel\">Compléments sur l'aspect visuel<a class=\"anchor-link\" href=\"#Compl%C3%A9ments-sur-l'aspect-visuel\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Styles\">Styles<a class=\"anchor-link\" href=\"#Styles\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Plusieurs styles prédéfinis sont distribués avec l'application. Un style se définit comme la combinaison d'une palette de couleurs (répertoire <code>colors</code>) avec un dictionnaire de polices et de dimensions (répertoire <code>shapes</code>).</p>\n<p>Vous pouvez bien sûr créer vos propres styles en vous inspirant des fichiers fournis. Si vous êtes particulièrement content d'un style, soumettez-le pour inclusion dans une prochaine distribution.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Réglages.</strong> Une approximation de la largeur des caractères des différentes polices a été pré-calculée sous macOS. Il est possible qu'elle soit inexacte, en particulier sous Windows ou Linux. Dans ce cas, en particulier, les traits de soulignement n'atteindront pas ou excéderont la largeur des libellés soulignés. Vous pouvez contourner le problème en appliquant un facteur multiplicatif avec l'argument <code>--adjust_width</code>).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Param%C3%A9trage-du-r%C3%A9arrangement-automatique\">Paramétrage du réarrangement automatique<a class=\"anchor-link\" href=\"#Param%C3%A9trage-du-r%C3%A9arrangement-automatique\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il est possible de demander à Mocodo de chercher tout seul une « bonne » permutation des définitions des boîtes, ce qui à la main deviendrait vite difficile.</p>\n<p>Le critère que nous avons retenu pour évaluer la qualité du tracé est double :</p>\n<ol>\n<li>les liens ne doivent pas se couper ;</li>\n<li>leur longueur cumulée doit être minimale.</li>\n</ol>\n<p>Actuellement, deux algorithmes d'arrangement sont fournis :</p>\n<ul>\n<li>un algorithme exact (<code>bb</code>, pour <em>Branch &amp; Bound</em>), qui ne trouve que des solutions satisfaisant au premier critère ;</li>\n<li>un algorithme approché (<code>ga</code>, pour <em>Genetic Algorithm</em>), réservé aux cas où il est impossible d'y satisfaire. L'algorithme va alors chercher des solutions où les liens se coupent seulement le moins possible.</li>\n</ul>\n<p><strong>Remarque.</strong> Mocodo met en œuvre une technique de réarrangement originale : en contraignant la position des boîtes aux intersections d'une grille invisible, il transforme un classique <a href=\"https://en.wikipedia.org/wiki/Graph_embedding\">problème de plongement</a> en un <a href=\"https://fr.wikipedia.org/wiki/Probl%C3%A8me_d%27affectation\">problème d'affectation</a>, ce qui permet de satisfaire de façon efficace à un certain nombre de contraintes esthétiques pertinentes (planarité, compacité, etc.).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Nous illustrerons les algorithmes et leurs paramètres sur le MCD d'accueil de Mocodo online.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le réarrangement automatique peut se faire sans contraintes, ou dans les limites d'une grille spécifiée par l'utilisateur.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"M%C3%A9thode-exacte-(branch-&amp;-bound)\">Méthode exacte (<em>branch &amp; bound</em>)<a class=\"anchor-link\" href=\"#M%C3%A9thode-exacte-(branch-&amp;-bound)\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Arrangement-non-contraint-(par-d%C3%A9faut)\">Arrangement non contraint (par défaut)<a class=\"anchor-link\" href=\"#Arrangement-non-contraint-(par-d%C3%A9faut)\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le réarrangement dit organique consiste à choisir une première boîte au hasard, puis à essayer d'agréger les autres sans se préoccuper de contenir le tout dans une grille prédéterminée :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [116]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ../examples/landing --select mcd --seed=2 -t arrange\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3MjciIGhlaWdodD0iMzc2IiB2aWV3Qm94PSIwIDAgNzI3IDM3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3MjciIGhlaWdodD0iMzc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIzOTQiIHkxPSI0NyIgeDI9IjI1NiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjE0NyIgeDI9IjI1NiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjU2IiBjeT0iNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMjQzIiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzAxIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjMwMSIgeTE9IjY1IiB4Mj0iMzE5IiB5Mj0iNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNjEiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEVNUExPWUVSIC0tPgo8ZyBjbGFzcz0icGFnZV8wX2UwODI2Zjc1IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMjU2IiB5MT0iMTQ3IiB4Mj0iODYiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iODYiIHkxPSIyMzgiIHgyPSI4NiIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0xMzAgMTE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjE0NiBoLTExNiBWMTMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0xNDQgMTQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNDYgSDExNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyOCIgeT0iMTE4IiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMjgiIHkxPSIxNDYiIHgyPSIxNDQiIHkyPSIxNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzNiIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RU1QTE9ZRVI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxODEiIHk9IjE2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iOTEiIHk9IjE5MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIERJUklHRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIyNTYiIHkxPSIxNDciIHgyPSIzOTQiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzk0IiB5MT0iMjM4IiB4Mj0iMzk0IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQyNiAxMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTQ2IGgtOTIgVjEzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDQwIDE0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM2MiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE0NiBIOTIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzQ4IiB5PSIxMTgiIHdpZHRoPSI5MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM0OCIgeTE9IjE0NiIgeDI9IjQ0MCIgeTI9IjE0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1NiIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RElSSUdFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMxMyIgeT0iMTYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd19lMDgyNmY3NShldnQsJ3Jlc3BvbnNhYmxlJykiIG9ubW91c2VvdXQ9ImhpZGVfZTA4MjZmNzUoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM5OSIgeT0iMTkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVFJBVkFJTExFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lMDgyNmY3NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjE0NyIgeDI9IjI1NiIgeTI9IjIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzOTQiIHkxPSIyMzgiIHgyPSIyNTYiIHkyPSIyMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMzA2IDIwOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMzcgaC0xMjggVjIyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzIwIDIzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIwNiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIzNyBIMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE5MiIgeT0iMjA5IiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTkyIiB5MT0iMjM3IiB4Mj0iMzIwIiB5Mj0iMjM3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTk5IiB5PSIyMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5UUkFWQUlMTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjYxIiB5PSIyMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjMyNSIgeT0iMjU0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUkVRVUVSSVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIzOTQiIHkxPSIyMzgiIHgyPSI1MjQiIHkyPSIyMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTI0IiB5MT0iMzI5IiB4Mj0iNTI0IiB5Mj0iMjM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTU2NiAyMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjM3IGgtMTEyIFYyMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTU4MCAyMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0ODIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYyMzcgSDExMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI0NjgiIHk9IjIwOSIgd2lkdGg9IjExMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQ2OCIgeTE9IjIzNyIgeDI9IjU4MCIgeTI9IjIzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQ3NiIgeT0iMjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UkVRVcOJUklSPC90ZXh0PgoJCTx0ZXh0IHg9IjQ3NSIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF0w6kgcmVxdWlzZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQ0NCIgeT0iMjU0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI1MjkiIHk9IjI4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlRST0xFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lMDgyNmY3NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPHBhdGggZD0iTTI1NiAzMjkgQzIyNS4zMyAzNjEgMTY4LjY3IDM2MSA4NiAzMjkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjE1MS4wMSAzNDguNyAxNjMuOTUgMzQ1LjE3IDE1OC44NSAzNTAuMjcgMTYxLjYgMzU2Ljk0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxwYXRoIGQ9Ik0yNTYgMzI5IEMyMjYgMjk3IDE2OS4zMyAyOTcgODYgMzI5IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTEzNyAzMDAgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzI4IGgtMTMwIFYzMTQgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTE1MSAzMjggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzNSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjMyOCBIMTMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjIxIiB5PSIzMDAiIHdpZHRoPSIxMzAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyMSIgeTE9IjMyOCIgeDI9IjE1MSIgeTI9IjMyOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjI4IiB5PSIzMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT05UUsOUTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTgxIiB5PSIzNDQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93X2UwODI2Zjc1KGV2dCwnbcOocmUnKSIgb25tb3VzZW91dD0iaGlkZV9lMDgyNmY3NShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMTgyIiB5PSIzMjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93X2UwODI2Zjc1KGV2dCwnZmlsaWFsZScpIiBvbm1vdXNlb3V0PSJoaWRlX2UwODI2Zjc1KGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRk9VUk5JUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lMDgyNmY3NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjM5NCIgeTE9IjIzOCIgeDI9IjM5NCIgeTI9IjMyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MjQiIHkxPSIzMjkiIHgyPSIzOTQiIHkyPSIzMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjU2IiB5MT0iMzI5IiB4Mj0iMzk0IiB5Mj0iMzI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQzMCAzMDAgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzI4IGgtMTAwIFYzMTQgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ0NCAzMjggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzNTggYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYzMjggSDEwMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNDQiIHk9IjMwMCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM0NCIgeTE9IjMyOCIgeDI9IjQ0NCIgeTI9IjMyOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1MiIgeT0iMzIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Rk9VUk5JUjwvdGV4dD4KCQk8dGV4dCB4PSIzNTEiIHk9IjM0Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdMOpIGZvdXJuaWU8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzOTkiIHk9IjI5MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNDU1IiB5PSIzNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjMxMiIgeT0iMzQ1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09NUE9TRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik01MjQgMzI5IEM1NTguNjcgMjk3IDYwMy4zMyAyOTcgNjU4IDMyOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik01MjQgMzI5IEM1NTguNjcgMzYxIDYwMy4zMyAzNjEgNjU4IDMyOSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik03MDQgMzAwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjMyOCBoLTEyMCBWMzE0IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03MTggMzI4IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINjEyIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzI4IEgxMjAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNTk4IiB5PSIzMDAiIHdpZHRoPSIxMjAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI1OTgiIHkxPSIzMjgiIHgyPSI3MTgiIHkyPSIzMjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI2MDUiIHk9IjMyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTVBPU0VSPC90ZXh0PgoJCTx0ZXh0IHg9IjYwNSIgeT0iMzQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjU3NCIgeT0iMzIyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd19lMDgyNmY3NShldnQsJ2NvbXBvc8OpZScpIiBvbm1vdXNlb3V0PSJoaWRlX2UwODI2Zjc1KGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI1NzQiIHk9IjM0NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfZTA4MjZmNzUoZXZ0LCdjb21wb3NhbnRlJykiIG9ubW91c2VvdXQ9ImhpZGVfZTA4MjZmNzUoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQVlBTlRfRFJPSVQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjMyNCIgeT0iOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjQiIHk9IjM5IiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyNCIgeT0iOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMjQiIHkxPSIzOSIgeDI9IjQ2NCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMzIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QVlBTlQtRFJPSVQ8L3RleHQ+Cgk8dGV4dCB4PSIzMzIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBheWFudC1kcm9pdDwvdGV4dD4KCTxsaW5lIHgxPSIzMzIiIHkxPSI1OSIgeDI9IjQzMyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMzMyIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWVuPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFTVBMT1lFIC0tPgo8ZyBjbGFzcz0icGFnZV8wX2UwODI2Zjc1IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIyMDQiIHk9IjEwOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMDQiIHk9IjEzOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMDQiIHk9IjEwOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMDQiIHkxPSIxMzkiIHgyPSIzMDgiIHkyPSIxMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIxMiIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RU1QTE9Zw4k8L3RleHQ+Cgk8dGV4dCB4PSIyMTIiIHk9IjE1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tYXRyaWN1bGU8L3RleHQ+Cgk8bGluZSB4MT0iMjEyIiB5MT0iMTU5IiB4Mj0iMjcxIiB5Mj0iMTU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjEyIiB5PSIxNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGVtcGxvecOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBERVBBUlRFTUVOVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lMDgyNmY3NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMjAwIiB3aWR0aD0iMTU0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIzMCIgd2lkdGg9IjE1NCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMDAiIHdpZHRoPSIxNTQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjIzMCIgeDI9IjE2MyIgeTI9IjIzMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjIyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkTDiVBBUlRFTUVOVDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIyNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBkw6lwYXJ0ZW1lbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIyNTAiIHgyPSIxMzIiIHkyPSIyNTAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBkw6lwYXJ0ZW1lbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF9lMDgyNmY3NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iMzQ5IiB5PSIyMDAiIHdpZHRoPSI5MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNDkiIHk9IjIzMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM0OSIgeT0iMjAwIiB3aWR0aD0iOTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzQ5IiB5MT0iMjMwIiB4Mj0iNDM5IiB5Mj0iMjMwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNTgiIHk9IjIyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0pFVDwvdGV4dD4KCTx0ZXh0IHg9IjM1NyIgeT0iMjQ3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gcHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjM1NyIgeTE9IjI1MCIgeDI9IjQzMSIgeTI9IjI1MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM1NyIgeT0iMjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBwcm9qZXQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNPQ0lFVEUgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjIwNSIgeT0iMjkxIiB3aWR0aD0iMTAyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIwNSIgeT0iMzIxIiB3aWR0aD0iMTAyIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIwNSIgeT0iMjkxIiB3aWR0aD0iMTAyIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIwNSIgeTE9IjMyMSIgeDI9IjMwNyIgeTI9IjMyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjE2IiB5PSIzMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TT0NJw4lUw4k8L3RleHQ+Cgk8dGV4dCB4PSIyMTMiIHk9IjMzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIHNvY2nDqXTDqTwvdGV4dD4KCTxsaW5lIHgxPSIyMTMiIHkxPSIzNDEiIHgyPSIyOTMiIHkyPSIzNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMTMiIHk9IjM1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yYWlzb24gc29jaWFsZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUElFQ0UgLS0+CjxnIGNsYXNzPSJwYWdlXzBfZTA4MjZmNzUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjQ3OSIgeT0iMjkxIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDc5IiB5PSIzMjEiIHdpZHRoPSI5MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NzkiIHk9IjI5MSIgd2lkdGg9IjkwIiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ3OSIgeTE9IjMyMSIgeDI9IjU2OSIgeTI9IjMyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDk2IiB5PSIzMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QScOIQ0U8L3RleHQ+Cgk8dGV4dCB4PSI0ODciIHk9IjMzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yw6lmLiBwacOoY2U8L3RleHQ+Cgk8bGluZSB4MT0iNDg3IiB5MT0iMzQxIiB4Mj0iNTQ1IiB5Mj0iMzQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDg3IiB5PSIzNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGliZWxsw6kgcGnDqGNlPC90ZXh0Pgo8L2c+Cgo8IS0tIE5vdGVzIC0tPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc2hvd19lMDgyNmY3NShldnQsIHRleHQpIHsKCQl2YXIgcG9zID0gKGV2dC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ5IikgPCAzMzEpID8gImJvdHRvbSIgOiAidG9wIjsKCQl2YXIgbm90ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfbm90ZV9lMDgyNmY3NSIpOwoJCW5vdGUudGV4dENvbnRlbnQgPSB0ZXh0OwoJCW5vdGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfb3ZlcmxheV9lMDgyNmY3NSIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCX0KCWZ1bmN0aW9uIGhpZGVfZTA4MjZmNzUoZXZ0KSB7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9ub3RlX2UwODI2Zjc1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9vdmVybGF5X2UwODI2Zjc1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9ub3RlX2UwODI2Zjc1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9vdmVybGF5X2UwODI2Zjc1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7Cgl9Cl1dPgo8L3NjcmlwdD4KPHJlY3QgaWQ9InRvcF9vdmVybGF5X2UwODI2Zjc1IiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0idG9wX25vdGVfZTA4MjZmNzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM2MyIgeT0iMjQiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8cmVjdCBpZD0iYm90dG9tX292ZXJsYXlfZTA4MjZmNzUiIHg9IjAiIHk9IjMzNiIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNDAiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC43IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHRleHQgaWQ9ImJvdHRvbV9ub3RlX2UwODI2Zjc1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNjMiIHk9IjM2MCIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cela donne un plongement sur une grille $5\\times4$, ce qui est loin d'être optimal. Cependant, l'arrangement organique fournit souvent un bon point de départ pour chercher soi-même une permutation plus esthétique ou mettant en évidence certaines propriétés du MCD.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Arrangement-dans-la-grille-courante\">Arrangement dans la grille courante<a class=\"anchor-link\" href=\"#Arrangement-dans-la-grille-courante\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le réarrangement automatique des boîtes peut s'opérer dans les limites de la grille courante ; c'est-à-dire que le MCD résultant aura (au plus) le même nombre de colonnes et de rangées que le texte de départ (ici, $4\\times5$) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [117]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ../examples/landing --select mcd --seed=2 -t arrange:current\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NDMiIGhlaWdodD0iMjk0IiB2aWV3Qm94PSIwIDAgNzQzIDI5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3NDMiIGhlaWdodD0iMjk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTVBMT1lFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjIyNSIgeTE9IjQ3IiB4Mj0iODYiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI4NiIgeTE9IjE0NyIgeDI9Ijg2IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTMwIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtMTE2IFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTQ0IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTE2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI4IiB5PSIxOCIgd2lkdGg9IjExNiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI4IiB5MT0iNDYiIHgyPSIxNDQiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM2IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVNUExPWUVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTUwIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iOTEiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFRSQVZBSUxMRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNjRjYTcxNDEgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIyMjUiIHkxPSI0NyIgeDI9IjM4OSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjUzNCIgeTE9IjQ3IiB4Mj0iMzg5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDM5IDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtMTI4IFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDUzIDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzM5IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDEyOCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzMjUiIHk9IjE4IiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzI1IiB5MT0iNDYiIHgyPSI0NTMiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMzMiIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5UUkFWQUlMTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjgyIiB5PSIzOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDY1IiB5PSIzOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJFUVVFUklSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzY0Y2E3MTQxIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNTM0IiB5MT0iNDciIHgyPSI2NzQiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI2NzQiIHkxPSIxNDciIHgyPSI2NzQiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik03MTYgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC0xMTIgVjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03MzAgNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg2MzIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjYxOCIgeT0iMTgiIHdpZHRoPSIxMTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI2MTgiIHkxPSI0NiIgeDI9IjczMCIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNjI2IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJFUVXDiVJJUjwvdGV4dD4KCQk8dGV4dCB4PSI2MjUiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF0w6kgcmVxdWlzZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjU4NCIgeT0iNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjY3OSIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzY0Y2E3MTQxIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMjI1IiB5MT0iMjQ3IiB4Mj0iMjI1IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIyNSIgeTE9IjQ3IiB4Mj0iMjI1IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjI1IiBjeT0iMTQ3IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjIxMiIgeT0iMTUxLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyMzAiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjIzMCIgeTE9IjIwMyIgeDI9IjI0OCIgeTI9IjIwMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIwMSIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRElSSUdFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjIyNSIgeTE9IjQ3IiB4Mj0iMzg5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjUzNCIgeTE9IjQ3IiB4Mj0iMzg5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQyMSAxMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTQ2IGgtOTIgVjEzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDM1IDE0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM1NyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE0NiBIOTIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzQzIiB5PSIxMTgiIHdpZHRoPSI5MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM0MyIgeTE9IjE0NiIgeDI9IjQzNSIgeTI9IjE0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1MSIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RElSSUdFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI4MiIgeT0iNzUuNDIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzY0Y2E3MTQxKGV2dCwncmVzcG9uc2FibGUnKSIgb25tb3VzZW91dD0iaGlkZV82NGNhNzE0MShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDY2IiB5PSI3NS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRk9VUk5JUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjUzNCIgeTE9IjQ3IiB4Mj0iNTM0IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjY3NCIgeTE9IjE0NyIgeDI9IjUzNCIgeTI9IjE0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzQiIHkxPSIyNDciIHgyPSI1MzQiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNTcwIDExOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxNDYgaC0xMDAgVjEzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNTg0IDE0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQ5OCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE0NiBIMTAwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQ4NCIgeT0iMTE4IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNDg0IiB5MT0iMTQ2IiB4Mj0iNTg0IiB5Mj0iMTQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNDkyIiB5PSIxMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5GT1VSTklSPC90ZXh0PgoJCTx0ZXh0IHg9IjQ5MSIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF0w6kgZm91cm5pZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUzOSIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI2MDUiIHk9IjE2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNTM5IiB5PSIyMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDT05UUk9MRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNjRjYTcxNDEgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik01MzQgMjQ3IEM0OTUgMjc5IDQ0Ni42NyAyNzkgMzg5IDI0NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwb2x5Z29uIHBvaW50cz0iNDU0LjAxIDI3MC4wOCA0NjYuNjYgMjY1LjYxIDQ2MS45NSAyNzEuMDcgNDY1LjE3IDI3Ny41MiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8cGF0aCBkPSJNNTM0IDI0NyBDNDk1LjY3IDIxNSA0NDcuMzMgMjE1IDM4OSAyNDciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDQwIDIxOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyNDYgaC0xMzAgVjIzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDU0IDI0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDMzOCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI0NiBIMTMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMyNCIgeT0iMjE4IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzI0IiB5MT0iMjQ2IiB4Mj0iNDU0IiB5Mj0iMjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzMxIiB5PSIyMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT05UUsOUTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDU5IiB5PSIyNjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzY0Y2E3MTQxKGV2dCwnbcOocmUnKSIgb25tb3VzZW91dD0iaGlkZV82NGNhNzE0MShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDYwIiB5PSIyNDAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzY0Y2E3MTQxKGV2dCwnZmlsaWFsZScpIiBvbm1vdXNlb3V0PSJoaWRlXzY0Y2E3MTQxKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09NUE9TRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNjRjYTcxNDEgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxwYXRoIGQ9Ik02NzQgMTQ3IEM3MTIuNjcgMTgwLjMzIDcxMi42NyAyMTMuNjcgNjc0IDI0NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik02NzQgMTQ3IEM2MzUuMzMgMTgwLjMzIDYzNS4zMyAyMTMuNjcgNjc0IDI0NyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik03MjAgMjE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjI0NiBoLTEyMCBWMjMyIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03MzQgMjQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINjI4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMjQ2IEgxMjAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNjE0IiB5PSIyMTgiIHdpZHRoPSIxMjAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI2MTQiIHkxPSIyNDYiIHgyPSI3MzQiIHkyPSIyNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI2MjEiIHk9IjIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTVBPU0VSPC90ZXh0PgoJCTx0ZXh0IHg9IjYyMSIgeT0iMjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjY3NyIgeT0iMjAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd182NGNhNzE0MShldnQsJ2NvbXBvc8OpZScpIiBvbm1vdXNlb3V0PSJoaWRlXzY0Y2E3MTQxKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI2NTIiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfNjRjYTcxNDEoZXZ0LCdjb21wb3NhbnRlJykiIG9ubW91c2VvdXQ9ImhpZGVfNjRjYTcxNDEoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRU1QTE9ZRSAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iMTczIiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3MyIgeT0iMzkiIHdpZHRoPSIxMDQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTczIiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE3MyIgeTE9IjM5IiB4Mj0iMjc3IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4MSIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FTVBMT1nDiTwvdGV4dD4KCTx0ZXh0IHg9IjE4MSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bWF0cmljdWxlPC90ZXh0PgoJPGxpbmUgeDE9IjE4MSIgeTE9IjU5IiB4Mj0iMjQwIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxODEiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBlbXBsb3nDqTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzY0Y2E3MTQxIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSI0ODkiIHk9IjkiIHdpZHRoPSI5MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0ODkiIHk9IjM5IiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDg5IiB5PSI5IiB3aWR0aD0iOTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDg5IiB5MT0iMzkiIHgyPSI1NzkiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDk4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0pFVDwvdGV4dD4KCTx0ZXh0IHg9IjQ5NyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBwcm9qZXQ8L3RleHQ+Cgk8bGluZSB4MT0iNDk3IiB5MT0iNTkiIHgyPSI1NzEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ5NyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHByb2pldDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREVQQVJURU1FTlQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNjRjYTcxNDEgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjEwOSIgd2lkdGg9IjE1NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMzkiIHdpZHRoPSIxNTQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTA5IiB3aWR0aD0iMTU0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIxMzkiIHgyPSIxNjMiIHkyPSIxMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ew4lQQVJURU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gZMOpcGFydGVtZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMTU5IiB4Mj0iMTMyIiB5Mj0iMTU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjE3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQSUVDRSAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNjI5IiB5PSIxMDkiIHdpZHRoPSI5MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI2MjkiIHk9IjEzOSIgd2lkdGg9IjkwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjYyOSIgeT0iMTA5IiB3aWR0aD0iOTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNjI5IiB5MT0iMTM5IiB4Mj0iNzE5IiB5Mj0iMTM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI2NDYiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBJw4hDRTwvdGV4dD4KCTx0ZXh0IHg9IjYzNyIgeT0iMTU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnLDqWYuIHBpw6hjZTwvdGV4dD4KCTxsaW5lIHgxPSI2MzciIHkxPSIxNTkiIHgyPSI2OTUiIHkyPSIxNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI2MzciIHk9IjE3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWJlbGzDqSBwacOoY2U8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFZQU5UX0RST0lUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzY0Y2E3MTQxIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIxNTUiIHk9IjIwOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTUiIHk9IjIzOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTUiIHk9IjIwOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNTUiIHkxPSIyMzkiIHgyPSIyOTUiIHkyPSIyMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE2MyIgeT0iMjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QVlBTlQtRFJPSVQ8L3RleHQ+Cgk8dGV4dCB4PSIxNjMiIHk9IjI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gYXlhbnQtZHJvaXQ8L3RleHQ+Cgk8bGluZSB4MT0iMTYzIiB5MT0iMjU5IiB4Mj0iMjY0IiB5Mj0iMjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iMTYzIiB5PSIyNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGllbjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgU09DSUVURSAtLT4KPGcgY2xhc3M9InBhZ2VfMF82NGNhNzE0MSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNDgzIiB5PSIyMDkiIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDgzIiB5PSIyMzkiIHdpZHRoPSIxMDIiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDgzIiB5PSIyMDkiIHdpZHRoPSIxMDIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDgzIiB5MT0iMjM5IiB4Mj0iNTg1IiB5Mj0iMjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0OTQiIHk9IjIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNPQ0nDiVTDiTwvdGV4dD4KCTx0ZXh0IHg9IjQ5MSIgeT0iMjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gc29jacOpdMOpPC90ZXh0PgoJPGxpbmUgeDE9IjQ5MSIgeTE9IjI1OSIgeDI9IjU3MSIgeTI9IjI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ5MSIgeT0iMjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnJhaXNvbiBzb2NpYWxlPC90ZXh0Pgo8L2c+Cgo8IS0tIE5vdGVzIC0tPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc2hvd182NGNhNzE0MShldnQsIHRleHQpIHsKCQl2YXIgcG9zID0gKGV2dC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ5IikgPCAyNDkpID8gImJvdHRvbSIgOiAidG9wIjsKCQl2YXIgbm90ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfbm90ZV82NGNhNzE0MSIpOwoJCW5vdGUudGV4dENvbnRlbnQgPSB0ZXh0OwoJCW5vdGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfb3ZlcmxheV82NGNhNzE0MSIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCX0KCWZ1bmN0aW9uIGhpZGVfNjRjYTcxNDEoZXZ0KSB7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9ub3RlXzY0Y2E3MTQxIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9vdmVybGF5XzY0Y2E3MTQxIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9ub3RlXzY0Y2E3MTQxIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9vdmVybGF5XzY0Y2E3MTQxIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7Cgl9Cl1dPgo8L3NjcmlwdD4KPHJlY3QgaWQ9InRvcF9vdmVybGF5XzY0Y2E3MTQxIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0idG9wX25vdGVfNjRjYTcxNDEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3MSIgeT0iMjQiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8cmVjdCBpZD0iYm90dG9tX292ZXJsYXlfNjRjYTcxNDEiIHg9IjAiIHk9IjI1NCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNDAiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC43IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHRleHQgaWQ9ImJvdHRvbV9ub3RlXzY0Y2E3MTQxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNzEiIHk9IjI3OCIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Arrangement-en-privil%C3%A9giant-la-largeur\">Arrangement en privilégiant la largeur<a class=\"anchor-link\" href=\"#Arrangement-en-privil%C3%A9giant-la-largeur\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans un document paginé, on cherche en général à utiliser en priorité l'espace horizontal. La version 4.0 introduit à cet effet une option de réarrangement « en largeur d'abord ». Le MCD d'accueil s'y prête particulièrement bien :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [118]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ../examples/landing --select mcd --seed=2 -t arrange:wide=8 --scale 0.8\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MjAiIGhlaWdodD0iMTYxIiB2aWV3Qm94PSIwIDAgOTIwIDE2MSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI5MjAiIGhlaWdodD0iMTYxIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSI2MyIgeTE9IjM5IiB4Mj0iMTU4IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIyOTAiIHkxPSIzOSIgeDI9IjE1OCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIxNTgiIGN5PSIzOSIgcj0iMTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIxNDgiIHk9IjQzLjUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEyMyIgeT0iNTEuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSIxMjMiIHkxPSI1My4yIiB4Mj0iMTM4IiB5Mj0iNTMuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iMjI5IiB5PSI1MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIERJUklHRVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSIyOTAiIHkxPSIzOSIgeDI9IjQxMiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iNTMyIiB5MT0iMzkiIHgyPSI0MTIiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTQzNy44IDE1IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWMzggaC03NCBWMjYuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik00NDkgMzggdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIMzg2LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjM4IEg3NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNzUiIHk9IjE1IiB3aWR0aD0iNzQiIGhlaWdodD0iNDgiIGZpbGw9Im5vbmUiIHJ4PSIxMS4yIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPGxpbmUgeDE9IjM3NSIgeTE9IjM4IiB4Mj0iNDQ5IiB5Mj0iMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSIzODEiIHk9IjMyLjc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+RElSSUdFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMzNiIgeT0iMzIuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiIG9ubW91c2VvdmVyPSJzaG93XzZmZWE5OTQ1KGV2dCwncmVzcG9uc2FibGUnKSIgb25tb3VzZW91dD0iaGlkZV82ZmVhOTk0NShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDc3IiB5PSIzMi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEZPVVJOSVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSI1MzIiIHkxPSIzOSIgeDI9IjYzNiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iNjM2IiB5MT0iMTIyIiB4Mj0iNjM2IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSI3NDQiIHkxPSIzOSIgeDI9IjYzNiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8Zz4KCQk8cGF0aCBkPSJNNjY0LjggMTUgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYzOCBoLTgwIFYyNi4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTY3NiAzOCB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEg2MDcuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMzggSDgwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjU5NiIgeT0iMTUiIHdpZHRoPSI4MCIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iNTk2IiB5MT0iMzgiIHgyPSI2NzYiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjYwMiIgeT0iMzIuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5GT1VSTklSPC90ZXh0PgoJCTx0ZXh0IHg9IjYwMiIgeT0iNTMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+cXTDqSBmb3VybmllPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNTcyIiB5PSI1MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNjQwIiB5PSI4My42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNjg1IiB5PSI1MS42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTlRST0xFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF82ZmVhOTk0NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPHBhdGggZD0iTTc0NCAzOSBDNzc0IDEzLjY3IDgxMi42NyAxMy42NyA4NjAgMzkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxwb2x5Z29uIHBvaW50cz0iODA2Ljk5IDIwLjcxIDc5Ni44OCAyNC4zMiA4MDAuNjQgMTkuOTQgNzk4LjA1IDE0Ljc5IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxwYXRoIGQ9Ik03NDQgMzkgQzc3NCA2NC4zMyA4MTIuNjcgNjQuMzMgODYwIDM5IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8Zz4KCQk8cGF0aCBkPSJNOTAxLjggMTUgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAxMS4yIFYzOCBoLTEwNiBWMjYuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik05MTMgMzggdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBIODE4LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjM4IEgxMDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iODA3IiB5PSIxNSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iODA3IiB5MT0iMzgiIHgyPSI5MTMiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTx0ZXh0IHg9IjgxNCIgeT0iMzIuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5DT05UUsOUTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNzg4IiB5PSIzMy42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCIgb25tb3VzZW92ZXI9InNob3dfNmZlYTk5NDUoZXZ0LCdtw6hyZScpIiBvbm1vdXNlb3V0PSJoaWRlXzZmZWE5OTQ1KGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSI3ODgiIHk9IjUwLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44IiBvbm1vdXNlb3Zlcj0ic2hvd182ZmVhOTk0NShldnQsJ2ZpbGlhbGUnKSIgb25tb3VzZW91dD0iaGlkZV82ZmVhOTk0NShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEVNUExPWUVSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzZmZWE5OTQ1IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMjkwIiB5MT0iMzkiIHgyPSIyOTAiIHkyPSIxMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxsaW5lIHgxPSIxNTgiIHkxPSIxMjIiIHgyPSIyOTAiIHkyPSIxMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zMjUuOCA5OCBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjEyMSBoLTk0IFYxMDkuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zMzcgMTIxIHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDI1NC4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxMjEgSDk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI0MyIgeT0iOTgiIHdpZHRoPSI5NCIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iMjQzIiB5MT0iMTIxIiB4Mj0iMzM3IiB5Mj0iMTIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iMjUwIiB5PSIxMTUuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5FTVBMT1lFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI3MSIgeT0iODMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjIyNCIgeT0iMTM0LjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVFJBVkFJTExFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF82ZmVhOTk0NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjI5MCIgeTE9IjM5IiB4Mj0iNDEyIiB5Mj0iMTIyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8bGluZSB4MT0iNTMyIiB5MT0iMzkiIHgyPSI0MTIiIHkyPSIxMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik00NTIuOCA5OCBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjEyMSBoLTEwNCBWMTA5LjIgYTExLjIgMTEuMiA5MCAwIDEgMTEuMiAtMTEuMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDY0IDEyMSB2MTMuOCBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAxMS4yIEgzNzEuMiBhMTEuMiAxMS4yIDkwIDAgMSAtMTEuMiAtMTEuMiBWMTIxIEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzYwIiB5PSI5OCIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iMzYwIiB5MT0iMTIxIiB4Mj0iNDY0IiB5Mj0iMTIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iMzY3IiB5PSIxMTUuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5UUkFWQUlMTEVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzM2IiB5PSI2NS4zNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjQ3NyIgeT0iNjEuNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gUkVRVUVSSVIgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxsaW5lIHgxPSI1MzIiIHkxPSIzOSIgeDI9IjUzMiIgeTI9IjEyMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGxpbmUgeDE9IjYzNiIgeTE9IjEyMiIgeDI9IjUzMiIgeTI9IjEyMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPGc+CgkJPHBhdGggZD0iTTU2NS44IDk4IGExMS4yIDExLjIgOTAgMCAxIDExLjIgMTEuMiBWMTIxIGgtOTAgVjEwOS4yIGExMS4yIDExLjIgOTAgMCAxIDExLjIgLTExLjIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTU3NyAxMjEgdjEzLjggYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgMTEuMiBINDk4LjIgYTExLjIgMTEuMiA5MCAwIDEgLTExLjIgLTExLjIgVjEyMSBIOTAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDg3IiB5PSI5OCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjQ4IiBmaWxsPSJub25lIiByeD0iMTEuMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJCTxsaW5lIHgxPSI0ODciIHkxPSIxMjEiIHgyPSI1NzciIHkyPSIxMjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8dGV4dCB4PSI0OTMiIHk9IjExNS43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPlJFUVXDiVJJUjwvdGV4dD4KCQk8dGV4dCB4PSI0OTMiIHk9IjEzNi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5xdMOpIHJlcXVpc2U8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI1MzYiIHk9IjgzLjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOC44Ij4xLE48L3RleHQ+Cgk8dGV4dCB4PSI1ODEiIHk9IjEzNC42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTVBPU0VSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzZmZWE5OTQ1IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8cGF0aCBkPSJNNjM2IDEyMiBDNjYzLjMzIDk2LjY3IDY5OS4zMyA5Ni42NyA3NDQgMTIyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8cGF0aCBkPSJNNjM2IDEyMiBDNjYzLjMzIDE0Ny4zMyA2OTkuMzMgMTQ3LjMzIDc0NCAxMjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiLz4KCTxnPgoJCTxwYXRoIGQ9Ik03ODEuOCA5OCBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIDExLjIgVjEyMSBoLTk4IFYxMDkuMiBhMTEuMiAxMS4yIDkwIDAgMSAxMS4yIC0xMS4yIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik03OTMgMTIxIHYxMy44IGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIDExLjIgSDcwNi4yIGExMS4yIDExLjIgOTAgMCAxIC0xMS4yIC0xMS4yIFYxMjEgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjY5NSIgeT0iOTgiIHdpZHRoPSI5OCIgaGVpZ2h0PSI0OCIgZmlsbD0ibm9uZSIgcng9IjExLjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCQk8bGluZSB4MT0iNjk1IiB5MT0iMTIxIiB4Mj0iNzkzIiB5Mj0iMTIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+CgkJPHRleHQgeD0iNzAyIiB5PSIxMTUuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5DT01QT1NFUjwvdGV4dD4KCQk8dGV4dCB4PSI3MDEiIHk9IjEzNi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5xdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2NzYiIHk9IjExNi42IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjguOCIgb25tb3VzZW92ZXI9InNob3dfNmZlYTk5NDUoZXZ0LCdjb21wb3PDqWUnKSIgb25tb3VzZW91dD0iaGlkZV82ZmVhOTk0NShldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNjc2IiB5PSIxMzMuNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI4LjgiIG9ubW91c2VvdmVyPSJzaG93XzZmZWE5OTQ1KGV2dCwnY29tcG9zYW50ZScpIiBvbm1vdXNlb3V0PSJoaWRlXzZmZWE5OTQ1KGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFZQU5UX0RST0lUIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzZmZWE5OTQ1IGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSI3IiB5PSI3IiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjciIHk9IjMyIiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjciIHk9IjciIHdpZHRoPSIxMTIiIGhlaWdodD0iNjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNyIgeTE9IjMyIiB4Mj0iMTE5IiB5Mj0iMzIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9IjE0IiB5PSIyNC43NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE0LjQiPkFZQU5ULURST0lUPC90ZXh0PgoJPHRleHQgeD0iMTMiIHk9IjQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm5vbSBheWFudC1kcm9pdDwvdGV4dD4KCTxsaW5lIHgxPSIxMyIgeTE9IjQ4LjYiIHgyPSI5NCIgeTI9IjQ4LjYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjgiIHN0cm9rZS1kYXNoYXJyYXk9IjMuMiIvPgoJPHRleHQgeD0iMTMiIHk9IjYwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPmxpZW48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVNUExPWUUgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjI0OCIgeT0iNyIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0OCIgeT0iMzIiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzOSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNDgiIHk9IjciIHdpZHRoPSI4NCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNDgiIHkxPSIzMiIgeDI9IjMzMiIgeTI9IjMyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSIyNTUiIHk9IjI0Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+RU1QTE9Zw4k8L3RleHQ+Cgk8dGV4dCB4PSIyNTQiIHk9IjQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm1hdHJpY3VsZTwvdGV4dD4KCTxsaW5lIHgxPSIyNTQiIHkxPSI0OC42IiB4Mj0iMzAxIiB5Mj0iNDguNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iMjU0IiB5PSI2MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5ub20gZW1wbG95w6k8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF82ZmVhOTk0NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNDk2IiB5PSI3IiB3aWR0aD0iNzIiIGhlaWdodD0iMjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDk2IiB5PSIzMiIgd2lkdGg9IjcyIiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5NiIgeT0iNyIgd2lkdGg9IjcyIiBoZWlnaHQ9IjY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ5NiIgeTE9IjMyIiB4Mj0iNTY4IiB5Mj0iMzIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz4KCTwvZz4KCTx0ZXh0IHg9IjUwMyIgeT0iMjQuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5QUk9KRVQ8L3RleHQ+Cgk8dGV4dCB4PSI1MDIiIHk9IjQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm51bS4gcHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjUwMiIgeTE9IjQ4LjYiIHgyPSI1NjEiIHkyPSI0OC42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSI1MDIiIHk9IjYwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTIiPm5vbSBwcm9qZXQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNPQ0lFVEUgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjcwNCIgeT0iNyIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjcwNCIgeT0iMzIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzOSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI3MDQiIHk9IjciIHdpZHRoPSI4MCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI3MDQiIHkxPSIzMiIgeDI9Ijc4NCIgeTI9IjMyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIi8+Cgk8L2c+Cgk8dGV4dCB4PSI3MTIiIHk9IjI0Ljc1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTQuNCI+U09DScOJVMOJPC90ZXh0PgoJPHRleHQgeD0iNzEwIiB5PSI0Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5udW0uIHNvY2nDqXTDqTwvdGV4dD4KCTxsaW5lIHgxPSI3MTAiIHkxPSI0OC42IiB4Mj0iNzc0IiB5Mj0iNDguNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iNzEwIiB5PSI2MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5yYWlzb24gc29jaWFsZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREVQQVJURU1FTlQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNmZlYTk5NDUgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9Ijk2IiB5PSI5MCIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIyNSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NiIgeT0iMTE1IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjM5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijk2IiB5PSI5MCIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI2NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5NiIgeTE9IjExNSIgeDI9IjIyMCIgeTI9IjExNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iMTAzIiB5PSIxMDcuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5Ew4lQQVJURU1FTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxMDIiIHk9IjEyOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5udW0uIGTDqXBhcnRlbWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxMDIiIHkxPSIxMzEuNiIgeDI9IjE5NCIgeTI9IjEzMS42IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC44Ii8+Cgk8dGV4dCB4PSIxMDIiIHk9IjE0My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5ub20gZMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQSUVDRSAtLT4KPGcgY2xhc3M9InBhZ2VfMF82ZmVhOTk0NSBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNjAwIiB5PSI5MCIgd2lkdGg9IjcyIiBoZWlnaHQ9IjI1IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjYwMCIgeT0iMTE1IiB3aWR0aD0iNzIiIGhlaWdodD0iMzkiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNjAwIiB5PSI5MCIgd2lkdGg9IjcyIiBoZWlnaHQ9IjY0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yIiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjYwMCIgeTE9IjExNSIgeDI9IjY3MiIgeTI9IjExNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMiIvPgoJPC9nPgoJPHRleHQgeD0iNjE0IiB5PSIxMDcuNzUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNC40Ij5QScOIQ0U8L3RleHQ+Cgk8dGV4dCB4PSI2MDYiIHk9IjEyOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEyIj5yw6lmLiBwacOoY2U8L3RleHQ+Cgk8bGluZSB4MT0iNjA2IiB5MT0iMTMxLjYiIHgyPSI2NTMiIHkyPSIxMzEuNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOCIvPgoJPHRleHQgeD0iNjA2IiB5PSIxNDMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMiI+bGliZWxsw6kgcGnDqGNlPC90ZXh0Pgo8L2c+Cgo8IS0tIE5vdGVzIC0tPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc2hvd182ZmVhOTk0NShldnQsIHRleHQpIHsKCQl2YXIgcG9zID0gKGV2dC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ5IikgPCAxMjUpID8gImJvdHRvbSIgOiAidG9wIjsKCQl2YXIgbm90ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfbm90ZV82ZmVhOTk0NSIpOwoJCW5vdGUudGV4dENvbnRlbnQgPSB0ZXh0OwoJCW5vdGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfb3ZlcmxheV82ZmVhOTk0NSIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCX0KCWZ1bmN0aW9uIGhpZGVfNmZlYTk5NDUoZXZ0KSB7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9ub3RlXzZmZWE5OTQ1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9vdmVybGF5XzZmZWE5OTQ1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9ub3RlXzZmZWE5OTQ1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9vdmVybGF5XzZmZWE5OTQ1Iikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7Cgl9Cl1dPgo8L3NjcmlwdD4KPHJlY3QgaWQ9InRvcF9vdmVybGF5XzZmZWE5OTQ1IiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIzMiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0idG9wX25vdGVfNmZlYTk5NDUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ2MCIgeT0iMTkuMiIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMi44IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHJlY3QgaWQ9ImJvdHRvbV9vdmVybGF5XzZmZWE5OTQ1IiB4PSIwIiB5PSIxMjkiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjMyIiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuNyIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjx0ZXh0IGlkPSJib3R0b21fbm90ZV82ZmVhOTk0NSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDYwIiB5PSIxNDguMiIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMi44IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ici, l'utilisateur a demandé $8$ boîtes en largeur (c'est aussi la valeur par défaut). L'algorithme commence par calculer le nombre de lignes minimal correspondant, sachant qu'il a $14$ boîtes à placer : c'est $\\lceil14/8\\rceil=2$. Il cherche donc un plongement sur une grille $8\\times2$.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Arrangement-dans-une-grille-%C3%A9quilibr%C3%A9e-minimale\">Arrangement dans une grille équilibrée minimale<a class=\"anchor-link\" href=\"#Arrangement-dans-une-grille-%C3%A9quilibr%C3%A9e-minimale\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>On peut chercher à faire tenir le MCD dans la plus petite grille possible, tout en maintenant entre hauteur et largeur un rapport « équilibré » (ou proche du <a href=\"https://fr.wikipedia.org/wiki/Nombre_d%27or\">nombre d'or</a>). Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles:</p>\n<ul>\n<li>$13\\times1$;</li>\n<li>$7\\times2$, ce qui laisse 1 case vide;</li>\n<li>$5\\times3$, ce qui laisse 2 cases vides;</li>\n<li>$4\\times4$, ce qui laisse 3 cases vides;</li>\n<li>etc.</li>\n</ul>\n<p>Les deux premières grilles étant non équilibrées, on retiendra la plus petite des suivantes, de dimensions $5\\times3$.</p>\n<p>La table ci-dessous énumère les dimensions des grilles minimales d'équilibre supérieur à 0,5 pour tous les MCD comportant moins de 100 boîtes. On peut y vérifier par exemple que le MCD de taille 13 (en gras) se trouve effectivement aux coordonnées (5, 3).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:center\"></th>\n<th style=\"text-align:center\"><strong>1</strong></th>\n<th style=\"text-align:center\"><strong>2</strong></th>\n<th style=\"text-align:center\"><strong>3</strong></th>\n<th style=\"text-align:center\"><strong>4</strong></th>\n<th style=\"text-align:center\"><strong>5</strong></th>\n<th style=\"text-align:center\"><strong>6</strong></th>\n<th style=\"text-align:center\"><strong>7</strong></th>\n<th style=\"text-align:center\"><strong>8</strong></th>\n<th style=\"text-align:center\"><strong>9</strong></th>\n<th style=\"text-align:center\"><strong>10</strong></th>\n<th style=\"text-align:center\"><strong>11</strong></th>\n<th style=\"text-align:center\"><strong>12</strong></th>\n<th style=\"text-align:center\"><strong>13</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><strong>1</strong></td>\n<td style=\"text-align:center\">1</td>\n<td style=\"text-align:center\">2</td>\n<td style=\"text-align:center\">3</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>2</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">4</td>\n<td style=\"text-align:center\">5, 6</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>3</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">7, 8, 9</td>\n<td style=\"text-align:center\">10, 11, 12</td>\n<td style=\"text-align:center\"><strong>13</strong>, 14, 15</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>4</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">16</td>\n<td style=\"text-align:center\">17, 18, 19, 20</td>\n<td style=\"text-align:center\">21, 22, 23, 24</td>\n<td style=\"text-align:center\">26, 27, 28</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>5</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">25</td>\n<td style=\"text-align:center\">29, 30</td>\n<td style=\"text-align:center\">31, 32, 33, 34, 35</td>\n<td style=\"text-align:center\">37, 38, 39, 40</td>\n<td style=\"text-align:center\">43, 44, 45</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>6</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">36</td>\n<td style=\"text-align:center\">41, 42</td>\n<td style=\"text-align:center\">46, 47, 48</td>\n<td style=\"text-align:center\">50, 51, 52, 53, 54</td>\n<td style=\"text-align:center\">57, 58, 59, 60</td>\n<td style=\"text-align:center\">65, 66</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>7</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">49</td>\n<td style=\"text-align:center\">55, 56</td>\n<td style=\"text-align:center\">61, 62, 63</td>\n<td style=\"text-align:center\">67, 68, 69, 70</td>\n<td style=\"text-align:center\">73, 74, 75, 76, 77</td>\n<td style=\"text-align:center\">82, 83, 84</td>\n<td style=\"text-align:center\">91</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>8</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">64</td>\n<td style=\"text-align:center\">71, 72</td>\n<td style=\"text-align:center\">78, 79, 80</td>\n<td style=\"text-align:center\">85, 86, 87, 88</td>\n<td style=\"text-align:center\">92, 93, 94, 95, 96</td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>9</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">81</td>\n<td style=\"text-align:center\">89, 90</td>\n<td style=\"text-align:center\">97, 98, 99</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><strong>10</strong></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\">100</td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n<td style=\"text-align:center\"></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le MCD d'accueil ayant déjà été arrangé avec l'option <code>-t arrange:balanced</code>, nous ne le reproduisons pas ici. Sachez cependant qu'au cas où, pour une raison ou une autre, la plus petite grille équilibrée ne convient pas, il est possible de passer à la $i^\\text{e}$ suivante en mettant $i$ en sous-sous-argument. Ici, pour $14$ boîtes, <code>balanced=1</code> permet donc de passer de la grille $5\\times3$ (prévue pour $13$, $14$ et $15$ boîtes) à la grille $4\\times4$ (prévue pour $16$ boîtes).</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [119]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ../examples/landing --select mcd --seed=1 -t arrange:balanced=1\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MTMiIGhlaWdodD0iMzY3IiB2aWV3Qm94PSIwIDAgNjEzIDM2NyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MTMiIGhlaWdodD0iMzY3IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBFTVBMT1lFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjQ3IiB4Mj0iODYiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI4NiIgeTE9IjEzOCIgeDI9Ijg2IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTMwIDE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ2IGgtMTE2IFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTQ0IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBIMTE2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI4IiB5PSIxOCIgd2lkdGg9IjExNiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI4IiB5MT0iNDYiIHgyPSIxNDQiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM2IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVNUExPWUVSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTgxIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iOTEiIHk9IjkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iNTM0IiB5MT0iNDciIHgyPSIzOTUiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNTYiIHkxPSI0NyIgeDI9IjM5NSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMzk1IiBjeT0iNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMzgyIiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDQxIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjQ0MSIgeTE9IjY1IiB4Mj0iNDU5IiB5Mj0iNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMTMiIHk9IjM5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVFJBVkFJTExFUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjQ3IiB4Mj0iMjU2IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM5NSIgeTE9IjIyOSIgeDI9IjI1NiIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zMDYgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTEyOCBWMTIzIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zMjAgMTM3IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjA2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTM3IEgxMjgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTkyIiB5PSIxMDkiIHdpZHRoPSIxMjgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxOTIiIHkxPSIxMzciIHgyPSIzMjAiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxOTkiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRSQVZBSUxMRVI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyMzIiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMzI2IiB5PSIyMTAuNTEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBESVJJR0VSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMjU2IiB5MT0iNDciIHgyPSIzOTUiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzk1IiB5MT0iMjI5IiB4Mj0iMzk1IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQyNyAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtOTIgVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDQxIDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM2MyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEzNyBIOTIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzQ5IiB5PSIxMDkiIHdpZHRoPSI5MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM0OSIgeTE9IjEzNyIgeDI9IjQ0MSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1NyIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RElSSUdFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMxMyIgeT0iNzguMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIG9ubW91c2VvdmVyPSJzaG93XzQ0OWY0MjMzKGV2dCwncmVzcG9uc2FibGUnKSIgb25tb3VzZW91dD0iaGlkZV80NDlmNDIzMyhldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCxOPC90ZXh0PgoJPHRleHQgeD0iNDAwIiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVFVRVJJUiAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGxpbmUgeDE9IjM5NSIgeTE9IjIyOSIgeDI9IjI1NiIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNTYiIHkxPSIzMjAiIHgyPSIyNTYiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjk4IDIwMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMjggaC0xMTIgVjIxNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzEyIDIyOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIxNCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOCBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjIwMCIgeT0iMjAwIiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMjAwIiB5MT0iMjI4IiB4Mj0iMzEyIiB5Mj0iMjI4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMjA4IiB5PSIyMjEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SRVFVw4lSSVI8L3RleHQ+CgkJPHRleHQgeD0iMjA3IiB5PSIyNDYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXTDqSByZXF1aXNlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzI2IiB5PSIyNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI2MSIgeT0iMjc0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09OVFJPTEVSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8cGF0aCBkPSJNNTM0IDMyMCBDNDk1LjMzIDI4My42NyA0OTUuMzMgMjUzLjMzIDUzNCAyMjkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8cG9seWdvbiBwb2ludHM9IjUwNy4xMyAyNTcuOTkgNTA4LjY1IDI3MS4zMiA1MDQuMzkgMjY1LjUxIDQ5Ny4zOCAyNjcuMjEiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPHBhdGggZD0iTTUzNCAzMjAgQzU3MS4zMyAyODMuNjcgNTcxLjMzIDI1My4zMyA1MzQgMjI5IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTU4NSAyMDAgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjI4IGgtMTMwIFYyMTQgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTU5OSAyMjggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0ODMgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYyMjggSDEzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI0NjkiIHk9IjIwMCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQ2OSIgeTE9IjIyOCIgeDI9IjU5OSIgeTI9IjIyOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQ3NiIgeT0iMjIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q09OVFLDlExFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUxMiIgeT0iMjc0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd180NDlmNDIzMyhldnQsJ23DqHJlJykiIG9ubW91c2VvdXQ9ImhpZGVfNDQ5ZjQyMzMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjUzNyIgeT0iMjc0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd180NDlmNDIzMyhldnQsJ2ZpbGlhbGUnKSIgb25tb3VzZW91dD0iaGlkZV80NDlmNDIzMyhldnQpIiBzdHlsZT0iY3Vyc29yOiBwb2ludGVyOyI+MCwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENPTVBPU0VSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8cGF0aCBkPSJNMjU2IDMyMCBDMjMzLjMzIDM1MiAxNzYuNjcgMzUyIDg2IDMyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwYXRoIGQ9Ik0yNTYgMzIwIEMyMzMuMzMgMjg4IDE3Ni42NyAyODggODYgMzIwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTEzMiAyOTEgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzE5IGgtMTIwIFYzMDUgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTE0NiAzMTkgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjMxOSBIMTIwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI2IiB5PSIyOTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyNiIgeTE9IjMxOSIgeDI9IjE0NiIgeTI9IjMxOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMzIiB5PSIzMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01QT1NFUjwvdGV4dD4KCQk8dGV4dCB4PSIzMyIgeT0iMzM3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF1YW50aXTDqTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE4NyIgeT0iMzM1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBvbm1vdXNlb3Zlcj0ic2hvd180NDlmNDIzMyhldnQsJ2NvbXBvc8OpZScpIiBvbm1vdXNlb3V0PSJoaWRlXzQ0OWY0MjMzKGV2dCkiIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7Ij4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxODciIHk9IjMxMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgb25tb3VzZW92ZXI9InNob3dfNDQ5ZjQyMzMoZXZ0LCdjb21wb3NhbnRlJykiIG9ubW91c2VvdXQ9ImhpZGVfNDQ5ZjQyMzMoZXZ0KSIgc3R5bGU9ImN1cnNvcjogcG9pbnRlcjsiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBGT1VSTklSIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8bGluZSB4MT0iMzk1IiB5MT0iMjI5IiB4Mj0iMzk1IiB5Mj0iMzIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjMyMCIgeDI9IjM5NSIgeTI9IjMyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1MzQiIHkxPSIzMjAiIHgyPSIzOTUiIHkyPSIzMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDMxIDI5MSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzMTkgaC0xMDAgVjMwNSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDQ1IDMxOSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM1OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjMxOSBIMTAwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM0NSIgeT0iMjkxIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzQ1IiB5MT0iMzE5IiB4Mj0iNDQ1IiB5Mj0iMzE5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzUzIiB5PSIzMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5GT1VSTklSPC90ZXh0PgoJCTx0ZXh0IHg9IjM1MiIgeT0iMzM3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF0w6kgZm91cm5pZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjQwMCIgeT0iMjgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzMDYiIHk9IjMzNiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNDU5IiB5PSIzMzYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRU1QTE9ZRSAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iMjA0IiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIwNCIgeT0iMzkiIHdpZHRoPSIxMDQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjA0IiB5PSI5IiB3aWR0aD0iMTA0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIwNCIgeTE9IjM5IiB4Mj0iMzA4IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIxMiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FTVBMT1nDiTwvdGV4dD4KCTx0ZXh0IHg9IjIxMiIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bWF0cmljdWxlPC90ZXh0PgoJPGxpbmUgeDE9IjIxMiIgeTE9IjU5IiB4Mj0iMjcxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMTIiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBlbXBsb3nDqTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQVlBTlRfRFJPSVQgLS0+CjxnIGNsYXNzPSJwYWdlXzBfNDQ5ZjQyMzMgZGlhZ3JhbV9wYWdlIiB2aXNpYmlsaXR5PSJ2aXNpYmxlIj4KCTxnPgoJCTxyZWN0IHg9IjQ2NCIgeT0iOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NjQiIHk9IjM5IiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ2NCIgeT0iOSIgd2lkdGg9IjE0MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0NjQiIHkxPSIzOSIgeDI9IjYwNCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0NzIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QVlBTlQtRFJPSVQ8L3RleHQ+Cgk8dGV4dCB4PSI0NzIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBheWFudC1kcm9pdDwvdGV4dD4KCTxsaW5lIHgxPSI0NzIiIHkxPSI1OSIgeDI9IjU3MyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgoJPHRleHQgeD0iNDcyIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWVuPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBERVBBUlRFTUVOVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTAwIiB3aWR0aD0iMTU0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjEzMCIgd2lkdGg9IjE1NCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxMDAiIHdpZHRoPSIxNTQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjEzMCIgeDI9IjE2MyIgeTI9IjEzMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjEyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkTDiVBBUlRFTUVOVDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBkw6lwYXJ0ZW1lbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIxNTAiIHgyPSIxMzIiIHkyPSIxNTAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBkw6lwYXJ0ZW1lbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iMzUwIiB5PSIxOTEiIHdpZHRoPSI5MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTAiIHk9IjIyMSIgd2lkdGg9IjkwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM1MCIgeT0iMTkxIiB3aWR0aD0iOTAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzUwIiB5MT0iMjIxIiB4Mj0iNDQwIiB5Mj0iMjIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNTkiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0pFVDwvdGV4dD4KCTx0ZXh0IHg9IjM1OCIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gcHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjM1OCIgeTE9IjI0MSIgeDI9IjQzMiIgeTI9IjI0MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM1OCIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBwcm9qZXQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBJRUNFIC0tPgo8ZyBjbGFzcz0icGFnZV8wXzQ0OWY0MjMzIGRpYWdyYW1fcGFnZSIgdmlzaWJpbGl0eT0idmlzaWJsZSI+Cgk8Zz4KCQk8cmVjdCB4PSIyMTEiIHk9IjI4MiIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxMSIgeT0iMzEyIiB3aWR0aD0iOTAiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjExIiB5PSIyODIiIHdpZHRoPSI5MCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMTEiIHkxPSIzMTIiIHgyPSIzMDEiIHkyPSIzMTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyOCIgeT0iMzAzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEnDiENFPC90ZXh0PgoJPHRleHQgeD0iMjE5IiB5PSIzMjkuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gcGnDqGNlPC90ZXh0PgoJPGxpbmUgeDE9IjIxOSIgeTE9IjMzMiIgeDI9IjI3NyIgeTI9IjMzMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIxOSIgeT0iMzQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpYmVsbMOpIHBpw6hjZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgU09DSUVURSAtLT4KPGcgY2xhc3M9InBhZ2VfMF80NDlmNDIzMyBkaWFncmFtX3BhZ2UiIHZpc2liaWxpdHk9InZpc2libGUiPgoJPGc+CgkJPHJlY3QgeD0iNDgzIiB5PSIyODIiIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDgzIiB5PSIzMTIiIHdpZHRoPSIxMDIiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDgzIiB5PSIyODIiIHdpZHRoPSIxMDIiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDgzIiB5MT0iMzEyIiB4Mj0iNTg1IiB5Mj0iMzEyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0OTQiIHk9IjMwMy4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNPQ0nDiVTDiTwvdGV4dD4KCTx0ZXh0IHg9IjQ5MSIgeT0iMzI5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gc29jacOpdMOpPC90ZXh0PgoJPGxpbmUgeDE9IjQ5MSIgeTE9IjMzMiIgeDI9IjU3MSIgeTI9IjMzMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ5MSIgeT0iMzQ2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnJhaXNvbiBzb2NpYWxlPC90ZXh0Pgo8L2c+Cgo8IS0tIE5vdGVzIC0tPgo8c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+CjwhW0NEQVRBWwoJZnVuY3Rpb24gc2hvd180NDlmNDIzMyhldnQsIHRleHQpIHsKCQl2YXIgcG9zID0gKGV2dC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ5IikgPCAzMjIpID8gImJvdHRvbSIgOiAidG9wIjsKCQl2YXIgbm90ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfbm90ZV80NDlmNDIzMyIpOwoJCW5vdGUudGV4dENvbnRlbnQgPSB0ZXh0OwoJCW5vdGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAidmlzaWJsZSIpOwoJCWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBvcyArICJfb3ZlcmxheV80NDlmNDIzMyIpLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ2aXNpYmlsaXR5IiwgInZpc2libGUiKTsKCX0KCWZ1bmN0aW9uIGhpZGVfNDQ5ZjQyMzMoZXZ0KSB7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9ub3RlXzQ0OWY0MjMzIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInRvcF9vdmVybGF5XzQ0OWY0MjMzIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9ub3RlXzQ0OWY0MjMzIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CgkJZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJvdHRvbV9vdmVybGF5XzQ0OWY0MjMzIikuc2V0QXR0cmlidXRlTlMobnVsbCwgInZpc2liaWxpdHkiLCAiaGlkZGVuIik7Cgl9Cl1dPgo8L3NjcmlwdD4KPHJlY3QgaWQ9InRvcF9vdmVybGF5XzQ0OWY0MjMzIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI0MCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjciIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8dGV4dCBpZD0idG9wX25vdGVfNDQ5ZjQyMzMiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMwNiIgeT0iMjQiIGZpbGw9IiNGRkZGRkYiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTYiIHZpc2liaWxpdHk9ImhpZGRlbiIvPgo8cmVjdCBpZD0iYm90dG9tX292ZXJsYXlfNDQ5ZjQyMzMiIHg9IjAiIHk9IjMyNyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNDAiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC43IiB2aXNpYmlsaXR5PSJoaWRkZW4iLz4KPHRleHQgaWQ9ImJvdHRvbV9ub3RlXzQ0OWY0MjMzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMDYiIHk9IjM1MSIgZmlsbD0iI0ZGRkZGRiIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxNiIgdmlzaWJpbGl0eT0iaGlkZGVuIi8+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Limitations-de-la-m%C3%A9thode-exacte\">Limitations de la méthode exacte<a class=\"anchor-link\" href=\"#Limitations-de-la-m%C3%A9thode-exacte\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le réarrangement exact ne fonctionnera jamais sur les MCD non planaires ou n'admettant aucun plongement planaire dans les limites de la grille spécifiée (par les sous-options <code>current</code>, <code>wide</code> ou <code>balanced</code>).</p>\n<p>Rappelons qu'un graphe est dit <a href=\"https://fr.wikipedia.org/wiki/Graphe_planaire\">planaire</a> lorsqu'il en existe au moins un arrangement sans croisement. Le graphe non planaire comportant le plus petit nombre de liens est connu sous le doux nom de <a href=\"https://www.rodhilton.com/2011/10/29/why-the-complete-bipartite-graph-k33-is-not-planar/\">$K_{3,3}$</a> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [120]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nDIGNISSIM: nec sem, nunc, vulputate\nIMPERDIET: a praesent, nibh, semper\nTINCIDUNT: faucibus, orci, cursus\n\nRHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\nSODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\nQUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MjYiIGhlaWdodD0iMTk0IiB2aWV3Qm94PSIwIDAgNDI2IDE5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MjYiIGhlaWdodD0iMTk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSSE9OQ1VTIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NiIgeTE9IjU2IiB4Mj0iNjYiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjExIiB5MT0iNTYiIHgyPSI2NiIgeTI9IjE1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNTgiIHkxPSI1NiIgeDI9IjY2IiB5Mj0iMTU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTEwNiAxMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTU1IGgtMTA4IFYxNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTEyMCAxNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyNiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE1NSBIMTA4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEyIiB5PSIxMjciIHdpZHRoPSIxMDgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMiIgeTE9IjE1NSIgeDI9IjEyMCIgeTI9IjE1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE5IiB5PSIxNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SSE9OQ1VTPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDIiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTI4IiB5PSI5My45NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjc1IiB5PSI3MC44OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFNPREFMRVMgLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTYiIHgyPSIyMTEiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjExIiB5MT0iNTYiIHgyPSIyMTEiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzU4IiB5MT0iNTYiIHgyPSIyMTEiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQ4IDEyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxNTUgaC0xMDIgVjE0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjYyIDE1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3NCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE1NSBIMTAyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE2MCIgeT0iMTI3IiB3aWR0aD0iMTAyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTYwIiB5MT0iMTU1IiB4Mj0iMjYyIiB5Mj0iMTU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTY4IiB5PSIxNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TT0RBTEVTPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTI4IiB5PSI5Mi41NyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjE2IiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI3NSIgeT0iOTMuMzQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBRVUlTX0VOSU0gLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTYiIHgyPSIzNTgiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjExIiB5MT0iNTYiIHgyPSIzNTgiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzU4IiB5MT0iNTYiIHgyPSIzNTgiIHkyPSIxNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDAwIDEyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxNTUgaC0xMTIgVjE0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDE0IDE1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDMxNiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE1NSBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMwMiIgeT0iMTI3IiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzAyIiB5MT0iMTU1IiB4Mj0iNDE0IiB5Mj0iMTU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzA5IiB5PSIxNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5RVUlTIEVOSU08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9IjcwLjE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNzUiIHk9IjkzLjM0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzNjMiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBESUdOSVNTSU0gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjEyMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ESUdOSVNTSU08L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bmVjIHNlbTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNjkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW5jPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij52dWxwdXRhdGU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElNUEVSRElFVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNTIiIHk9IjkiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTUyIiB5PSIzOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTIiIHk9IjkiIHdpZHRoPSIxMTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTUyIiB5MT0iMzkiIHgyPSIyNzAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTYxIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPklNUEVSRElFVDwvdGV4dD4KCTx0ZXh0IHg9IjE2MCIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YSBwcmFlc2VudDwvdGV4dD4KCTxsaW5lIHgxPSIxNjAiIHkxPSI1OSIgeDI9IjIyNSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTYwIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uaWJoPC90ZXh0PgoJPHRleHQgeD0iMTYwIiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2VtcGVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSU5DSURVTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjk5IiB5PSI5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5OSIgeT0iMzkiIHdpZHRoPSIxMTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjk5IiB5PSI5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI5OSIgeTE9IjM5IiB4Mj0iNDE3IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMwNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5USU5DSURVTlQ8L3RleHQ+Cgk8dGV4dCB4PSIzMDciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmZhdWNpYnVzPC90ZXh0PgoJPGxpbmUgeDE9IjMwNyIgeTE9IjU5IiB4Mj0iMzU3IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMDciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm9yY2k8L3RleHQ+Cgk8dGV4dCB4PSIzMDciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jdXJzdXM8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Son réarrangement par <em>Branch &amp; bound</em> échouera donc nécessairement :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [121]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --seed=1 -t arrange:balanced\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.9 - Impossible de calculer un plongement planaire satisfaisant la contrainte\ndonnée.</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme on voit, Mocodo ne cherche pas à savoir si la non-planarité est intrinsèque au graphe, ou résulte des dimensions de la grille imposée pour le plongement. Pour en avoir le cœur net, tentez un arrangement non contraint :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [122]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --seed=1 -t arrange\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.41 - Impossible de calculer un plongement planaire.</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme exact (<em>Branch and Bound</em>) :</p>\n<ul>\n<li><code>call_limit</code> : nombre maximal d'appels pour une boîte de départ donnée (défaut: <code>10000</code>).</li>\n<li><code>min_objective</code> : meilleur objectif esthétique pour la mise en page (défaut: <code>0</code>).</li>\n<li><code>max_objective</code> : pire objectif esthétique pour la mise en page (défaut: <code>15</code>).</li>\n</ul>\n<p>Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"M%C3%A9thode-heuristique-(algorithme-g%C3%A9n%C3%A9tique)\">Méthode heuristique (algorithme génétique)<a class=\"anchor-link\" href=\"#M%C3%A9thode-heuristique-(algorithme-g%C3%A9n%C3%A9tique)\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans tous les cas où la méthode exacte ne produit pas de résultat satisfaisant, on pourra se rabattre sur une heuristique qui, au lieu d'interdire les croisements, cherchera simplement à en minimiser le nombre.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [123]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --seed=1 -t arrange:algo=ga\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTgiIGhlaWdodD0iMjMwIiB2aWV3Qm94PSIwIDAgNDE4IDIzMCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTgiIGhlaWdodD0iMjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSSE9OQ1VTIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NiIgeTE9IjU2IiB4Mj0iMjA2IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzUwIiB5MT0iNTYiIHgyPSIyMDYiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMDYiIHkxPSIxNzQiIHgyPSIyMDYiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDYgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMDggVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjAgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNjYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTA4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE1MiIgeT0iMjciIHdpZHRoPSIxMDgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTIiIHkxPSI1NSIgeDI9IjI2MCIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTU5IiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJIT05DVVM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9IjQ4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNjciIHk9IjQ4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTEiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFNPREFMRVMgLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTYiIHgyPSI2NiIgeTI9IjE3NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNTAiIHkxPSI1NiIgeDI9IjY2IiB5Mj0iMTc0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIwNiIgeTE9IjE3NCIgeDI9IjY2IiB5Mj0iMTc0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTEwMyAxNDUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTczIGgtMTAyIFYxNTkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTExNyAxNzMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyOSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE3MyBIMTAyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE1IiB5PSIxNDUiIHdpZHRoPSIxMDIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNSIgeTE9IjE3MyIgeDI9IjExNyIgeTI9IjE3MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIzIiB5PSIxNjYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TT0RBTEVTPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNDIiIHk9IjExOSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjY3IiB5PSI3NS43NyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTIzIiB5PSIxOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBRVUlTX0VOSU0gLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTYiIHgyPSIzNTAiIHkyPSIxNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzUwIiB5MT0iNTYiIHgyPSIzNTAiIHkyPSIxNzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjA2IiB5MT0iMTc0IiB4Mj0iMzUwIiB5Mj0iMTc0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM5MiAxNDUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTczIGgtMTEyIFYxNTkgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQwNiAxNzMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzMDggYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNzMgSDExMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyOTQiIHk9IjE0NSIgd2lkdGg9IjExMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjI5NCIgeTE9IjE3MyIgeDI9IjQwNiIgeTI9IjE3MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMwMSIgeT0iMTY2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UVVJUyBFTklNPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTI4IiB5PSI3NC45NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMzU1IiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI3MCIgeT0iMTkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERJR05JU1NJTSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTIzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRJR05JU1NJTTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uZWMgc2VtPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI2OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bmM8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnZ1bHB1dGF0ZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgSU1QRVJESUVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI5MSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyOTEiIHk9IjM5IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5MSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyOTEiIHkxPSIzOSIgeDI9IjQwOSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMDAiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SU1QRVJESUVUPC90ZXh0PgoJPHRleHQgeD0iMjk5IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hIHByYWVzZW50PC90ZXh0PgoJPGxpbmUgeDE9IjI5OSIgeTE9IjU5IiB4Mj0iMzY0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyOTkiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5pYmg8L3RleHQ+Cgk8dGV4dCB4PSIyOTkiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5zZW1wZXI8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFRJTkNJRFVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNDciIHk9IjEyNyIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNDciIHk9IjE1NyIgd2lkdGg9IjExOCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNDciIHk9IjEyNyIgd2lkdGg9IjExOCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNDciIHkxPSIxNTciIHgyPSIyNjUiIHkyPSIxNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE1NSIgeT0iMTQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VElOQ0lEVU5UPC90ZXh0PgoJPHRleHQgeD0iMTU1IiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZmF1Y2lidXM8L3RleHQ+Cgk8bGluZSB4MT0iMTU1IiB5MT0iMTc3IiB4Mj0iMjA1IiB5Mj0iMTc3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTU1IiB5PSIxOTEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+b3JjaTwvdGV4dD4KCTx0ZXh0IHg9IjE1NSIgeT0iMjA4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jdXJzdXM8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox.mcd\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>%%mocodo --seed=1\nDIGNISSIM: nec sem, nunc, vulputate\nRHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\nIMPERDIET: a praesent, nibh, semper\n\nSODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\nTINCIDUNT: faucibus, orci, cursus\nQUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'amélioration ne saute pas forcément aux yeux, mais il n'y a plus que trois croisements au lieu de neuf. Ce plongement constitue en tout cas un bon point de départ pour un réarrangement manuel. Il ne reste en effet plus qu'à insérer quelques boîtes invisibles:</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [124]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nRHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n\nDIGNISSIM: nec sem, nunc, vulputate\n:::\nIMPERDIET: a praesent, nibh, semper\n\nSODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n:::\nQUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n\nTINCIDUNT: faucibus, orci, cursus\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0ODQiIGhlaWdodD0iMzM2IiB2aWV3Qm94PSIwIDAgNDg0IDMzNiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0ODQiIGhlaWdodD0iMzM2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSSE9OQ1VTIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NiIgeTE9IjEwOSIgeDI9IjI0MCIgeTI9IjM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQxNiIgeTE9IjEwOSIgeDI9IjI0MCIgeTI9IjM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI0MCIgeTE9IjI4MCIgeDI9IjI0MCIgeTI9IjM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI4MCA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjM3IGgtMTA4IFYyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjk0IDM3IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjAwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzcgSDEwOCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxODYiIHk9IjkiIHdpZHRoPSIxMDgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxODYiIHkxPSIzNyIgeDI9IjI5NCIgeTI9IjM3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTkzIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJIT05DVVM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9Ijk4LjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzMzMiIHk9Ijk4LjA0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDUiIHk9IjIyNSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFNPREFMRVMgLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iMTA5IiB4Mj0iNjYiIHkyPSIyMDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNDE2IiB5MT0iMTA5IiB4Mj0iNjYiIHkyPSIyMDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjQwIiB5MT0iMjgwIiB4Mj0iNjYiIHkyPSIyMDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTAzIDE4MCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMDggaC0xMDIgVjE5NCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTE3IDIwOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDI5IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMjA4IEgxMDIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTUiIHk9IjE4MCIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE1IiB5MT0iMjA4IiB4Mj0iMTE3IiB5Mj0iMjA4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMjMiIHk9IjIwMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNPREFMRVM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0MiIgeT0iMTcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzMzMiIHk9IjEyMC4wNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTU3IiB5PSIyNjguNzMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBRVUlTX0VOSU0gLS0+CjxnPgoJPGxpbmUgeDE9IjY2IiB5MT0iMTA5IiB4Mj0iNDE2IiB5Mj0iMjA5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQxNiIgeTE9IjEwOSIgeDI9IjQxNiIgeTI9IjIwOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNDAiIHkxPSIyODAiIHgyPSI0MTYiIHkyPSIyMDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDU4IDE4MCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYyMDggaC0xMTIgVjE5NCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDcyIDIwOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM3NCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIwOCBIMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjM2MCIgeT0iMTgwIiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzYwIiB5MT0iMjA4IiB4Mj0iNDcyIiB5Mj0iMjA4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzY3IiB5PSIyMDEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5RVUlTIEVOSU08L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMjgiIHk9IjExOS41IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI0MjEiIHk9IjE3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMzA0IiB5PSIyNjkuMDQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRElHTklTU0lNIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjYyIiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkyIiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjYyIiB3aWR0aD0iMTE0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSI5MiIgeDI9IjEyMyIgeTI9IjkyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iODMuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ESUdOSVNTSU08L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTA5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5lYyBzZW08L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIxMTIiIHgyPSI2OSIgeTI9IjExMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSIxMjYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVuYzwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNDMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnZ1bHB1dGF0ZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgSU1QRVJESUVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM1NyIgeT0iNjIiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU3IiB5PSI5MiIgd2lkdGg9IjExOCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTciIHk9IjYyIiB3aWR0aD0iMTE4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM1NyIgeTE9IjkyIiB4Mj0iNDc1IiB5Mj0iOTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM2NiIgeT0iODMuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JTVBFUkRJRVQ8L3RleHQ+Cgk8dGV4dCB4PSIzNjUiIHk9IjEwOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hIHByYWVzZW50PC90ZXh0PgoJPGxpbmUgeDE9IjM2NSIgeTE9IjExMiIgeDI9IjQzMCIgeTI9IjExMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM2NSIgeT0iMTI2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5pYmg8L3RleHQ+Cgk8dGV4dCB4PSIzNjUiIHk9IjE0MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2VtcGVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUSU5DSURVTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTgxIiB5PSIyMzMiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgxIiB5PSIyNjMiIHdpZHRoPSIxMTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgxIiB5PSIyMzMiIHdpZHRoPSIxMTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTgxIiB5MT0iMjYzIiB4Mj0iMjk5IiB5Mj0iMjYzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjI1NC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRJTkNJRFVOVDwvdGV4dD4KCTx0ZXh0IHg9IjE4OSIgeT0iMjgwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmZhdWNpYnVzPC90ZXh0PgoJPGxpbmUgeDE9IjE4OSIgeTE9IjI4MyIgeDI9IjIzOSIgeTI9IjI4MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4OSIgeT0iMjk3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm9yY2k8L3RleHQ+Cgk8dGV4dCB4PSIxODkiIHk9IjMxNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y3Vyc3VzPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme génétique :</p>\n<ul>\n<li><code>population_size</code> : nombre d'individus à faire évoluer (défaut: <code>1000</code>).</li>\n<li><code>crossover_rate</code> : taux de croisement, entre 0 et 1 (défaut: <code>0.9</code>).</li>\n<li><code>mutation_rate</code> : taux de mutation, entre 0 et 1 (défaut: <code>0.06</code>).</li>\n<li><code>sample_size</code> : taille de l'échantillon pour les tournois (défaut: <code>7</code>).</li>\n<li><code>max_generations</code> : nombre maximal de générations (défaut: <code>300</code>).</li>\n<li><code>plateau</code> : nombre maximal de générations consécutives sans amélioration (défaut: <code>30</code>).</li>\n</ul>\n<p>Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Am%C3%A9lioration-du-plongement\">Amélioration du plongement<a class=\"anchor-link\" href=\"#Am%C3%A9lioration-du-plongement\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Une entité liée à de nombreuses associations peut limiter ou même empêcher les possibilités de réarrangement sans croisements.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Par-duplication-d'entit%C3%A9s-r%C3%A9duites-%C3%A0-leur-identifiant\">Par duplication d'entités réduites à leur identifiant<a class=\"anchor-link\" href=\"#Par-duplication-d'entit%C3%A9s-r%C3%A9duites-%C3%A0-leur-identifiant\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Lorsque cette entité est indépendante et réduite à son identifiant, elle est vouée à disparaître lors du passage au relationnel. Il n'y a donc aucun inconvénient à en créer plusieurs, et cela peut avoir l'avantage de faciliter (ou même de rendre possible) l'obtention d'une bonne mise en page.</p>\n<p>Prenons comme exemple un MCD extrait d'une <a href=\"https://fsmrel.developpez.com/basesrelationnelles/ullman-cthrsg/\">étude de François de Sainte Marie</a>, et présenté comme suit :</p>\n<p><img alt=\"\" src=\"examples/ullman_cthrsg_mcd_sans_cif_80.png\"/></p>\n<p>Le graphe sous-jacent étant non planaire, des croisements sont inévitables (ici entre certaines pattes des associations SHR, CT et THR). Cependant, cette non-planarité résulte elle-même de la mise en jeu d'une même entité Période dans quatre associations triples. La monnayer en quatre entités Période numérotées augmente l'ordre du graphe, mais le rend planaire, le tout sans impact sur le schéma relationnel :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [125]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nÉtudiant: id. étudiant, nom étudiant\n:\n:\nSHR, 0N Période3, 0N Salle, 0N Étudiant\nPériode3: heure\n\n:\nCSG, 0N Niveau, 1N Cours, 1N Étudiant\nNiveau: niveau\n:\n\nCHS, 0N Période2, 0N Cours, 0N Étudiant\nCours: id. cours, nom cours\nCHR, 0N Période4, 0N Salle, 0N Cours\nSalle: id. salle, nom salle\n\nPériode2: heure\nCT, 11 Cours, 1N Professeur\nPériode4: heure\n:\n:\n\n:\nProfesseur: id. professeur, nom professeur\n:\nTHR, 0N Période1, 0N Salle, 0N Professeur\nPériode1: heure\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MDQiIGhlaWdodD0iNDYxIiB2aWV3Qm94PSIwIDAgNTA0IDQ2MSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1MDQiIGhlaWdodD0iNDYxIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBTSFIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ1MSIgeTE9IjQ3IiB4Mj0iMzUxIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzUxIiB5MT0iMjMwIiB4Mj0iMzUxIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTkiIHkxPSI0NyIgeDI9IjM1MSIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM2NCAxOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFY0NiBoLTU0IFYzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzc4IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzM4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNDYgSDU0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMyNCIgeT0iMTgiIHdpZHRoPSI1NCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjMyNCIgeTE9IjQ2IiB4Mj0iMzc4IiB5Mj0iNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzMzEiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U0hSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzgzIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMzU2IiB5PSIxODQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjExNCIgeT0iMzkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDU0cgLS0+CjxnPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjEzOCIgeDI9IjE1NyIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNTciIHkxPSIyMzAiIHgyPSIxNTciIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTkiIHkxPSI0NyIgeDI9IjE1NyIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0xNzAgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTU0IFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTE4NCAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNDQgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDU0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEzMCIgeT0iMTA5IiB3aWR0aD0iNTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMzAiIHkxPSIxMzciIHgyPSIxODQiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMzgiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNTRzwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5MiIgeT0iMTU0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxNjIiIHk9IjE4NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iODIuNjIiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENIUyAtLT4KPGc+Cgk8bGluZSB4MT0iNTkiIHkxPSIzMjIiIHgyPSI1OSIgeTI9IjIzMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNTciIHkxPSIyMzAiIHgyPSI1OSIgeTI9IjIzMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1OSIgeTE9IjQ3IiB4Mj0iNTkiIHkyPSIyMzAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNzIgMjAxIGExNCAxNCA5MCAwIDEgMTQgMTQgVjIyOSBoLTU0IFYyMTUgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTg2IDIyOSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQ2IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMjI5IEg1NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzMiIgeT0iMjAxIiB3aWR0aD0iNTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzMiIgeTE9IjIyOSIgeDI9Ijg2IiB5Mj0iMjI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzkiIHk9IjIyMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNIUzwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjY0IiB5PSIyODQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjkxIiB5PSIyNDYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM1IiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDSFIgLS0+CjxnPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjMyMiIgeDI9IjI1NiIgeTI9IjIzMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNTEiIHkxPSIyMzAiIHgyPSIyNTYiIHkyPSIyMzAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMTU3IiB5MT0iMjMwIiB4Mj0iMjU2IiB5Mj0iMjMwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI3MCAyMDEgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjI5IGgtNTYgVjIxNSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjg0IDIyOSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDI0MiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjIyOSBINTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjI4IiB5PSIyMDEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjIyOCIgeTE9IjIyOSIgeDI9IjI4NCIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIzNiIgeT0iMjIyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0hSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjYxIiB5PSIyODQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjI4OSIgeT0iMjQ2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMDQiIHk9IjI0NiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENUIC0tPgo8Zz4KCTxsaW5lIHgxPSIxNTciIHkxPSIyMzAiIHgyPSIxNTciIHkyPSIzMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMTU3IiB5MT0iNDE0IiB4Mj0iMTU3IiB5Mj0iMzIyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE2MyAyOTMgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzIxIGgtNDAgVjMwNyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTc3IDMyMSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE1MSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjMyMSBINDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTM3IiB5PSIyOTMiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEzNyIgeTE9IjMyMSIgeDI9IjE3NyIgeTI9IjMyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE0NSIgeT0iMzE0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q1Q8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNjIiIHk9IjI4NCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMTYyIiB5PSIzNjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBUSFIgLS0+CjxnPgoJPGxpbmUgeDE9IjQ1MSIgeTE9IjQxNCIgeDI9IjM1MSIgeTI9IjQxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNTEiIHkxPSIyMzAiIHgyPSIzNTEiIHkyPSI0MTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMTU3IiB5MT0iNDE0IiB4Mj0iMzUxIiB5Mj0iNDE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM2NCAzODUgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDEzIGgtNTQgVjM5OSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMzc4IDQxMyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDMzOCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjQxMyBINTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzI0IiB5PSIzODUiIHdpZHRoPSI1NCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjMyNCIgeTE9IjQxMyIgeDI9IjM3OCIgeTI9IjQxMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjMzMiIgeT0iNDA2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VEhSPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzgzIiB5PSI0MzAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM1NiIgeT0iMjg0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyMjQiIHk9IjQzMCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFVFVESUFOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTA5IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsOJdHVkaWFudDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gw6l0dWRpYW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI4NyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSDDqXR1ZGlhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBFUklPREUzIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQwNyIgeT0iMTciIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MDciIHk9IjQ3IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDA3IiB5PSIxNyIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQwNyIgeTE9IjQ3IiB4Mj0iNDk1IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQxNSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qw6lyaW9kZTwvdGV4dD4KCTx0ZXh0IHg9IjQxNSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aGV1cmU8L3RleHQ+Cgk8bGluZSB4MT0iNDE1IiB5MT0iNjciIHgyPSI0NTIiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgTklWRUFVIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIxNiIgeT0iMTA4IiB3aWR0aD0iODAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjE2IiB5PSIxMzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTYiIHk9IjEwOCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIxNiIgeTE9IjEzOCIgeDI9IjI5NiIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjI1IiB5PSIxMjkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5OaXZlYXU8L3RleHQ+Cgk8dGV4dCB4PSIyMjQiIHk9IjE1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uaXZlYXU8L3RleHQ+Cgk8bGluZSB4MT0iMjI0IiB5MT0iMTU4IiB4Mj0iMjY0IiB5Mj0iMTU4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBDT1VSUyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMTUiIHk9IjE5MiIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjExNSIgeT0iMjIyIiB3aWR0aD0iODQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTE1IiB5PSIxOTIiIHdpZHRoPSI4NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMTUiIHkxPSIyMjIiIHgyPSIxOTkiIHkyPSIyMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEyOCIgeT0iMjEzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q291cnM8L3RleHQ+Cgk8dGV4dCB4PSIxMjMiIHk9IjIzOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gY291cnM8L3RleHQ+Cgk8bGluZSB4MT0iMTIzIiB5MT0iMjQyIiB4Mj0iMTc3IiB5Mj0iMjQyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTIzIiB5PSIyNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGNvdXJzPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTQUxMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMTMiIHk9IjE5MiIgd2lkdGg9Ijc2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMxMyIgeT0iMjIyIiB3aWR0aD0iNzYiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzEzIiB5PSIxOTIiIHdpZHRoPSI3NiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMTMiIHkxPSIyMjIiIHgyPSIzODkiIHkyPSIyMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMyNSIgeT0iMjEzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U2FsbGU8L3RleHQ+Cgk8dGV4dCB4PSIzMjEiIHk9IjIzOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gc2FsbGU8L3RleHQ+Cgk8bGluZSB4MT0iMzIxIiB5MT0iMjQyIiB4Mj0iMzY3IiB5Mj0iMjQyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzIxIiB5PSIyNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHNhbGxlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQRVJJT0RFMiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNSIgeT0iMjkyIiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTUiIHk9IjMyMiIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE1IiB5PSIyOTIiIHdpZHRoPSI4OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNSIgeTE9IjMyMiIgeDI9IjEwMyIgeTI9IjMyMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjMiIHk9IjMxMy4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlDDqXJpb2RlPC90ZXh0PgoJPHRleHQgeD0iMjMiIHk9IjMzOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5oZXVyZTwvdGV4dD4KCTxsaW5lIHgxPSIyMyIgeTE9IjM0MiIgeDI9IjYwIiB5Mj0iMzQyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBQRVJJT0RFNCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMTIiIHk9IjI5MiIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxMiIgeT0iMzIyIiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjEyIiB5PSIyOTIiIHdpZHRoPSI4OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMTIiIHkxPSIzMjIiIHgyPSIzMDAiIHkyPSIzMjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyMCIgeT0iMzEzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UMOpcmlvZGU8L3RleHQ+Cgk8dGV4dCB4PSIyMjAiIHk9IjMzOS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5oZXVyZTwvdGV4dD4KCTxsaW5lIHgxPSIyMjAiIHkxPSIzNDIiIHgyPSIyNTciIHkyPSIzNDIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFBST0ZFU1NFVVIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOTUiIHk9IjM3NiIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NSIgeT0iNDA2IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijk1IiB5PSIzNzYiIHdpZHRoPSIxMjQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOTUiIHkxPSI0MDYiIHgyPSIyMTkiIHkyPSI0MDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjEwMyIgeT0iMzk3LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZmVzc2V1cjwvdGV4dD4KCTx0ZXh0IHg9IjEwMyIgeT0iNDIzLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlkLiBwcm9mZXNzZXVyPC90ZXh0PgoJPGxpbmUgeDE9IjEwMyIgeTE9IjQyNiIgeDI9IjE4OSIgeTI9IjQyNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjEwMyIgeT0iNDQwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBwcm9mZXNzZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQRVJJT0RFMSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0MDciIHk9IjM4NCIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQwNyIgeT0iNDE0IiB3aWR0aD0iODgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDA3IiB5PSIzODQiIHdpZHRoPSI4OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0MDciIHkxPSI0MTQiIHgyPSI0OTUiIHkyPSI0MTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQxNSIgeT0iNDA1LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UMOpcmlvZGU8L3RleHQ+Cgk8dGV4dCB4PSI0MTUiIHk9IjQzMS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5oZXVyZTwvdGV4dD4KCTxsaW5lIHgxPSI0MTUiIHkxPSI0MzQiIHgyPSI0NTIiIHkyPSI0MzQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>CHR</strong> (<u>heure</u>, <u><em>#id. salle</em></u>, <u><em>#id. cours</em></u>)</li>\n<li><strong>CHS</strong> (<u>heure</u>, <u><em>#id. cours</em></u>, <u><em>#id. étudiant</em></u>)</li>\n<li><strong>Cours</strong> (<u>id. cours</u>, nom cours, <em>#id. professeur</em>)</li>\n<li><strong>CSG</strong> (<u>niveau</u>, <u><em>#id. cours</em></u>, <u><em>#id. étudiant</em></u>)</li>\n<li><strong>Étudiant</strong> (<u>id. étudiant</u>, nom étudiant)</li>\n<li><strong>Professeur</strong> (<u>id. professeur</u>, nom professeur)</li>\n<li><strong>Salle</strong> (<u>id. salle</u>, nom salle)</li>\n<li><strong>SHR</strong> (<u>heure</u>, <u><em>#id. salle</em></u>, <u><em>#id. étudiant</em></u>)</li>\n<li><strong>THR</strong> (<u>heure</u>, <u><em>#id. salle</em></u>, <u><em>#id. professeur</em></u>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ce genre de problème (et sa solution) se présente typiquement lorsqu'une entité DATE réduite à un identifiant <em>date</em> est associée à un grand nombre d'entités n'ayant rien à voir entre elles.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Par-suppression-de-ces-m%C3%AAmes-entit%C3%A9s\">Par suppression de ces mêmes entités<a class=\"anchor-link\" href=\"#Par-suppression-de-ces-m%C3%AAmes-entit%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Inversement, toujours étant donné que ce type d'entité est destiné à disparaître lors du passage au relationnel, on peut décider de les supprimer par anticipation. Pour cela, il faut accepter que les associations puissent être porteuses d'identifiants (ce qui n'est pas prévu par Merise). Cela permet d'obtenir un schéma conceptuel beaucoup plus lisible, toujours sans impact sur le schéma relationnel :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [126]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nCSG, 1N Cours, 1N Étudiant: _niveau\n:\nCours: id. cours, nom cours\nCT, 11 Cours, 1N Professeur\n\n:\nCHS, 0N Cours, 0N Étudiant: _heure\nCHR, 0N Salle, 0N Cours: _heure\nProfesseur: id. professeur, nom professeur\n    \nÉtudiant: id. étudiant, nom étudiant\nSHR, 0N Salle, 0N Étudiant: _heure\nSalle: id. salle, nom salle\nTHR, 0N Salle, 0N Professeur: _heure\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NDkiIGhlaWdodD0iMjk0IiB2aWV3Qm94PSIwIDAgNDQ5IDI5NCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NDkiIGhlaWdodD0iMjk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBDU0cgLS0+CjxnPgoJPGxpbmUgeDE9IjI1OSIgeTE9IjQ3IiB4Mj0iNTkiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1OSIgeTE9IjI0NyIgeDI9IjU5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNzIgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC01NCBWMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTg2IDQ2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NiBINTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzIiIHk9IjE4IiB3aWR0aD0iNTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzMiIgeTE9IjQ2IiB4Mj0iODYiIHkyPSI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQwIiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNTRzwvdGV4dD4KCQk8dGV4dCB4PSIzOSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bml2ZWF1PC90ZXh0PgoJCTxsaW5lIHgxPSIzOSIgeTE9IjY3IiB4Mj0iNzkiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTwvZz4KCTx0ZXh0IHg9IjE5MyIgeT0iMzkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM1IiB5PSIyMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDVCAtLT4KPGc+Cgk8bGluZSB4MT0iMjU5IiB5MT0iNDciIHgyPSIzNzgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNzgiIHkxPSIxNDciIHgyPSIzNzgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zODQgMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDYgaC00MCBWMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTM5OCA0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM3MiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjQ2IEg0MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNTgiIHk9IjE4IiB3aWR0aD0iNDAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzNTgiIHkxPSI0NiIgeDI9IjM5OCIgeTI9IjQ2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMzY2IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNUPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzA2IiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMzgzIiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDSFMgLS0+CjxnPgoJPGxpbmUgeDE9IjI1OSIgeTE9IjQ3IiB4Mj0iMTY1IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU5IiB5MT0iMjQ3IiB4Mj0iMTY1IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE3OCAxMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTQ2IGgtNTQgVjEzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMTkyIDE0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE1MiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE0NiBINTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTM4IiB5PSIxMTgiIHdpZHRoPSI1NCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEzOCIgeTE9IjE0NiIgeDI9IjE5MiIgeTI9IjE0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE0NSIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0hTPC90ZXh0PgoJCTx0ZXh0IHg9IjE0NSIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhldXJlPC90ZXh0PgoJCTxsaW5lIHgxPSIxNDUiIHkxPSIxNjciIHgyPSIxODIiIHkyPSIxNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8L2c+Cgk8dGV4dCB4PSIyMjEuNTIiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iODIuMDYiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIENIUiAtLT4KPGc+Cgk8bGluZSB4MT0iMjU5IiB5MT0iMjQ3IiB4Mj0iMjU5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI1OSIgeTE9IjQ3IiB4Mj0iMjU5IiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI3MyAxMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTQ2IGgtNTYgVjEzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjg3IDE0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDI0NSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjE0NiBINTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMjMxIiB5PSIxMTgiIHdpZHRoPSI1NiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjIzMSIgeTE9IjE0NiIgeDI9IjI4NyIgeTI9IjE0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIzOSIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0hSPC90ZXh0PgoJCTx0ZXh0IHg9IjIzOCIgeT0iMTY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhldXJlPC90ZXh0PgoJCTxsaW5lIHgxPSIyMzgiIHkxPSIxNjciIHgyPSIyNzUiIHkyPSIxNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjQiIHk9IjIwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMjY0IiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBTSFIgLS0+CjxnPgoJPGxpbmUgeDE9IjI1OSIgeTE9IjI0NyIgeDI9IjE2NSIgeTI9IjI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1OSIgeTE9IjI0NyIgeDI9IjE2NSIgeTI9IjI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0xNzggMjE4IGExNCAxNCA5MCAwIDEgMTQgMTQgVjI0NiBoLTU0IFYyMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTE5MiAyNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNTIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYyNDYgSDU0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEzOCIgeT0iMjE4IiB3aWR0aD0iNTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMzgiIHkxPSIyNDYiIHgyPSIxOTIiIHkyPSIyNDYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNDUiIHk9IjIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlNIUjwvdGV4dD4KCQk8dGV4dCB4PSIxNDUiIHk9IjI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5oZXVyZTwvdGV4dD4KCQk8bGluZSB4MT0iMTQ1IiB5MT0iMjY3IiB4Mj0iMTgyIiB5Mj0iMjY3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPC9nPgoJPHRleHQgeD0iMTk3IiB5PSIyNjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjExNCIgeT0iMjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVEhSIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNTkiIHkxPSIyNDciIHgyPSIzNzgiIHkyPSIyNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzc4IiB5MT0iMTQ3IiB4Mj0iMzc4IiB5Mj0iMjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM5MSAyMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjQ2IGgtNTQgVjIzMiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDA1IDI0NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM2NSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjI0NiBINTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzUxIiB5PSIyMTgiIHdpZHRoPSI1NCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM1MSIgeTE9IjI0NiIgeDI9IjQwNSIgeTI9IjI0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM1OSIgeT0iMjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VEhSPC90ZXh0PgoJCTx0ZXh0IHg9IjM1OCIgeT0iMjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhldXJlPC90ZXh0PgoJCTxsaW5lIHgxPSIzNTgiIHkxPSIyNjciIHgyPSIzOTUiIHkyPSIyNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8L2c+Cgk8dGV4dCB4PSIzMDIiIHk9IjI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMzgzIiB5PSIyMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09VUlMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjE3IiB5PSI5IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjE3IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxNyIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIxNyIgeTE9IjM5IiB4Mj0iMzAxIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIzMCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db3VyczwvdGV4dD4KCTx0ZXh0IHg9IjIyNSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGNvdXJzPC90ZXh0PgoJPGxpbmUgeDE9IjIyNSIgeTE9IjU5IiB4Mj0iMjc5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMjUiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBjb3VyczwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRkVTU0VVUiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMTYiIHk9IjEwOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMTYiIHk9IjEzOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMTYiIHk9IjEwOSIgd2lkdGg9IjEyNCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMTYiIHkxPSIxMzkiIHgyPSI0NDAiIHkyPSIxMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMyNCIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvZmVzc2V1cjwvdGV4dD4KCTx0ZXh0IHg9IjMyNCIgeT0iMTU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlkLiBwcm9mZXNzZXVyPC90ZXh0PgoJPGxpbmUgeDE9IjMyNCIgeTE9IjE1OSIgeDI9IjQxMCIgeTI9IjE1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMyNCIgeT0iMTczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBwcm9mZXNzZXVyPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFVFVESUFOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIyMDkiIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMjM5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIwOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMjM5IiB4Mj0iMTA5IiB5Mj0iMjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+w4l0dWRpYW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gw6l0dWRpYW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMjU5IiB4Mj0iODciIHkyPSIyNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSDDqXR1ZGlhbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNBTExFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIyMSIgeT0iMjA5IiB3aWR0aD0iNzYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIxIiB5PSIyMzkiIHdpZHRoPSI3NiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMjEiIHk9IjIwOSIgd2lkdGg9Ijc2IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyMSIgeTE9IjIzOSIgeDI9IjI5NyIgeTI9IjIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjMzIiB5PSIyMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TYWxsZTwvdGV4dD4KCTx0ZXh0IHg9IjIyOSIgeT0iMjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlkLiBzYWxsZTwvdGV4dD4KCTxsaW5lIHgxPSIyMjkiIHkxPSIyNTkiIHgyPSIyNzUiIHkyPSIyNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMjkiIHk9IjI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gc2FsbGU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>CHR</strong> (<u><em>#id. salle</em></u>, <u><em>#id. cours</em></u>, <u>heure</u>)</li>\n<li><strong>CHS</strong> (<u><em>#id. cours</em></u>, <u><em>#id. étudiant</em></u>, <u>heure</u>)</li>\n<li><strong>Cours</strong> (<u>id. cours</u>, nom cours, <em>#id. professeur</em>)</li>\n<li><strong>CSG</strong> (<u><em>#id. cours</em></u>, <u><em>#id. étudiant</em></u>, <u>niveau</u>)</li>\n<li><strong>Étudiant</strong> (<u>id. étudiant</u>, nom étudiant)</li>\n<li><strong>Professeur</strong> (<u>id. professeur</u>, nom professeur)</li>\n<li><strong>Salle</strong> (<u>id. salle</u>, nom salle)</li>\n<li><strong>SHR</strong> (<u><em>#id. salle</em></u>, <u><em>#id. étudiant</em></u>, <u>heure</u>)</li>\n<li><strong>THR</strong> (<u><em>#id. salle</em></u>, <u><em>#id. professeur</em></u>, <u>heure</u>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notez qu'avec cette technique, les cardinalités minimales des pattes distinguées par les entités supprimées sont perdues dès le niveau conceptuel (sachant qu'elles l'auraient été de toute façon lors du passage au relationnel).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme la notion d'identifiant explicite d'association enfreint le standard Merise, et risque de semer la discorde entre professeurs et étudiants, elle est par défaut désactivée sous Mocodo online. En ligne de commande, elle est interdite à la demande :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [127]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --no_assoc_ids\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"application/vnd.jupyter.stderr\" tabindex=\"0\">\n<pre>Mocodo Err.52 - L'association « CSG » ne peut pas avoir d'identifiant.</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Ajustement-de-l'aspect-de-certains-%C3%A9l%C3%A9ments\">Ajustement de l'aspect de certains éléments<a class=\"anchor-link\" href=\"#Ajustement-de-l'aspect-de-certains-%C3%A9l%C3%A9ments\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Format-des-cardinalit%C3%A9s\">Format des cardinalités<a class=\"anchor-link\" href=\"#Format-des-cardinalit%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Par défaut, les cardinalités sont séparées par une virgule, et celles des entités faibles soulignées, mais cela peut être changé :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [128]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>  --card_format=({min_card}/{max_card}) --strengthen_card=(1/1)(R)\nŒUVRE: Cote œuvre, Titre, Date parution\nDF, 1N ŒUVRE, _11 EXEMPLAIRE\nEXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTIiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgNDEyIDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTIiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjYxIiB5MT0iNTYiIHgyPSIxOTEiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMzYiIHkxPSI1NiIgeDI9IjE5MSIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTkxIiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTc4IiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTE4IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+KDEvTik8L3RleHQ+Cgk8dGV4dCB4PSIyMTYiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4oMS8xKShSKTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgT0VVVlJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIxMDQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+xZJVVlJFPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkNvdGUgxZN1dnJlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI5NCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlRpdHJlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5EYXRlIHBhcnV0aW9uPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFWEVNUExBSVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI2OSIgeT0iOSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjkiIHk9IjM5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI2OSIgeT0iOSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNjkiIHkxPSIzOSIgeDI9IjQwMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNzciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RVhFTVBMQUlSRTwvdGV4dD4KCTx0ZXh0IHg9IjI3NyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TnVtLiBleGVtcGxhaXJlPC90ZXh0PgoJPGxpbmUgeDE9IjI3NyIgeTE9IjU5IiB4Mj0iMzg1IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIyNzciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOJdGF0IGR1IGxpdnJlPC90ZXh0PgoJPHRleHQgeD0iMjc3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZSBk4oCZYWNoYXQ8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Format-des-cl%C3%A9s-%C3%A9trang%C3%A8res\">Format des clés étrangères<a class=\"anchor-link\" href=\"#Format-des-cl%C3%A9s-%C3%A9trang%C3%A8res\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La mise en forme des clés étrangères affichées dans le diagramme relationnel peut être paramétrée, par exemple pour enlever le préfixe par défaut (<code>#</code>) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [129]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp -t diagram --fk_format={label}\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nccp_mld.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2NzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjcwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY3MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElOQ0xVUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzU2IiB5PSIxNyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjQ3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzU2IiB5MT0iNDciIHgyPSI0ODAiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzgyIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkluY2x1cmU8L3RleHQ+Cgk8dGV4dCB4PSIzNjQiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMzY0IiB5MT0iNjciIHgyPSI0NzIiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM2NCIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQzOSIgeTI9Ijg0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUzOCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MzgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTM4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjUzOCIgeTE9IjQ3IiB4Mj0iNjMyIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU0OSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTQ2IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU0NiIgeTE9IjY3IiB4Mj0iNjIxIiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NDYiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTQ2IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDAwMDAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwMDAwMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDgwIDc4LjUgQzUwOSA3MCA0OTkuMzMgNjEuNSA1MzggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1MzggNjEuNSA1MjYgNjcuNSA1MzAgNjEuNSA1MjYgNTUuNSIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ4MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzAwMDAwMCIvPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Symbole-de-d%C3%A9pendance-fonctionnelle\">Symbole de dépendance fonctionnelle<a class=\"anchor-link\" href=\"#Symbole-de-d%C3%A9pendance-fonctionnelle\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il est possible d'activer l'encerclement d'un autre sigle que DF. C'est ce sigle qui devra alors apparaître en entrée, par exemple:</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [130]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --df CIF\nCLIENT: Réf. client, Nom, Prénom, Adresse\nCIF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1ODgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTg4IDEyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1ODgiIGhlaWdodD0iMTI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBDSUYwIC0tPgo8Zz4KCTxsaW5lIHgxPSI1MSIgeTE9IjY0IiB4Mj0iMTQ1IiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjYwIiB5MT0iNjQiIHgyPSIxNDUiIHkyPSI2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjE0NSIgY3k9IjY0IiByPSIyMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjEyOSIgeT0iNjUuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DSUY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI5OCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjE3NCIgeT0iODAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBJTkNMVVJFIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNjAiIHkxPSI2NCIgeDI9IjQwMSIgeTI9IjY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjUyOSIgeTE9IjY0IiB4Mj0iNDAxIiB5Mj0iNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDM2IDM1IGExNCAxNCA5MCAwIDEgMTQgMTQgVjYzIGgtOTggVjQ5IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik00NTAgNjMgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzNjYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY2MyBIOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzUyIiB5PSIzNSIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzUyIiB5MT0iNjMiIHgyPSI0NTAiIHkyPSI2MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM2MCIgeT0iNTYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JTkNMVVJFPC90ZXh0PgoJCTx0ZXh0IHg9IjM1OSIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzI4IiB5PSI4MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iNDU1IiB5PSI4MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iODQiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI5MyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI3OSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTk3IiB5PSIxNyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOTciIHk9IjQ3IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE5NyIgeT0iMTciIHdpZHRoPSIxMjYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTk3IiB5MT0iNDciIHgyPSIzMjMiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjA2IiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTU1BTkRFPC90ZXh0PgoJPHRleHQgeD0iMjA1IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5OdW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjIwNSIgeTE9IjY3IiB4Mj0iMzEzIiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMDUiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSIyMDUiIHk9Ijk4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Nb250YW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQ3OSIgeT0iMTciIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDc5IiB5PSI0NyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NzkiIHk9IjE3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ3OSIgeTE9IjQ3IiB4Mj0iNTc5IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ4OCIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QUk9EVUlUPC90ZXh0PgoJPHRleHQgeD0iNDg3IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjQ4NyIgeTE9IjY3IiB4Mj0iNTYyIiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0ODciIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNDg3IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme le cercle est alors un peu plus grand, on peut vouloir régler (<em>a priori</em> une fois pour toutes) le ratio défini dans l'objet <code>shapes</code> du fichier appelé par défaut <code>sandbox_geo.json</code>):</p>\n<pre><code>\"df_text_height_ratio\" : 1.00,\n</code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Basculement-des-cardinalit%C3%A9s-et-inflexion-des-pattes-rectilignes\">Basculement des cardinalités et inflexion des pattes rectilignes<a class=\"anchor-link\" href=\"#Basculement-des-cardinalit%C3%A9s-et-inflexion-des-pattes-rectilignes\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mocodo est capable de détecter certaines configurations de pattes dont les cardinalités présentent un risque élevé de collision. Il procède alors à deux types d'ajustements:</p>\n<ol>\n<li><a href=\"https://github.com/laowantong/mocodo/issues/25\">Issue 25</a>. Les cardinalités d'une patte verticale ou horizontale sont envoyées de l'autre côté de la patte. Par exemple, dans le plongement du MCD précédent, la présence de la patte oblique <em>BLANDIT-VIVAMUS</em> envoie les cardinalités de <em>VELIT-BLANDIT</em> à l'opposé de leur position par défaut (à droite d'une patte verticale ou en bas d'une patte horizontale).</li>\n<li><a href=\"https://github.com/laowantong/mocodo/issues/27\">Issue 27</a>. Les pattes obliques sont infléchies de façon à ménager plus d'espace pour afficher deux couples de cardinalités. Ici, l'inflexion de la patte <em>DF-CONGUE</em> permet à ses cardinalités de coexister sans problème avec celles de l'association réflexive.</li>\n</ol>\n<p>Ces ajustements automatiques résolvent les problèmes les plus courants. Toutefois, étant antérieurs au tracé proprement dit, ils peuvent seulement réduire les risques de collision, et non les prévenir totalement. Ils peuvent même en produire d'autres. Ainsi, autour des entités monstrueusement pattues, des collisions qui ne se seraient pas produites par défaut seront parfois observées. L'utilisateur a alors deux possibilités:</p>\n<ul>\n<li>diminuer la valeur du paramètre <code>--flex</code> (par défaut, <code>0.75</code>) pour réduire la courbure de l'inflexion automatique, en allant jusqu'à <code>0</code> pour la désactiver totalement ;</li>\n<li>modifier à la main les positions des cardinalités en conflit, comme expliqué dans la section suivante.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Positionnement-des-contraintes\">Positionnement des contraintes<a class=\"anchor-link\" href=\"#Positionnement-des-contraintes\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"En-ajoutant-des-liens-invisibles\">En ajoutant des liens invisibles<a class=\"anchor-link\" href=\"#En-ajoutant-des-liens-invisibles\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La possibilité de rendre un trait invisible peut être exploitée pour « attirer » une contrainte vers telle ou telle boîte existante, soit en la répétant dans la définition de la contrainte, soit en l'y intégrant (fictivement) si elle n'en fait pas partie.</p>\n<p>Par exemple, ci-dessous, répéter l'association Stocker et intégrer l'entité Commande permet de réduire la largeur du MCD sans compromettre sa lisibilité :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [131]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\n:::\nDépôt: num dépôt, surface\n\n:\nLouer, 11 Commande, 0N Dépôt\n:\nStocker, 1N Dépôt, 1N Article: quantité\n\nCommande: num. commande, date\nComposer, 1N Commande, 0N Article\n:\nArticle: réf. article, prix\n\n(I) -&gt;Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande, Stocker\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiB2aWV3Qm94PSIwIDAgNDE3IDI3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IElfQ09OU1RSQUlOVF8jMSAtLT4KPGc+Cgk8cG9seWdvbiBwb2ludHM9IjMyMCAxNTEuMjggMzEwLjI1IDE2MC40OSAzMTIuMzQgMTUzLjU5IDMwNi43OCAxNDkuMCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMTM4IiB4Mj0iMjc3Ljg2IiB5Mj0iMTY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjQ3IiB4Mj0iMjc3Ljg2IiB5Mj0iMTY0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxsaW5lIHgxPSIzNjQiIHkxPSIyMjkiIHgyPSIyNzcuODYiIHkyPSIxNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtZGFzaGFycmF5PSIwLDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJPGxpbmUgeDE9IjIxMCIgeTE9IjIyOSIgeDI9IjI3Ny44NiIgeTI9IjE2NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMTAiIHkxPSIxMzgiIHgyPSIyNzcuODYiIHkyPSIxNjQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIyNzcuODYiIGN5PSIxNjQiIHI9IjEyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjI3NS4zNiIgeT0iMTY4LjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkk8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gTE9VRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjQ3IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIzMSAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtNzAgVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjQ1IDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE4OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEzNyBINzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTc1IiB5PSIxMDkiIHdpZHRoPSI3MCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE3NSIgeTE9IjEzNyIgeDI9IjI0NSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE4MiIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TG91ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMDkuODQiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMjk3IiB5PSI2OC45OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFNUT0NLRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjQ3IiB4Mj0iMzY0IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjIyOSIgeDI9IjM2NCIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zOTQgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTg4IFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQwOCAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzMzQgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMyMCIgeT0iMTA5IiB3aWR0aD0iODgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzMjAiIHkxPSIxMzciIHgyPSI0MDgiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzMjciIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlN0b2NrZXI8L3RleHQ+CgkJPHRleHQgeD0iMzI3IiB5PSIxNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVhbnRpdMOpPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzY5IiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM2OSIgeT0iMTgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09NUE9TRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMjI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjIyOSIgeDI9IjIxMCIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDggMjAwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjIyOCBoLTEwNCBWMjE0IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjIgMjI4IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTcyIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMjI4IEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTU4IiB5PSIyMDAiIHdpZHRoPSIxMDQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTgiIHkxPSIyMjgiIHgyPSIyNjIiIHkyPSIyMjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNjUiIHk9IjIyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbXBvc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTM0IiB5PSIyNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI5NyIgeT0iMjQ1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERFUE9UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMyMSIgeT0iOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iMzkiIHdpZHRoPSI4NiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9IjkiIHdpZHRoPSI4NiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMjEiIHkxPSIzOSIgeDI9IjQwNyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMzciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RMOpcMO0dDwvdGV4dD4KCTx0ZXh0IHg9IjMyOSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIGTDqXDDtHQ8L3RleHQ+Cgk8bGluZSB4MT0iMzI5IiB5MT0iNTkiIHgyPSIzOTgiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMyOSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c3VyZmFjZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIyMSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxOTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjIyMSIgeDI9IjEyOSIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjIiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbW1hbmRlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMjQxIiB4Mj0iMTIxIiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBUlRJQ0xFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMyMSIgeT0iMTkxIiB3aWR0aD0iODYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzIxIiB5PSIyMjEiIHdpZHRoPSI4NiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9IjE5MSIgd2lkdGg9Ijg2IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMyMSIgeTE9IjIyMSIgeDI9IjQwNyIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzMwIiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BcnRpY2xlPC90ZXh0PgoJPHRleHQgeD0iMzI5IiB5PSIyMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gYXJ0aWNsZTwvdGV4dD4KCTxsaW5lIHgxPSIzMjkiIHkxPSIyNDEiIHgyPSIzOTMiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMjkiIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcml4PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"En-ajoutant-une-bo%C3%AEte-invisible\">En ajoutant une boîte invisible<a class=\"anchor-link\" href=\"#En-ajoutant-une-bo%C3%AEte-invisible\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ces réglages restent relativement fragiles. Une façon d'assurer qu'ils survivront à un réarrangement est de faire coïncider le centre d'une contrainte avec celui d'une boîte supplémentaire, que nous appelons ici « Z » :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [132]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\n:::\nDépôt: num dépôt, surface\n\n:\nLouer, 11 Commande, 0N Dépôt\nZ, XX Commande, XX Article, XX Dépôt\nStocker, 1N Dépôt, 1N Article: quantité\n\nCommande: num. commande, date\nComposer, 1N Commande, 0N Article\n:\nArticle: réf. article, prix\n\n(I) -&gt;Stocker, ..Dépôt, ..Article, --Composer, --Louer: Z, Z\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MzAiIGhlaWdodD0iMjc2IiB2aWV3Qm94PSIwIDAgNDMwIDI3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MzAiIGhlaWdodD0iMjc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IElfQ09OU1RSQUlOVF8jMSAtLT4KPGc+Cgk8cG9seWdvbiBwb2ludHM9IjMzMyAxMzggMzIxIDE0NCAzMjUgMTM4IDMyMSAxMzIiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGxpbmUgeDE9IjM3NyIgeTE9IjEzOCIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNzciIHkxPSI0NyIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cgk8bGluZSB4MT0iMzc3IiB5MT0iMjI5IiB4Mj0iMjkxIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxsaW5lIHgxPSIyMTAiIHkxPSIyMjkiIHgyPSIyOTEiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjEwIiB5MT0iMTM4IiB4Mj0iMjkxIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjkxIiBjeT0iMTM4IiByPSIxMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIyODguNSIgeT0iMTQyLjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkk8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gTE9VRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM3NyIgeTE9IjQ3IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIzMSAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtNzAgVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjQ1IDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE4OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEzNyBINzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTc1IiB5PSIxMDkiIHdpZHRoPSI3MCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE3NSIgeTE9IjEzNyIgeDI9IjI0NSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE4MiIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TG91ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMDkuODQiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMzEwIiB5PSI2Ni42OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFogLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjkxIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM3NyIgeTE9IjIyOSIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNzciIHkxPSI0NyIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yOTAgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTI2IFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTMwNCAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyOTIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDI2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjI3OCIgeT0iMTA5IiB3aWR0aD0iMjYiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyNzgiIHkxPSIxMzciIHgyPSIzMDQiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyODUiIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlo8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzQiIHk9IjIxNy4yIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4gICAgIDwvdGV4dD4KCTx0ZXh0IHg9IjMzOS4zIiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPiAgICAgPC90ZXh0PgoJPHRleHQgeD0iMzM5LjMiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+ICAgICA8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gU1RPQ0tFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMzc3IiB5MT0iNDciIHgyPSIzNzciIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzc3IiB5MT0iMjI5IiB4Mj0iMzc3IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQwNyAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtODggVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDIxIDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM0NyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEzNyBIODgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzMzIiB5PSIxMDkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjMzMyIgeTE9IjEzNyIgeDI9IjQyMSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM0MCIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U3RvY2tlcjwvdGV4dD4KCQk8dGV4dCB4PSIzNDAiIHk9IjE1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzODIiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMzgyIiB5PSIxODMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBDT01QT1NFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNjkiIHkxPSIyMjkiIHgyPSIyMTAiIHkyPSIyMjkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzc3IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMjI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI0OCAyMDAgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMjI4IGgtMTA0IFYyMTQgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI2MiAyMjggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzIgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYyMjggSDEwNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTgiIHk9IjIwMCIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE1OCIgeTE9IjIyOCIgeDI9IjI2MiIgeTI9IjIyOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE2NSIgeT0iMjIxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tcG9zZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzQiIHk9IjI0NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMzEwIiB5PSIyNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREVQT1QgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzM0IiB5PSI5IiB3aWR0aD0iODYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzM0IiB5PSIzOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMzNCIgeT0iOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMzNCIgeTE9IjM5IiB4Mj0iNDIwIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM1MCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ew6lww7R0PC90ZXh0PgoJPHRleHQgeD0iMzQyIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gZMOpcMO0dDwvdGV4dD4KCTxsaW5lIHgxPSIzNDIiIHkxPSI1OSIgeDI9IjQxMSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzQyIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5zdXJmYWNlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDT01NQU5ERSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIxOTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMjIxIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE5MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMjIxIiB4Mj0iMTI5IiB5Mj0iMjIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMiIgeT0iMjEyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMjM4LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIyNDEiIHgyPSIxMjEiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFSVElDTEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzM0IiB5PSIxOTEiIHdpZHRoPSI4NiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMzQiIHk9IjIyMSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMzNCIgeT0iMTkxIiB3aWR0aD0iODYiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzM0IiB5MT0iMjIxIiB4Mj0iNDIwIiB5Mj0iMjIxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNDMiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFydGljbGU8L3RleHQ+Cgk8dGV4dCB4PSIzNDIiIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yw6lmLiBhcnRpY2xlPC90ZXh0PgoJPGxpbmUgeDE9IjM0MiIgeTE9IjI0MSIgeDI9IjQwNiIgeTI9IjI0MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM0MiIgeT0iMjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByaXg8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il ne reste plus qu'à rendre invisibles l'association Z et ses pattes en préfixant Z d'un signe moins <code>-</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [133]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\n:::\nDépôt: num dépôt, surface\n\n:\nLouer, 11 Commande, 0N Dépôt\n-Z, XX Commande, XX Article, XX Dépôt\nStocker, 1N Dépôt, 1N Article: quantité\n\nCommande: num. commande, date\nComposer, 1N Commande, 0N Article\n:\nArticle: réf. article, prix\n\n(I) -&gt;Stocker, ..Dépôt, ..Article, --Composer, --Louer: Z, Z\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiB2aWV3Qm94PSIwIDAgNDE3IDI3NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MTciIGhlaWdodD0iMjc2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IElfQ09OU1RSQUlOVF8jMSAtLT4KPGc+Cgk8cG9seWdvbiBwb2ludHM9IjMyMCAxMzggMzA4IDE0NCAzMTIgMTM4IDMwOCAxMzIiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjEzOCIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNjQiIHkxPSI0NyIgeDI9IjI5MSIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cgk8bGluZSB4MT0iMzY0IiB5MT0iMjI5IiB4Mj0iMjkxIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxsaW5lIHgxPSIyMTAiIHkxPSIyMjkiIHgyPSIyOTEiIHkyPSIxMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMjEwIiB5MT0iMTM4IiB4Mj0iMjkxIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjkxIiBjeT0iMTM4IiByPSIxMiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIyODguNSIgeT0iMTQyLjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkk8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gTE9VRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjQ3IiB4Mj0iMjEwIiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIzMSAxMDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTM3IGgtNzAgVjEyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjQ1IDEzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE4OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEzNyBINzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTc1IiB5PSIxMDkiIHdpZHRoPSI3MCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE3NSIgeTE9IjEzNyIgeDI9IjI0NSIgeTI9IjEzNyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE4MiIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TG91ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMDkuODQiIHk9IjE4MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMjk3IiB5PSI2OC45OSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFNUT0NLRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjQ3IiB4Mj0iMzY0IiB5Mj0iMTM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjIyOSIgeDI9IjM2NCIgeTI9IjEzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0zOTQgMTA5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjEzNyBoLTg4IFYxMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQwOCAxMzcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgzMzQgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxMzcgSDg4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjMyMCIgeT0iMTA5IiB3aWR0aD0iODgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIzMjAiIHkxPSIxMzciIHgyPSI0MDgiIHkyPSIxMzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzMjciIHk9IjEzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlN0b2NrZXI8L3RleHQ+CgkJPHRleHQgeD0iMzI3IiB5PSIxNTUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVhbnRpdMOpPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzY5IiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjM2OSIgeT0iMTgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09NUE9TRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjY5IiB5MT0iMjI5IiB4Mj0iMjEwIiB5Mj0iMjI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM2NCIgeTE9IjIyOSIgeDI9IjIxMCIgeTI9IjIyOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDggMjAwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjIyOCBoLTEwNCBWMjE0IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjIgMjI4IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTcyIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMjI4IEgxMDQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTU4IiB5PSIyMDAiIHdpZHRoPSIxMDQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTgiIHkxPSIyMjgiIHgyPSIyNjIiIHkyPSIyMjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNjUiIHk9IjIyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbXBvc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTM0IiB5PSIyNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI5NyIgeT0iMjQ1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERFUE9UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMyMSIgeT0iOSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iMzkiIHdpZHRoPSI4NiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9IjkiIHdpZHRoPSI4NiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMjEiIHkxPSIzOSIgeDI9IjQwNyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMzciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RMOpcMO0dDwvdGV4dD4KCTx0ZXh0IHg9IjMyOSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIGTDqXDDtHQ8L3RleHQ+Cgk8bGluZSB4MT0iMzI5IiB5MT0iNTkiIHgyPSIzOTgiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMyOSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c3VyZmFjZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTkxIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIyMSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxOTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjIyMSIgeDI9IjEyOSIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjIiIHk9IjIxMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbW1hbmRlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjIzOC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMjQxIiB4Mj0iMTIxIiB5Mj0iMjQxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBBUlRJQ0xFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMyMSIgeT0iMTkxIiB3aWR0aD0iODYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzIxIiB5PSIyMjEiIHdpZHRoPSI4NiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9IjE5MSIgd2lkdGg9Ijg2IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMyMSIgeTE9IjIyMSIgeDI9IjQwNyIgeTI9IjIyMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzMwIiB5PSIyMTIuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BcnRpY2xlPC90ZXh0PgoJPHRleHQgeD0iMzI5IiB5PSIyMzguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gYXJ0aWNsZTwvdGV4dD4KCTxsaW5lIHgxPSIzMjkiIHkxPSIyNDEiIHgyPSIzOTMiIHkyPSIyNDEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMjkiIHk9IjI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcml4PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cette technique résiste très bien aux réarrangements automatiques.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Goutti%C3%A8re-d'identifiants\">Gouttière d'identifiants<a class=\"anchor-link\" href=\"#Goutti%C3%A8re-d'identifiants\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Elle apparaît automatiquement (<code>visibility=auto</code>) dès qu'il y a au moins un identifiant alternatif. Il est possible de l'en empêcher :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [134]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --gutters ids:visibility=off\nCLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDIiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgMTAyIDE0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDIiIGhlaWdodD0iMTQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9Ijk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSIxMjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iOTMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q0xJRU5UPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHLDqW5vbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTI0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5NYWlsPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>... ou au contraire de la forcer quand elle est superfétatoire :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [135]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --gutters ids:visibility=on\nCLIENT: Réf. client, Nom, Prénom, Adresse, Mail\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMzQiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgMTM0IDE0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMzQiIGhlaWdodD0iMTQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDEiIHk9IjM5IiB3aWR0aD0iODQiIGhlaWdodD0iOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIzMiIgaGVpZ2h0PSI5OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDEiIHkxPSIzOSIgeDI9IjQxIiB5Mj0iMTM3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC4zOCIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTYiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjEyNSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSI0OSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPklEPC90ZXh0PgoJPGxpbmUgeDE9IjQ5IiB5MT0iNTkiIHgyPSIxMTEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Ob208L3RleHQ+Cgk8dGV4dCB4PSIyNCIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSIvPgoJPHRleHQgeD0iNDkiIHk9IjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPlByw6lub208L3RleHQ+Cgk8dGV4dCB4PSIyNCIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSIvPgoJPHRleHQgeD0iNDkiIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjI0IiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiLz4KCTx0ZXh0IHg9IjQ5IiB5PSIxMjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk1haWw8L3RleHQ+Cgk8dGV4dCB4PSIyNCIgeT0iMTI0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ii8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Vous pouvez aussi préciser quelles chaînes dénoteront un identifiant fort (par défaut, <code>strong=ID</code>), un identifiant faible (par défaut, <code>weak=id</code>) ainsi que les numéros des groupes d'identifiants alternatifs (par défaut, <code>alts=123456789</code>, mais vous pouvez lister moins de 9 symboles) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [136]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --gutters ids:strong=➤,alts=❶❷❸❹\nCLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgMTI4IDE0NiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMjgiIGhlaWdodD0iMTQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzQiIHk9IjM5IiB3aWR0aD0iODUiIGhlaWdodD0iOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIyNSIgaGVpZ2h0PSI5OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzQiIHkxPSIzOSIgeDI9IjM0IiB5Mj0iMTM3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC4zOCIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTAiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjExOSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DTElFTlQ8L3RleHQ+Cgk8dGV4dCB4PSI0MiIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gY2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPuKepDwvdGV4dD4KCTxsaW5lIHgxPSI0MiIgeTE9IjU5IiB4Mj0iMTA0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0MiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Tm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPuKdtjwvdGV4dD4KCTx0ZXh0IHg9IjQyIiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPuKdtjwvdGV4dD4KCTx0ZXh0IHg9IjQyIiB5PSIxMDciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkFkcmVzc2U8L3RleHQ+Cgk8dGV4dCB4PSIyMSIgeT0iMTA3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ii8+Cgk8dGV4dCB4PSI0MiIgeT0iMTI0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5NYWlsPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjEyNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+4p23PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Style-et-direction-des-pattes-de-l'h%C3%A9ritage\">Style et direction des pattes de l'héritage<a class=\"anchor-link\" href=\"#Style-et-direction-des-pattes-de-l'h%C3%A9ritage\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le type de flèche spécifiant le mécanisme de passage au modèle relationnel (<code>&lt;=</code>, <code>&lt;-</code>, <code>-&gt;</code> ou <code>=&gt;</code>) fait par défaut l'objet d'une visualisation dès le modèle conceptuel : la ou les pattes vers les entités de destination des attributs migrants sont orientées vers celles-ci ; et la ou les autres pattes sont doublées (pour <code>&lt;=</code> et <code>=&gt;</code>) ou non (pour <code>&lt;-</code> et <code>-&gt;</code>).</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [137]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nPersonne: num SS, nom, prénom\n\n/XT\\ Personne =&gt; Homme, Femme: sexe\n\nHomme: \n:\nFemme: nom de jeune fille\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiB2aWV3Qm94PSIwIDAgMjk2IDI3MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBQRVJTT05ORV9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjEzMSIgeTE9IjU2IiB4Mj0iMTMxIiB5Mj0iMTUyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjEyOSIgeTE9IjU2IiB4Mj0iMTI5IiB5Mj0iMTUyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4IiB5MT0iMjMxIiB4Mj0iMTMwIiB5Mj0iMTUyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSI2OS44IDIxMCA3NC4yOCAxOTcuMzUgNzUuNTYgMjA0LjQ1IDgyLjYgMjA2LjAiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGxpbmUgeDE9IjIyMyIgeTE9IjIzMSIgeDI9IjEzMCIgeTI9IjE1MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwb2x5Z29uIHBvaW50cz0iMTg3LjY4IDIwMSAxNzQuNjUgMTk3LjggMTgxLjU5IDE5NS44MiAxODIuNDIgMTg4LjY2IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxnPgoJCTxwb2x5Z29uIHBvaW50cz0iMTMwIDEyMy4xMyAxMDUgMTY2LjQzIDE1NSAxNjYuNDMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIxMTgiIHk9IjE1OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5YVDwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBFbnRpdHkgUEVSU09OTkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNzciIHk9IjkiIHdpZHRoPSIxMDYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNzciIHk9IjM5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijc3IiB5PSI5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijc3IiB5MT0iMzkiIHgyPSIxODMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iODYiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UGVyc29ubmU8L3RleHQ+Cgk8dGV4dCB4PSI4NSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIFNTPC90ZXh0PgoJPGxpbmUgeDE9Ijg1IiB5MT0iNTkiIHgyPSIxMzEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9Ijg1IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub208L3RleHQ+Cgk8dGV4dCB4PSI4NSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByw6lub208L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEhPTU1FIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjIxMCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjI0MCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjIxMCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjQyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIyNDAiIHgyPSI4NyIgeTI9IjI0MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjIzMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkhvbW1lPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBGRU1NRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNTkiIHk9IjIwMSIgd2lkdGg9IjEyOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTkiIHk9IjIzMSIgd2lkdGg9IjEyOCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTkiIHk9IjIwMSIgd2lkdGg9IjEyOCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNTkiIHkxPSIyMzEiIHgyPSIyODciIHkyPSIyMzEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE5NCIgeT0iMjIyLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RmVtbWU8L3RleHQ+Cgk8dGV4dCB4PSIxNjciIHk9IjI0OC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZGUgamV1bmUgZmlsbGU8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Femme</strong> (<u>num SS</u>, nom, prénom, nom de jeune fille)</li>\n<li><strong>Homme</strong> (<u>num SS</u>, nom, prénom)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cette visualisation n'est pas conventionnelle : on se borne normalement à ajouter une flèche dirigée vers l'entité-mère.</p>\n<p>Pour désactiver l'embellissement opéré par Mocodo, sans pour autant changer le mécanisme de passage au relationnel, prolongez simplement d'un caractère la flèche : <code>&lt;==</code>, <code>&lt;--</code>, <code>--&gt;</code> ou <code>==&gt;</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [138]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nPersonne: num SS, nom, prénom\n\n/XT\\ Personne ==&gt; Homme, Femme: sexe\n\nHomme: \n:\nFemme: nom de jeune fille\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiB2aWV3Qm94PSIwIDAgMjk2IDI3MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyOTYiIGhlaWdodD0iMjcwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBJbmhlcml0YW5jZSBQRVJTT05ORV9QQVJFTlRfIzEgLS0+CjxnPgoJPGxpbmUgeDE9IjEzMCIgeTE9IjU2IiB4Mj0iMTMwIiB5Mj0iMTUyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxMzAgMTAzIDEzNiAxMTUgMTMwIDExMSAxMjQgMTE1IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSI0OCIgeTE9IjIzMSIgeDI9IjEzMCIgeTI9IjE1MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMjMiIHkxPSIyMzEiIHgyPSIxMzAiIHkyPSIxNTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cG9seWdvbiBwb2ludHM9IjEzMCAxMjMuMTMgMTA1IDE2Ni40MyAxNTUgMTY2LjQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTE4IiB5PSIxNTgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+WFQ8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gRW50aXR5IFBFUlNPTk5FIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijc3IiB5PSI5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijc3IiB5PSIzOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI3NyIgeT0iOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI3NyIgeTE9IjM5IiB4Mj0iMTgzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9Ijg2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBlcnNvbm5lPC90ZXh0PgoJPHRleHQgeD0iODUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBTUzwvdGV4dD4KCTxsaW5lIHgxPSI4NSIgeTE9IjU5IiB4Mj0iMTMxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI4NSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tPC90ZXh0PgoJPHRleHQgeD0iODUiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcsOpbm9tPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBIT01NRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSIyMTAiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyNDAiIHdpZHRoPSI3OCIgaGVpZ2h0PSIxMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIyMTAiIHdpZHRoPSI3OCIgaGVpZ2h0PSI0MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMjQwIiB4Mj0iODciIHkyPSIyNDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3IiB5PSIyMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ib21tZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRkVNTUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMDEiIHdpZHRoPSIxMjgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMzEiIHdpZHRoPSIxMjgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU5IiB5PSIyMDEiIHdpZHRoPSIxMjgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTU5IiB5MT0iMjMxIiB4Mj0iMjg3IiB5Mj0iMjMxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOTQiIHk9IjIyMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZlbW1lPC90ZXh0PgoJPHRleHQgeD0iMTY3IiB5PSIyNDguMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGRlIGpldW5lIGZpbGxlPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Femme</strong> (<u>num SS</u>, nom, prénom, nom de jeune fille)</li>\n<li><strong>Homme</strong> (<u>num SS</u>, nom, prénom)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Changement de la version 4.0.</strong> Précédemment, <code>--&gt;</code> et <code>==&gt;</code> s'écrivaient respectivement <code>-&gt;&gt;</code> et <code>=&gt;&gt;</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Retouches-fines\">Retouches fines<a class=\"anchor-link\" href=\"#Retouches-fines\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Lors du plongement, Mocodo génère systématiquement un fichier (intitulé par défaut <code>sandbox_geo.json</code>) répertoriant les positions les plus importantes du dessin. Les autres coordonnées sont calculées relativement à celles-ci.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [139]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> --colors brewer+1\nVELIT, 1N&gt; BLANDIT, 11 NONUMMY: sollicitudin\n\nBLANDIT: consequat, ligula, nibh, consequat\n:::\nNONUMMY: consequat, ligula\n  \nVIVAMUS, 0N NONUMMY, 0N BLANDIT: eleifend, iaculis\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NDQiIGhlaWdodD0iMjQyIiB2aWV3Qm94PSIwIDAgNDQ0IDI0MiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NDQiIGhlaWdodD0iMjQyIiBmaWxsPSIjZjVmNWY1IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBWRUxJVCAtLT4KPGc+Cgk8bGluZSB4MT0iNTgiIHkxPSIxMTciIHgyPSIyMTQiIHkyPSIzOCIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxwb2x5Z29uIHBvaW50cz0iMTA3IDkyLjE5IDExNC45OSA4MS40MSAxMTQuMTQgODguNTcgMTIwLjQyIDkyLjEyIiBmaWxsPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIzNzgiIHkxPSIxMTciIHgyPSIyMTQiIHkyPSIzOCIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDEgOSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzNyBoLTgyIFYyMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2RmYzI3ZCIgc3Ryb2tlPSIjZGZjMjdkIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjU1IDM3IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTg3IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzcgSDgyIiBmaWxsPSIjZjZlOGMzIiBzdHJva2U9IiNmNmU4YzMiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE3MyIgeT0iOSIgd2lkdGg9IjgyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTczIiB5MT0iMzciIHgyPSIyNTUiIHkyPSIzNyIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE4OCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5WRUxJVDwvdGV4dD4KCQk8dGV4dCB4PSIxODAiIHk9IjU1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnNvbGxpY2l0dWRpbjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjExMiIgeT0iMTA0LjIzIiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyOTgiIHk9IjEwMS43NyIgZmlsbD0iIzAxNjY1ZSIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFZJVkFNVVMgLS0+CjxnPgoJPGxpbmUgeDE9IjM3OCIgeTE9IjExNyIgeDI9IjIxNCIgeTI9IjE5NiIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1OCIgeTE9IjExNyIgeDI9IjIxNCIgeTI9IjE5NiIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDkgMTU5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjE4NyBoLTk4IFYxNzMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNkZmMyN2QiIHN0cm9rZT0iI2RmYzI3ZCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI2MyAxODcgdjMyIGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzkgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxODcgSDk4IiBmaWxsPSIjZjZlOGMzIiBzdHJva2U9IiNmNmU4YzMiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE2NSIgeT0iMTU5IiB3aWR0aD0iOTgiIGhlaWdodD0iNzQiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNjUiIHkxPSIxODciIHgyPSIyNjMiIHkyPSIxODciIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNzMiIHk9IjE4MC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlZJVkFNVVM8L3RleHQ+CgkJPHRleHQgeD0iMTcyIiB5PSIyMDUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZWxlaWZlbmQ8L3RleHQ+CgkJPHRleHQgeD0iMTcyIiB5PSIyMjIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWFjdWxpczwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI5NyIgeT0iMTQwLjIzIiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxMTIiIHk9IjEzNy43NyIgZmlsbD0iIzAxNjY1ZSIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBCTEFORElUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjYyIiB3aWR0aD0iOTgiIGhlaWdodD0iMzAiIGZpbGw9IiM4MGNkYzEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOTIiIHdpZHRoPSI5OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2M3ZWFlNSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI2MiIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzU5NzhmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iOTIiIHgyPSIxMDciIHkyPSI5MiIgc3Ryb2tlPSIjMzU5NzhmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjgzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QkxBTkRJVDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxMDkuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y29uc2VxdWF0PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iMTEyIiB4Mj0iODEiIHkyPSIxMTIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iMTI2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpZ3VsYTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNDMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bmliaDwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNjAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbnNlcXVhdDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTk9OVU1NWSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMjEiIHk9Ijc5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjODBjZGMxIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iMTA5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjYzdlYWU1IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iNzkiIHdpZHRoPSIxMTQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM1OTc4ZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzIxIiB5MT0iMTA5IiB4Mj0iNDM1IiB5Mj0iMTA5IiBzdHJva2U9IiMzNTk3OGYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMzAiIHk9IjEwMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk5PTlVNTVk8L3RleHQ+Cgk8dGV4dCB4PSIzMjkiIHk9IjEyNi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb25zZXF1YXQ8L3RleHQ+Cgk8bGluZSB4MT0iMzI5IiB5MT0iMTI5IiB4Mj0iMzkzIiB5Mj0iMTI5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzI5IiB5PSIxNDMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGlndWxhPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ouvrons le fichier de géométrie généré :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [140]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Code</span><span class=\"p\">(</span><span class=\"s2\">\"sandbox_geo.json\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[140]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #FF0000 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #0044DD } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.output_html .no { color: #880000 } /* Name.Constant */\n.output_html .nd { color: #AA22FF } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #0000FF } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #bbbbbb } /* Text.Whitespace */\n.output_html .mb { color: #666666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666666 } /* Literal.Number.Float */\n.output_html .mh { color: #666666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #0000FF } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n<span class=\"w\">  </span><span class=\"nt\">\"width\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"mi\">444</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"nt\">\"height\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"mi\">242</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"nt\">\"cx\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"p\">[</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VELIT\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">214</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"BLANDIT\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">58</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"NONUMMY\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">378</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VIVAMUS\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">214</span><span class=\"w\"> </span><span class=\"p\">]</span>\n<span class=\"w\">  </span><span class=\"p\">],</span>\n<span class=\"w\">  </span><span class=\"nt\">\"cy\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"p\">[</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VELIT\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">38</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"BLANDIT\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">117</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"NONUMMY\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">117</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VIVAMUS\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">196</span><span class=\"w\"> </span><span class=\"p\">]</span>\n<span class=\"w\">  </span><span class=\"p\">],</span>\n<span class=\"w\">  </span><span class=\"nt\">\"shift\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"p\">[</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VELIT,BLANDIT,0\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">0</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VELIT,NONUMMY,0\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">0</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VIVAMUS,NONUMMY,0\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">0</span><span class=\"w\"> </span><span class=\"p\">],</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VIVAMUS,BLANDIT,0\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mi\">0</span><span class=\"w\"> </span><span class=\"p\">]</span>\n<span class=\"w\">  </span><span class=\"p\">],</span>\n<span class=\"w\">  </span><span class=\"nt\">\"ratio\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"p\">[</span>\n<span class=\"w\">    </span><span class=\"p\">[</span><span class=\"w\"> </span><span class=\"s2\">\"VELIT,BLANDIT,0\"</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"mf\">1.0</span><span class=\"w\"> </span><span class=\"p\">]</span>\n<span class=\"w\">  </span><span class=\"p\">]</span>\n<span class=\"p\">}</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>On y trouve :</p>\n<ul>\n<li>un couple de dimensions <code>width</code> et <code>height</code> définit la taille du MCD ;</li>\n<li>deux listes de couples <code>cx</code> et <code>cy</code>, les abscisses et ordonnées des centres des boîtes ;</li>\n<li>un dictionnaire <code>shift</code>, les positions relatives des cardinalités par rapport à leur position par défaut ;</li>\n<li>une liste <code>ratio</code>, les positions des flèches éventuelles : leur valeur peuvent varier de <code>0.0</code> (flèche cachée sous la boîte d'origine) à <code>1.0</code> (par défaut, pointe de la flèche au contact du bord de la boîte de destination, compte non tenu de l'arrondi s'il s'agit d'une association).</li>\n</ul>\n<p>Copions-collons ce texte, apportons-lui quelques modifications et sauvegardons-le :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [141]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%file</span> sandbox_geo.json\n<span class=\"p\">{</span>\n  <span class=\"s2\">\"width\"</span><span class=\"p\">:</span> <span class=\"mi\">444</span><span class=\"p\">,</span>\n  <span class=\"s2\">\"height\"</span><span class=\"p\">:</span> <span class=\"mi\">182</span><span class=\"p\">,</span>\n  <span class=\"s2\">\"cx\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VELIT\"</span><span class=\"p\">,</span> <span class=\"mi\">214</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"BLANDIT\"</span><span class=\"p\">,</span> <span class=\"mi\">58</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"NONUMMY\"</span><span class=\"p\">,</span> <span class=\"mi\">378</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VIVAMUS\"</span><span class=\"p\">,</span> <span class=\"mi\">214</span> <span class=\"p\">]</span>\n  <span class=\"p\">],</span>\n  <span class=\"s2\">\"cy\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VELIT\"</span><span class=\"p\">,</span> <span class=\"mi\">38</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"BLANDIT\"</span><span class=\"p\">,</span> <span class=\"mi\">87</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"NONUMMY\"</span><span class=\"p\">,</span> <span class=\"mi\">87</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VIVAMUS\"</span><span class=\"p\">,</span> <span class=\"mi\">136</span> <span class=\"p\">]</span>\n  <span class=\"p\">],</span>\n  <span class=\"s2\">\"shift\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VELIT,BLANDIT,0\"</span><span class=\"p\">,</span> <span class=\"o\">-</span><span class=\"mi\">30</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VELIT,NONUMMY,0\"</span><span class=\"p\">,</span> <span class=\"o\">-</span><span class=\"mi\">30</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VIVAMUS,NONUMMY,0\"</span><span class=\"p\">,</span> <span class=\"mi\">0</span> <span class=\"p\">],</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VIVAMUS,BLANDIT,0\"</span><span class=\"p\">,</span> <span class=\"mi\">0</span> <span class=\"p\">]</span>\n  <span class=\"p\">],</span>\n  <span class=\"s2\">\"ratio\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">[</span> <span class=\"s2\">\"VELIT,BLANDIT,0\"</span><span class=\"p\">,</span> <span class=\"mf\">0.5</span> <span class=\"p\">]</span>\n  <span class=\"p\">]</span>\n<span class=\"p\">}</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>Overwriting sandbox_geo.json\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il suffit maintenant d'ajouter l'option <code>--reuse_geo</code> pour appliquer ces modifications :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [142]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --colors brewer+1 --reuse_geo\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NDQiIGhlaWdodD0iMTgyIiB2aWV3Qm94PSIwIDAgNDQ0IDE4MiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NDQiIGhlaWdodD0iMTgyIiBmaWxsPSIjZjVmNWY1IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBWRUxJVCAtLT4KPGc+Cgk8bGluZSB4MT0iNTgiIHkxPSI4NyIgeDI9IjIxNCIgeTI9IjM4IiBzdHJva2U9IiNiZjgxMmQiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBvbHlnb24gcG9pbnRzPSIxNDAgNjEuMjQgMTQ5LjY1IDUxLjkyIDE0Ny42MyA1OC44NSAxNTMuMjUgNjMuMzciIGZpbGw9IiNiZjgxMmQiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGxpbmUgeDE9IjM3OCIgeTE9Ijg3IiB4Mj0iMjE0IiB5Mj0iMzgiIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQxIDkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzcgaC04MiBWMjMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNkZmMyN2QiIHN0cm9rZT0iI2RmYzI3ZCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI1NSAzNyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE4NyBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjM3IEg4MiIgZmlsbD0iI2Y2ZThjMyIgc3Ryb2tlPSIjZjZlOGMzIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNzMiIHk9IjkiIHdpZHRoPSI4MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiNiZjgxMmQiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE3MyIgeTE9IjM3IiB4Mj0iMjU1IiB5Mj0iMzciIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxODgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VkVMSVQ8L3RleHQ+CgkJPHRleHQgeD0iMTgwIiB5PSI1NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5zb2xsaWNpdHVkaW48L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMTIiIHk9IjU1LjE3IiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyOTgiIHk9IjUzLjY1IiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gVklWQU1VUyAtLT4KPGc+Cgk8bGluZSB4MT0iMzc4IiB5MT0iODciIHgyPSIyMTQiIHkyPSIxMzYiIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTgiIHkxPSI4NyIgeDI9IjIxNCIgeTI9IjEzNiIgc3Ryb2tlPSIjYmY4MTJkIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNDkgOTkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTI3IGgtOTggVjExMyBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI2RmYzI3ZCIgc3Ryb2tlPSIjZGZjMjdkIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjYzIDEyNyB2MzIgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjEyNyBIOTgiIGZpbGw9IiNmNmU4YzMiIHN0cm9rZT0iI2Y2ZThjMyIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTY1IiB5PSI5OSIgd2lkdGg9Ijk4IiBoZWlnaHQ9Ijc0IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iI2JmODEyZCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTY1IiB5MT0iMTI3IiB4Mj0iMjYzIiB5Mj0iMTI3IiBzdHJva2U9IiNiZjgxMmQiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTczIiB5PSIxMjAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5WSVZBTVVTPC90ZXh0PgoJCTx0ZXh0IHg9IjE3MiIgeT0iMTQ1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmVsZWlmZW5kPC90ZXh0PgoJCTx0ZXh0IHg9IjE3MiIgeT0iMTYyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlhY3VsaXM8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyOTciIHk9Ijk4LjM1IiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxMTIiIHk9Ijk2LjgzIiBmaWxsPSIjMDE2NjVlIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEJMQU5ESVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMzIiIHdpZHRoPSI5OCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzgwY2RjMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI2MiIgd2lkdGg9Ijk4IiBoZWlnaHQ9IjgwIiBmaWxsPSIjYzdlYWU1IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjMyIiB3aWR0aD0iOTgiIGhlaWdodD0iMTEwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzNTk3OGYiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSI2MiIgeDI9IjEwNyIgeTI9IjYyIiBzdHJva2U9IiMzNTk3OGYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iNTMuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5CTEFORElUPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9Ijc5LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbnNlcXVhdDwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjgyIiB4Mj0iODEiIHkyPSI4MiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI5Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWd1bGE8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTEzLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5pYmg8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTMwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb25zZXF1YXQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IE5PTlVNTVkgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzIxIiB5PSI0OSIgd2lkdGg9IjExNCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzgwY2RjMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMjEiIHk9Ijc5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjYzdlYWU1IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMyMSIgeT0iNDkiIHdpZHRoPSIxMTQiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM1OTc4ZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzIxIiB5MT0iNzkiIHgyPSI0MzUiIHkyPSI3OSIgc3Ryb2tlPSIjMzU5NzhmIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzMwIiB5PSI3MC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk5PTlVNTVk8L3RleHQ+Cgk8dGV4dCB4PSIzMjkiIHk9Ijk2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbnNlcXVhdDwvdGV4dD4KCTxsaW5lIHgxPSIzMjkiIHkxPSI5OSIgeDI9IjM5MyIgeTI9Ijk5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzI5IiB5PSIxMTMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGlndWxhPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Bien entendu, ce genre de manipulations doit rester exceptionnel. Il est en tout cas à réserver à la toute dernière étape de production d'un MCD, puisque la plupart des évolutions subséquentes de son texte-source frapperaient d'obsolescence votre fichier de géométrie.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> Étant donné que Mocodo produit des SVG, rien ne vous empêche de retoucher ceux-ci avec un logiciel de dessin vectoriel dédié, comme <a href=\"https://www.inkscape.org/?lang=fr\">Inkscape</a> (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc. Attention, le SVG généré n'est pas spécialement pensé pour cet usage. Certains éléments sont groupés pour permettre leur déplacement en bloc, mais les liens ne suivent pas ces déplacements, ce qui peut vite devenir fastidieux.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Conversion-dans-d'autres-formats-graphiques\">Conversion dans d'autres formats graphiques<a class=\"anchor-link\" href=\"#Conversion-dans-d'autres-formats-graphiques\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Avec l'option <code>--svg_to</code> suivie de <code>pdf</code> et/ou <code>png</code>, Mocodo convertit en PDF et/ou PNG le SVG généré pour le MCD.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [143]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i ccp --svg_to png pdf --select\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le premier format est prévu pour inclusion dans des documents qui ne gèrent pas les SVG :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [144]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">IFrame</span><span class=\"p\">(</span><span class=\"s2\">\"mocodo_notebook/ccp.pdf\"</span><span class=\"p\">,</span> <span class=\"n\">width</span><span class=\"o\">=</span><span class=\"s2\">\"100%\"</span><span class=\"p\">,</span> <span class=\"n\">height</span><span class=\"o\">=</span><span class=\"s2\">\"100%\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[144]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<iframe allowfullscreen=\"\" frameborder=\"0\" height=\"100%\" src=\"mocodo_notebook/ccp.pdf\" width=\"100%\"></iframe>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Attention, seules les polices de caractères les plus courantes apparaîtront correctement sur toutes les plateformes.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le second est un format bitmap, donc avec une certaine perte de qualité :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [145]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Image</span><span class=\"p\">(</span><span class=\"s2\">\"ccp.png\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[145]:</div>\n<div class=\"jp-RenderedImage jp-OutputArea-output jp-OutputArea-executeResult\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" class=\"\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlIAAACACAIAAABP1BApAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO29eTzU3f//f2axZanIkolQoZBpF5HSolQira7i0hWlq0UrqksoLeq6VJJUpBRxlUIlVLSQCvW21tV10aKSipR9eH3/OL9ev/nM8jLGjBnm3P9wG+ec12vO67zOc85rOY/zIGEYBhAIBAKBkAzIoq4AAoFAIBDdBxr2EAgEAiFBoGEPgUAgEBIEGvYQCAQCIUGgYQ+BQCAQEgQa9hAIBAIhQaBhD4FAIBASBJVbxsaNG589e9adVREhdDo9JCRE1LVAIBAIhNDherf37NkzCRn2JOdIEQgEAsH1bg8AQKfTMzMzu6smIsPa2lrUVUAgEAhEN4He7SEQCARCgkDDHgKBQCAkCDTsIRAIBEKCQMMeAoFAICQINOwhEAgEQoIgmsmJQIgQiVKOig9Iw9qDQDFCAEFPRnd7CDEF6Sm7H9TmPQt0vrhB3DLobg8hvkiIclR8QBrWHgeKEY4Q92R0t4dAIBAICaKrd3t1dXWnT5/+3//+V15eTqFQtLW1zczM5s6dq6ysLCcnJ5AqIhAIBAIhKLp0txcbG6urq7t58+bo6Oh79+7dvXs3Ojp6zZo1WlpaoaGhgqoihmEZGRk8Fk5LS2tsbGRJbGxsvHfvnqDqg0AgEIieC//DXn5+/q+//vr161d9ff1jx45lZGRcvXrVy8tLWVlZV1d33bp1sNi2bdsGDRpkamra1NTEvpO0tDQtLS0tLa309HSYEhQUNOj/oqGh4enpCXP9/f1hYlZWFr4TDw+PQYMGHThwAABw9+5dLS0tlj1oaWndvHmT7yNFIBAIRK+B/4ec27Zta25utrS0zMjIkJaWhon29va//vprVVWVrKwsTJkxY0ZwcPDEiRPxFGZmzJjx8eNHGRmZ6dOnw5TBgwdXVlYaGRlZWFjAFAaD8e+//8LPJiYmlZWVAABXV9d79+5paWkBAOh0ekREhKGhIQBASUnJzs5OVlb22bNnjx8/Hj9+PJ1Ob2pqUlJS4vtIEQgEAtFr4HPYYzAYjx49AgAEBgbiYx7ExMTExMSki9WytraGj0nr6+vJZDLLa0IVFZWKioqpU6dmZWVpamoyZ/n4+MAPBw4cePz4saOj4/bt27tYGQQCgUD0Gvh8yPn169f6+noAgIaGhkDr8/8RGRk5dOjQoUOHDh48+OHDhyy5gYGBixYtevXq1dSpUz9+/CiMCiAQCASiV8LnsKempjZ48GAAQHJyMnsu/qKObwYPHmxhYWFhYWFiYsJyNwkAoFAoFy5cmD9//osXL2xsbKqrq7v4dQgEAoGQEPif0rJw4UIAgK+v76lTpxgMBkysra09ePDg7Nmzs7Ozu1ItGxub6Ojo6Ojou3fvWllZsRegUqmXLl2aPXt2SUmJn59fV74LgUAgEJID/1Na9u3bV1JScuPGDXd39+3bt+vr6zc0NJSWljIYDAqFcvXqVXNzc7xwQUHBzp078X/fvHmzePFiOzs7bju/f/8+c/nHjx+npaWxlJGWlr58+fLcuXN5lzcgJAGkJUUgmAkKCsrLy2NJVFNTmz59uo2NTd++fUVSK1GCcWHy5MmTJ0/mlgtpb29PTEy0sbGBb/hkZGSMjY19fX3Ly8vxMriSgYWYmBgMw1JTU0kkEplMTkpKguXxOSkc6wnnpyxduhTff319vYKCAgDA29ubuW4uLi4AgAULFhAfAo9Hiuh++DsvFy9eVFZWZu8/JBLp4MGD7OVbW1sFUFfxo729PT09vbNboVjoWfB4vuDsd47o6urW1NR09nu7LWpu3brV0NDAktjQ0JCVlUW8IXHLdGnYY6apqam9vZ3Hwt+/f+9UW1dUVPBeuLOgUBdP+DgveXl5MjIyAAB2Lamenl5jYyNe8vbt23Z2durq6mQyWUNDY+7cuXfv3sVzr1y5QqPRaDRabm4unnjz5k2YmJqa2qlikGPHjsH0v//+mzl99+7dMD0zMxNPdHd3p9Fo+/fvh//OmTOHxoS+vr6joyN+pYhh2N69e2n/FzU1tWHDhnWq9TAUCz0NHs/Xly9f4CDn4+Nz/Pjx48ePh4aGrl69GiZGR0djGLZlyxbm/qOlpWVmZrZr167a2lp8P8RR02Ev9fX1pdFoZmZmzHWbOXMmjUb7/fff4b+3bt2CYuu0tDQMw7y9vVVUVFj6toqKCstNTmdbRmBLUcOfGx6B92e8A6fPIBDE8KglPXLkyMaNG0kkkq2t7fDhw4uLi5OTk5OTk8PCwtasWQMAoNFo8AI5Ojp6/PjxcKvTp0/DRBqNBlN4LAZJT0+H6VevXl2wYAGe3qEUFQAwYcKElJQUMzOzkSNHYhhWU1OTkZFx5cqVP//808vLC3SkdkUgIIsWLaLT6fAzhmGXL1+urq5+8+YNAMDIyKiysnL48OGWlpYAgLq6upycnMDAwH/++Sc2NhbwEDUd9tLp06cHBQXNnDmTuUqWlpa3bt0aPXo0/JdFyS0sHTZ/o2VvQnKOtGfR2fPS2toqLy8PAGC+bWKnqqqKQqFISUkx342lpKRQqVQqlfrlyxcMw3Jzc2F0UKnUkpISDMOYVwUqLCyEW/FYDMOwwsJCEonk4OCgpqZGoVBevnyJZ12+fBkAoKKiAgAYOnRoZWUlhmFhYWEAgKtXr8IygYGBAIBDhw7hW5WXlysqKsrLy3/79g3DsJiYGADA2rVrYe6PHz/YHw3xAoqFnkVn7/aWLFni5eXl5eW1cePGadOmwUTYzaKiogAAHh4e+FawexsYGGC8RU2HvfTu3bsAADc3N+a67dmzBwAQGRmJp1CpVHl5eZZD2L9/PwAAf/7RxZZBDgyIXgKPWtJHjx61tbXZ2dkxX3XCfxkMBj6SAQAcHR3b29u3bt2KYdimTZvk5OQWL17MvkNeisFw9fX13bp1a1tbW1BQEEuBzkpRdXR0xo4dW19fX1xcjCcSq10RiLi4uL/++uuvv/4KCQnJyMgYMmTI9u3b7e3t8QIPHjxYu3bt2rVrf/nlFzhXf+rUqaAzUcMMx14qDiC/PdHQ1NR0586dx48ff/jw4f379xwXLBU5ZDJ5wIABI0aMmDx58sSJEykUiqhrRATUkr5+/To5OdnAwIAlNz09HT42gWIbKpW158MUXIoDADA2NlZQUDh37tzy5cvz8vJ27tzJ8TR1WKy8vPzSpUtKSkrZ2dmtra0AgJiYmF27dunp6eFloBS1paXl6tWrNjY2HMdXjrS1teGfBw8eDJ+1vnnzhl3tKrb0iFjgRs+KkdOnTw8bNgwAQCKR9PX11dXVWQqUl5d//vy5ra3t8+fPAICAgAA4i5D3qOEIcy9taWlhzmpububvWLoCutvrbgoKChYvXqyqqmpnZ7dnz56UlJQPHz6IulKcqaury83N3bVrl6Wlpba29p49e+DtlNjCi5Z0woQJAIDr168/fvwY3zA7OxtOKoa5OLt375aWlr5w4YK6ujrBKnfExYKDgxkMRl1d3YYNG3x9fQEADAZj3759LMU6JUV98+bN06dPpaWlR4wYgSd2qHYVN3pQLHCjZ8XImDFjrKysrKysLC0t2cc8AIC7u/vHjx8/ffoEH4G2tLTA66dORQ0OSy/t168fACApKenbt2+wQFtb28WLFwEA3SyiQHd73ce7d++8vb1jY2OVlZVXrFgxf/58a2trKSkpUderA759+5aenh4VFeXn53fq1Kljx47NmzdP1JXiDC9aUhqN5ufn5+/vP2nSpKVLlxoaGpaUlMTFxTEYjD179qipqTHvUFdX193dPTQ0NCAggGAeFkGxjx8/RkVFDRs2LDc3F94K1NbWGhkZRUdH79y5k2WuFrEU9ebNmzU1Ne3t7dXV1deuXfv+/bu3tzezWoMXtauY0ENjgRs9KEZ4gUQiRUVFmZiY7Nu3z9bW1sLCgveoIeilJiYmo0ePzs/PHzZs2NSpU2VlZe/cufP27VttbW34KLX74O+VYG+ie470wYMHampq8vLyO3fuhC94exw5OTmmpqYAgJUrV3aDcIe/88KLlrS9vT0uLs7MzExRUREAoKSkZG5unpCQgBeIi4sDAMyaNQvDsA8fPowfP57BYMAqAQBwBQIvxRwdHQGbfhTOpps3bx7GmxSV5dZNTk5u/PjxoaGh+CbEalfeQbHQRcQzRuAzBsA06YkdaO5maWmJpyxatAgAoKqq+uLFC4yHqOmwl2IYVl1d7eXlNXjwYAqFQiaTNTU1f/nll1evXuEF2JXcEN512BDiliFhGMYxYKytrZ8/fw5PYe8GHmZmZqbwviIuLs7V1VVXVzcpKQk+W++hMBiMwMDAwMDA2bNnx8fH9+nTR3jfZW1tDQDoynlpbm6WlpYmkUgEZZqamjhaYvUCXr9+3VnlT9fbvEN6TSxwo2fFCH90PWra2tra29uFd39P3DLo3Z7Qefjwoaur68SJE3Nycnp6nFOpVH9//5MnT6ampjo6OjK/qRZDZGRkiMc8AEBvHfOAWKpde1MscKNnxQh/dD1qoBxCIJXhA6J3e8K+BxIT4HWBkHj37p2jo6Ourm5iYiJ8o9sLWLVqFZlM/u233/7444+9e/eKujqInkGvjAVuoBgRZ9CUFuHi7e1dX1//4MGDXhbnK1eufPLkyb59+6ytraEwAIEgprfGAjdQjIgt6CGnECkoKIiNjfXy8uqVz3OOHj06bNiwzZs398rHOAjB0rtjgRsoRsQTNOwJkf379ysrK2/dulXUFREK0tLS+/btKywsPHfunKjrghB3encscAPFiHiChj1h0dTUdPPmzUWLFnV11VQxxtHRccyYMSdOnBB1RRBijSTEAjdQjIghfA57mpqaVCpVSkqKRqMtX778/fv3LAU8PT1VVVU/ffoE/y0rKxs6dCiJRMIVJB1SWVlJpVIjIyP5q6HIuX379vfv3x0cHERdEeHi7Oz85MkTtNg/ggAJiQVuoBgRN/ic0sJgMLS0tGbNmpWXlxcTE/P27VvmOZ/fv38/f/58VFQUrt738/N7/fr10qVLoasFL2AYBrUdJSUlRkZGwcHBW7Zs4a+2IuHJkycUCoXjGlG9yezYyclp06ZN169fX79+vcB3/vz5c6HOs0WwICSpLkEsRERE3Lp1CwDg4ODwyy+/CPyrxQEUI90PcU/mfyanvr5+WFhYe3v75MmTs7KyPn/+PGDAAJj15cuXkJAQJycnvHBOTs6UKVPg8mudZciQIatWrZo1a1ZnN2QwGOnp6XxsKBDev3+voaHBcUVgV1fXHTt2sKeHh4fr6urm5+fzPtWtubmZSqVyWwCXOBcHw7Dbt2/jRiSdQktLq3///uhKFkEAQSxMmjTJw8MDAHDgwAH+dt7a2ioOq5oRBBGKEXGjqwIGMpk8cuTIBw8efPnyBR/2dHR0bG1tGxsb5eTkYEpVVRVcpYkPZGRkIiIiOrsVhmFubm7y8vIiHPYGDhzIMQsXe/r4+AwaNAgAgGFYUVFReHh4eXl5UlLSihUrYIHQ0FBoNHXkyBFmb9KamhofH5+rV69WVVVRqdSRI0c6OjpaW1tDl1Hi3KCgIGjnhtPa2tq3b9+XL18CALZu3QpdJSFkMplGo02fPn3z5s3cbkOh7wGfzUSIhChHxQch3TcQxAI+FuIf/P39T506BQC4cOECXOYNAODh4XH9+vV169bhK30nJSWFhITk5+fX1dUNHjx42rRps2bNmjZtmpKS0rZt2y5evKiiopKbm8surN6xY0d0dLSWllZOTg6eaGtrW1RU5ODgcOzYMcBDFBAHETsoRroZ4p7cpSkt9fX1jx49unr1qrq6ur6+PkzMzs7W09MbNGgQ7H8AAEVFxZaWliNHjhCPQI8fPzY0NCSRSCQSydzcHE+vrKwkkUhnzpxh3j+JRJKSkoL7LykpIZFIdnZ2ioqKJBJp2rRp9fX127ZtO3/+fHh4OLQD7sph8ge+siIBixYt8vT09PT0XLt2bVhYmKqqKgAAmh1DoCV3ZWXl1atXmTdcuXLlyZMnR40a5ePjs3z58oaGhp07d0LDxg5zoRN3v3797H4yZ84cTU1NmAtNlqGpsZ2dnYWFxYcPHwIDA1evXs3tKPr164cvqY5AsMNLLOBAu/nKykpXV9e3b9/CRDqdXllZidvN+/r62tvb5+fnOzo6bt261cjIKCoqyt/fX0ZGBgAwY8aMyspKfX19jouJTJ8+vbKyktm5AgBgaWlZWVmJe3x3GAXEQcQOihGxgv+7vbS0NNiV+/bte+HCBbgK1Ldv3+bPnz9gwIDIyMinT58GBwc7OzsfOXJk5cqVtra2BI+2a2pq5syZ09zcvGHDBjk5ufT0dDwLrhoK/3LcP/R8Kioqio6Ozs/P37t3b0RExNChQ+Xl5UePHu3s7KylpcX3YQqVAwcOwKtgeLdXXV0NADAxMYG5RUVFycnJDg4ODx8+jI2N/eOPP6Dmqb29PSUlBQDg7u4+c+bMPn36YBh2+PBh6ABJnItjbW0dGhoKAKivryeTyfh9OcTKyio8PBx+fvz48YQJEwoKCoTcGAjE/4+KikpFRcXUqVOzsrJYhpPnz5/v27dPU1MzLy8PtxS+fv26rq4uHPYERYdRQBxECLGF/7s9PT09Dw8PRUVFaWlp+KQOAJCWllZdXe3g4KClpTV//nx5efnExEQ3NzcymTxmzBiCu72UlJTq6urDhw+HhITs27fv6dOnHItx3D/MCggIcHR09Pf3l5eXLy0t9fDw6NOnj5GRkYeHx+zZs/k+TKFCbHbMzZKbTCbDMo6OjgoKClpaWvPmzevbty+8gCXOxSF24uZmsoxAdA8EdvNZWVkAABcXF3zMAwDY2dmx9PCu02EUIDv7Hgr/d3tDhw4NDw9fvXq1paWlvb39//73PyUlpcrKSgDA3bt38/PzAQCWlpY8mudWVFQAAGxsbIiLEeyfTCYDACgUira2dk1NDd/H1Z0QmB0TW3LHxsba2dllZGQUFRW9evUqJSUlJSWlpKTkr7/+6jAXQuzEzc1kGYHoHgjs5tvb2wEPjt7E8OLx3WEU9FA7e0RX5ep0Ov3YsWOvX7+GgryRI0cCABYvXnzzJ7t27eJlP9ra2gCAmzdvEhfjZf/4ovsUCoWlc4sbBGbHxJbcv/7664gRI2JiYp49e/bt2zeobsQ9RYlzIcRO3NxMlsUHTU3NcePGNTY2sqTT6XSWx7mSxooVK/AX7T0abnbzkyZNAgCcPXv23bt3eGJGRsZvv/3Gy2559/juMArE3M6+G9TVXUGEHVUAS1G7uLhERkaGhYUtXbrUzMxMV1d3165dpaWldDr9/v37AIALFy7ghd+9e+fq6rpp0yaWB492dnYqKire3t4FBQV0Ov3hw4cHDx5k/y6O++d2kgYMGHDr1q2oqKgHDx7gM2J6BMSW3NLS0pcuXYqPj58zZ864ceMYDMbly5cBAFOmTAEAfPjwgSAXhxcnbnaTZWEfOO8wGIynT5+uXLmSRRXDYDAkfP3Dtra2Lt4JiQ8c7ebHjh3r6ekZFhY2cuRINzc3RUXF/Pz8GzduMBiMWbNm4ROeCwoKmHv4mzdvFi9ebGdn11mPb4IoEHM7+25QV3cF4o4qXLk2f+60ampqM2fOxP/9559/+vTpM3To0MbGxrKyMisrK3hZNGTIEOgxTaFQdu7ciWHYo0ePKBTKnj172Pf56NEjOp0OZ3IOGzYMXsqdPn0a/wCLse+/uLgYAHD+/HlYwMjIaOHChRiGJSQkwEeCRkZG3A6kwyPlG2tra2tra45ZHZodE1tyf/78+cyZMwsWLMD7q6amppeXV1NTE4ZhxLlYR07cHZosd+pIuwLxeYGzXgEABw4cYE43MjKysbEReGV6EMuWLdPV1eVv2+6PBVyu9+eff8IUXuzmGQzG6dOnTUxM4O+AmprakiVL7ty5U1tbi2HYunXrOPbwmJgYuHmHHt8dRkFn7exFFSMzZszAMKytrQ3eIldXV+O55eXl+I8qREtLa/r06QKvJDeIO2pTU9OqVauKiorgv62trTdu3OB958Qtw+ew1yENDQ0/fvzgmPXt2zeCDb9///79+/eu7J+Fmpoa4gLdH+oCpKmpqbW1lb9cZioqKviug6hC2sbGhkajkclk5niQ5GHvw4cP1dXVPWvY6yIMBqO5uZmXkt+/f2f/KWAwGC0tLYKqDEEQiXbYw34O5GVlZcwF3r1719DQgP8rLS29YcMGgVeSnc521Pb29uXLl69evZr3ryBuGWEtRS0nJycvL88xi3g5WgUFBV4kPgT7Z6F3m3vJyMhA/QYfucyIoRN3h2hqaiYlJcnKyi5btoxFJgylnH///Tf819DQcOnSpQCA/Px8Eom0cOFCKPF0dHRMT0/X0NAgkUiGhoZQQMINdl1pdXW1i4uLurq6goKClZVVbm4uLNnht/BSjezsbG1tbRKJpK6uDt9scdSnwm8sKioyNTUdOHCgqqpqfHw8TGRXuPY+KBQKj2+dFRQU2H8KBOvxLZ5BJEB1dU5ODuz/ffr0MTU1PXHiBJxeRCKRdu/ebW5uDrsl4B4aHDsqx2hllmsLXITNz7u93bt3d/2LRULPrTmCI6NHjz5//ryTk5O9vX1ubi5+RYUxaT3Bz0dPeEppaWlsbGxKSsrJkyczMjIOHTpUVVX1xx9/XLt2jdu0CHZdaUtLi42NTVlZ2fz585WVlS9dumRlZZWXl2dsbNzht4waNarDasBH9Nu3b7906VJAQMCSJUvgbln0qV5eXg0NDXPnzq2trd2+ffvYsWMDAwO/f//OUeEqjPU2EeKMYNXVsAe6uroOHDjw3r17np6eNTU18JXN3r17FyxYQKPRZGVluYWGnp4ee0cFXKKVOVHgImxkPITo2Tg6Ou7du7esrMzZ2Rlee3ZIUFDQnDlz4DXQb7/95u7uDpUhqamp3DZh15UmJiYWFhYePnw4Pj4+PDz84cOHLS0tzPOwOvwW4gIuLi63b99eu3YtHImrqqrgViz6VABAZmZmRUXFtm3b9u/f7+TkZGxsDAgVrgjJQbDqaoiDg0NQUFBWVpa5ufmRI0dgopmZWVxcXEJCwvnz57mFBseOygsCF2FL1t0eolfi4+NTWlp6/vx5FjULfv3IEQ0NDTk5OVzuoqOjwyKLZoZdV1pWVgYAmDdvHvx3xIgRw4cPh+NQp76FWwE6nZ6YmOjn5wdFY/j0VHZ9KpzzxbIIMt8KWkRvQrDqamYoFMrEiROzs7PhvzNmzMCzuIUGx46KQxytggXd7SF6A6dOnbKwsAgKCiopKQE/BVj46qbc7gLxwaZD2HWlOjo6gEkN+fbt2xcvXsBinf0WjgViYmKcnJwCAgKuXLlCvJWuri4A4MmTJ8y5fCtoEb0PQamrWUhLS1NWVoafmZc/5RYaHDsq4C1aBSvC5lO3p6mpSaPR7t27x7IMHZ1OV1dXhwZaiGfPnkmCFdbz58+huEKEyMjIJCYmjh8/Ht6W0Wg0eXn5CxcuGBoaZmVlvXr1asyYMbzsh3ddaVhY2KBBg7Zs2ZKfn6+pqXn27FkMw9auXSuoI8rMzJSVlTUyMoqLiwMAFBcXc5u7YW1tbWBgEBgY2NLSQqPR4M9HhwrabkZCYoEbIo8RgairIdeuXWtpaYmNjS0sLOQ4Vcre3p5jaFhaWrJ3VMBbtApWhM2/zWxvEgtXVFQI/Mkt/P2VEITUgPCykSNwRhlziqqqanJyMpxORiKRTpw4sW7dunnz5s2YMUNVVRUWZv7LshP4ubKyMjMzc8qUKSwBP2DAgOvXr69evRqG3NChQ/v165eWlrZ69eqIiIj29nY9Pb2EhASod+7wWzosAABwc3O7fv36uHHjHBwctLW1d+3ade7cOY5bSUlJpaamrl+/3t/fv7a2FgCgp6fXp0+fmzdvuru7R0VFtbS0DBkyhEdDOxQLQkK0MUIikSIjI01NTV1dXQsLCzn2Dbw8tyiAXLx4MTIyUk5Obt26dQEBAfj+8QIEocHeUeG27NHKEiN+fn7bt293c3MzMjLqeruRuD1RhZdm3Jyc1NTU4DTrAwcOMA/4xsbGGhoazEsqiD/W1tYVFRWurq6C3W10dLSOjs7du3cFu1sxZMqUKRUVFS4uLoLd7dmzZ3V0dLriJcZgMOrr6zvrVl9XV0egsfnx4wcAgFlj09jY2NzcLAydDLyIlJGRaWxsJJFIHG10OqSxsbG9vZ1HtQ+KBSEhnjFC0Dc4RkF2draFhcW1a9fMzc379+/foX91p0KDl2itra3lcW/E4xf/i5PBKao+Pj4mJiaisnIVFDo6OgK/EIPrxEsIwmjArptnUqnUzo55gAddKUuKnJyckBxnqFQqlF12Zf+d3RbFgpAQwxgh6BvEUYA7ine4f967Hy/RKqiLS/6HPU1NzYMHD1paWi5btiw3N5dlUdHq6uotW7akpqbW19ePHj06ODh4woQJAID8/PwxY8Y4OTmlpqb++PHDwcFhzZo1y5cvr6qqMjAwuH//Pr7oFALBDTSXuOugNuzdCOP8Qtff2NhYOAVUtHTlALs0kxOKhb99+2Zvb19XV4enQ7libGzs5MmTf/nll8LCQisrq6KiIvB/9cIeHh6JiYkLFiwICAgICAh48eLFtWvXulIfBAKBQAiJ/v3729rasnjF9ES66sAAxcK+vr7Ozs74oAXlikePHoVrwq5fv97IyOjgwYPwnTz4KdQdO3bsyZMnoVAXAHD27NnU1FQe3UMQkgy6U0EgiEExQoAAjIfYxcKCUvIiEAgEAiFYBCNXZxELC1DJi0BwREVFBc74kJKSUlVVpdPpPj4+cEETRM+ira1t//79w4cPl5KSIpFImpqay5Yt+/Dhg6jqw2K+2nPp27cv9Etip6CggEqlpqSk8LKfyspKKpUaGRmJf2DO7YnNJZhhD4qFdXR04Ks7XK64Zs2awMBA6LghQCVvN3D//v1BgwaRSKSxY8e+fv2aOaumpsbAwIB5tZem1nsAABSjSURBVP7W1lYqlRobG9vt1RRrXr161adPHwqFcuPGjc7mdgiDwaDRaKtWrXJ1dZ0yZcrHjx/3798/duxYXAOLEBQEZ6rrsdDU1DRp0iQfH59Pnz7NnTvX1dW1X79+sbGxRkZGjx49Etgx/AQu9n/o0CFuBaD56okTJ3C7SuEh7B8ZBoPB4uOKH357e3tbWxuPa9hiGAYL4x/wrO5sLgHC57DHTSwMLVGgXJFOp0dERPzxxx8AAN6VvHwfiQBpbGxcuHDhqFGjMjMzGxoaVq1axVLg5cuXs2bNgsuHQ3jvQ5JDe3t7WFgYjJbO5vICnU4/ceLEqVOn4uPj37596+np+fr1a/aThcNgMJhXF0PwCPGZ6mIsBAcHP3r0aNKkSSUlJVeuXImKiiouLg4ICKipqXF3dxfI2hfM533IkCGrVq3CBVfsXeLLly8hISFOTk5d/15iRPIjw3L4Xafbmkuw8PluD18PnhljY2N8Pufw4cOzsrLY5YqjR49mDh4o/oWIj8g9MTGxqqrq0KFDBgYGPj4+K1asePXq1dChQ5nL5OXlzZ8//8aNGzIyMqKqp5ijr6/fv39//nI7i5SUVGhoaGFhYVpa2ocPHwYOHMhSAMMwNzc3eXn5nq4x7X46PFN8x8KPHz/279/fv3//xMREXApGIpF27dpVVlZ28eLFuLg4Z2dn/qvOdt5lZGQiIiI4ZkF0dHRsbW0bGxuFpMXEEcmPDH74eXl5MKW+vv779+8aGhr87bDbmkuwCHcpajk5uZ7o8vry5UslJSWoRBw7diwA4J9//mEps2/fvoKCAt7NbhDChkQi+fj4AACysrLYPVrZnSolwYW1e+A7FoqKihoaGlavXs0uf965cycA4PHjxxw9SNnPL+Biw8ty3onNS9nNV4WHSH5kmA8fABAQEKCurj5w4MDp06dDNw/QmbjozuYSLMiBgQM1NTXwmTv4ubw9+1yJ4cOHX7t2LSUlBVrdi6CWCDZGjBgBAHj48CH0aA0NDTUwMAgICCgtLYVOlZaWluHh4evXr4dOm7KyspGRke7u7sHBwc+fPxd19XsqfMcCnAEHDQFYMDAwkJaWLikp4ehByn5+8TLQhnfHjh23b9+OiIhgOe/s5qWi6hIi+ZFhaczPnz/7+vrOnTs3IyNj+/bt4KcDLS+N0KMjCA17HNDQ0Pj333/h22AYUewPzQAAlpaWMTExZ86c2bFjR3dXEcEJKIBRUVFh92hlcapELqyChb9YgM9Ov379yp5VU1PT0tLCbREsbh68gM2Gl8ChVLRdQhx+ZI4ePerr65uUlDRq1KiEhATQGXfiHh1BAtDt9T4MDQ2bm5uLi4tNTU2fPn1KIpFYll7DcXJy+vPPPzdu3NjNNURwBJqnjBs3jptHKw5yYRU4fMQCnU6HDzDXrFnDMp0NWruMHj0a/styr0NwftlteHmkm7uEWP3IWFhYFBQUgM40Qo+OIDTscWDOnDk0Gm3jxo2bNm3au3evnZ2dtrb2zp07zc3N2Z04NmzY8Pbt28OHD4ukqj0Lbm0oEOLi4o4fP25hYTFr1qyYmBgXF5fLly9raGhMnDgRFmB2qsSdNjds2ABTGhoahFGrXomgYkFXV3f58uXnzp3buXNnQEAAvqJ/RkaGt7e3mpqah4cHnCXH4kHK8fyygI+jBA6lIuwSYvUjc+fOHXivybERON6O9+gI4nPYw7uUjIyMgYGBn5+fo6Mjt8Kenp4JCQnFxcU9RdshJSUVHx/v5OQ0b948Op0eFhZWXV0dHBwcHx+Pl2G+OA0ODobXPsz07dtXQjRkdXV1gwYN4pjF3ErEbcgHpaWlu3fvZjAY1dXVT548KSgo0NfXj46OJpPJ7B6tJiYmzE6Vx44dEysXVjGH9/PY2Vg4fPhwWVlZUFBQSkrKjBkzFBUVnzx5kpKSoqSkFBsbq6SkpKioyO5ByvH8cqs883n39/fnliXULsEeIwL5kemQ4uJiODkIAmfu4Fy+fPnTp09xcXElJSVQacbRgZajU6O4+Rh3DowLkydPnjx5MrdcAMDw4cN///33yZMnUygUKpVaXFzMsWRdXZ2CgkJCQgK3XYkcbkfa3t7+6dMn+PnQoUOmpqZQusSRpqamly9fMqesW7dORUVFoDUVU9TV1eErd2I6bEMWiHugsrIyhUKBfU9OTs7AwGD37t2NjY0w9+HDhxoaGn379nV1ddXW1lZSUiosLITzIAAARkZGGIaVlZVZWVlBy/IhQ4b8/fffPFasF0Pc5hCBx0JDQ4Ofnx88NZAVK1bAySyQc+fO9e3bl0QizZw5U1VVdcmSJRzPb3FxMQDg/PnzcCsjI6OFCxdiP+e/wPP+7t07AMDp06dhmW7rEtxipIs/MsTni91ILyYmBh7+f//9Z2hoCBMVFRW9vb2bm5vhVuyNgDcaS+uJcwR1MH7xuRkAv/32G/wcEhICANi/fz/HkuXl5XgziSe8hPrq1asvX77cqd3CZnn79i3/NesJNDU1USgUf3//Dkt2tg15OS8EtLa2NjU1YRjW0NCAD4cYhtXU1DAXa2ho+PHjB9/f0ssQYSy0t7efOXMGzmExNjbesWNHREREQUEBzG1tba2trWUuz+38coPlvBNkCbxL8BgjfDRsF2OkoaHh48eP3LJ4bATxjCDilhHATE742pl5HR1mcD1j179IhJw4cYLgKS5H5s6dSyKR4PyoXsydO3fa2tqgmSIxfLRhV6BSqVDkKycnx+xLziIklZOT49F5HAERUiyQSCQ3N7cXL17s27ePQqEcOHDg3r17+KNLdg9SbueXGwQCYmF3CR5jpJsDBAAgJyfHzUWI90boiRHU1WHv9evXoaGhAABzc3MSibR79274Ydq0aYCTnpGjpBTuqrq62sXFRV1dXUFBwcrKKjc3FwCQn59PIpEWLlwIyzs6Oqanp2toaJBIJENDQ25jrTigp6c3evToHvOwm1+SkpKUlJSmTJki6oogxBfeY0FZWdnb2/vZs2f19fXnzp3DJ7n0aFCMiBv8D3tnzpyRlpbW0dGJj4+fPXs2fFm6d+9ebW1tJyengQMHctQzYpwkpYC7My3Wk21pPT098/Lyrly5IuqKCIva2tr4+Hg7Ozv4fB+B4EZnY0FaWlpMVujtIihGxBH+no0CAExNTXft2hUeHn779u22tjaYOGnSJLwMnJLk6+ubnp6elpYmLy/v5+cHPdbPnj2LYRiDwZCXl1+1ahWGYXBG1tGjR+G28O308uXLnz59CgC4du0ahmHQi8TLywuW0dPTW7BgAc8Pe7nSxefjBDAYDGNjY319ffx1cS/D29ubTCbDqxmBI7zzguAGigWBg2JEJBC3DP+6vXHjxgUEBLAkzpgxA/9MoGdkl5Ty4kzb42xpKRTKn3/+OXPmzPXr14eHh4u6OgKmtLT0yJEjK1as4Li4FALBTO+OBW6gGBFPBLw4GfO7ZVzPePMnuP06DvMYBnhwpu1xzz2mT5/u4+Nz8uRJfPnX3sHXr1/t7e379esXFBQkkgrIysrq6+sz27IAAJ49e9anTx87OzuRVAlBTG+NBW6IPEZIP5GVlTU1Ne3Fb1s6ixDX5MT1jKtXrw4PD3d2dibwQusFzrTcCAgImDlzpoeHx+nTp0VdF8Hw9evX+fPnv3379sqVKxwXEuwGWltb//nnH+Ye0tDQsHTp0sbGRoGYtCGEQe+LBW6IQ4yAn+pqMzOz4uLixYsXw7W/menQd5dvOrVn4VWDI/wPexxvvJgT+/Tpc/PmzVGjRkVFRa1ZsyY3N9fR0ZGbzSw3Z9oeYUtLDIVCuXLliq2trbu7u5+fH4vfcY+jtLR0woQJT548OX/+vJmZmWgrc/78eXx+oJeXF3xUzh98m9Ai91re6WWxwA3xiRELC4tjx45lZmYePnyYwWAkJyezFBC48SzHPXcYI8KrBmf4eyXYKTqlZ2xoaCAQlgqD7nkt3Nra6ubmBgAwNTXNzs4W9tcJg5qaGm9vbzk5uYEDB+bk5Aj76zoQnJLJM2bMgCt0/Pvvv5cvXwYAODg4KCsrz5w5s7Pf1d7evnz5cl7WmhHUhuIJioUuIlYxApgWFbl37x4AYPPmzcKuEjsiiRGhrNLSm+jOI01KSho8eDCZTLa1tb106RLLwhPiSVNT082bNz08PJSVlclksouLy/v377vhezsc9pYuXZqTkyMlJWVqaqqsrKyjo1NTU6OiogKHvU+fPq1YsUJNTQ16qj169AhuCCcJz549W0FBAQBgY2Pz48ePLVu24BeCM2fOfPjwoZaWFgBATU3tjz/+4H1D4beKcEGxwB/iGSP4sFdRUbFo0SIAALw69PPzg+t329jYMK83Nn78eFlZWThaf/v2zdDQUEFBobS0FN8hDAF8pUkDA4MlS5ZgXEID3zMvwcVcDZYaYhj28OFDaElIpVK3bt3a9ZZBDgzdyty5c6dOnRoSEnLixInFixeTSCRdXV1VVVVFRUVRV40DNTU179+/r6qqam9vV1JSsrOz8/b2Fqs5aWZmZgcOHNi0aZOUlNTNmzfx5TagDLSsrGz+/PnKysqXLl2ysrLKy8szNjbGmJSj+fn5e/fuxc1IR48e7ezsrKWlBZdq3L59+6VLlwICApYsWTJ8+HBeNhRlW/Q0elYscEPMY+TMmTPR0dGtra0AAGZ19YIFC2g0mqysLMZkPHvt2rXx48fb29vn5OSsX7/+xYsXV65cwZfuBGwutfjgyjE0Fi5cCLN4Dy58z8w1hPrvAQMGREZGPn36NDg42NnZ2dTUtCvNgoa97kZeXn7Hjh0+Pj6PHj3KysoqLi7+/PmzeM7C0NTUHDt2rKam5oQJE6ZMmSKeelsvL6/s7OxJkyaNHz8eT0xMTCwsLDx69Oi6desAAOvXrzcyMjp48OC5c+dgAWhGam9vHxISUlpaGhERsWvXLug4CgDQ1NQ8dOgQhUJRVFS8f/9+VVXV8OHDedkQ0Sl6UCxwQ8xjZOTIkfPmzaPRaMOGDbO2tobKMTMzM6iTBgDA2yyIhoZGcnLypEmTRo4cWV9fv3fv3vnz5/P+XSyhgad7eHjwGFw4zDVMSEiorq5etWqVlpbWoEGDoqOjExMT0bDXIyGTyebm5ubm5qKuSG+AfbHHDmWgxGakwnAxRXADxYLw6FBdzYKpqemaNWuCg4NpNBpcTpId7P9a/uLwGBodWkADnvXffIOGPUQvBJeBQs0MlIFyvHTlaEYqKBdTBEIMIVi5+/Hjx8eOHVNVVa2srNywYcPx48eZc+Fq4CyWv+ywT7DvbHBx1H8L0M+2S8Meg8HQ0dExMDC4ffs2tzIrVqx49OjRy5cvu/JFCESnwGWg+fn5mpqacDE8Yhkos+MoVPjy4WIqIUJsRK/k/fv3cC7006dP/f39w8LChgwZsmnTJrwAjUZjt/zlZc98BxcQjp9tl+TqKSkplZWVd+7cYVdB4rS1tfVWdQ5ChHBTbcJ0bjJQ8PNSlF396efnJyMj4+bmlpub6+bmpqSkNG7cuP/++09bW3vXrl2fPn3iZcPuOHIEgmc6VFcz92oHB4evX79evXp14MCBx48fnzVr1tatW69fv85c+MSJE+Xl5fPmzSssLFRVVWXenCU0mBP5CC78Sznqv7vaLNwe1FpbWwMAMjMzCTaeNWtWamoqAMDT05PldhjH2dk5Jyfnv//+62JFhQcvR4rofgRyXhobG5ubmwm81liora2FhRkMRltbm4yMTGNjI7w+5XHDHg2KhZ6FSM4Xg8Gor69nsT/kBb6DC9LY2Nje3s6jtx9xy/B/t1deXn7r1i04/fTcuXN1dXUsBT5+/AhfWiIQokJOTq5ToxFeWIAupghEb4Ld8pdH+A4uiAD9bPkf9iIiIjAMW7ly5Zo1a378+IFPDQcAFBUVmZqaDhw4UFVVFdoPAQC4mdCSSCQpKSk4a6itrW3OnDlUKlVBQWHZsmUcUzhuiEAgEAgEL/A57LW2tkZFReno6NjY2Li4uMjLyx8/fhw+L21oaJg7d+6bN2+2b9+ekJAwYsQIfKsOTWivXbt2/fp1KOWpqKgAALCncNyw6w2BQCAQCEmAz2EvMTGxqqpKTk5u8+bNu3fvVlZWLisrg/M5MzMzKyoqtm3btn//ficnJ2NjY3wrKEJMSEg4f/58WlpadXW1g4ODlpbW/Pnz5eXlExMT9fT0AABpaWkLFizIzs4GALCncNyw6w2BQCAQCEmATwHDyZMnyWTy+/fvIyMj8cTQ0NBp06ZB2T98jMlChyJEOp0eGhq6devW0aNHnz59etmyZewpwlAvIhAIBEJC4GfYe/ny5d27d5ctWxYTE4Mnzps3Lzk5+fXr13DN0CdPnowbN45lww5FiK2trWvXrrW1tV26dKmrq+v06dP79evHkiIM9SICgUAgJAR+hj04meX3339nTty0aVNycvKJEycCAwMNDAwCAwNbWlpoNBou6WeBowjRxMSkoKBgyZIlOjo6+fn5P378OHPmDEuKMNSLCAQCgZAQ+Bn2zp49O2bMGBb7RGtr61GjRp05c2bPnj2pqanr16/39/evra0FP9/PAU4iRHd396ioqJaWliFDhhw4cEBeXj40NDQ+Pl5ZWXnnzp26urrwISdzCgCAfUP+GwCBQCAQkgQ/wx43NR582QYA0NHRSUpKYsll18UbGBhkZWWxiBDfvXv3+fPnfv36UalUAICtrS1LCrcNEQgEAoHoENEvRS0nJ8eSMmDAgA5TOG6IQCAQCAQxXVqTE4FAIBCInoXo7/YQCG48e/YMrq2H6B6ePXtGp9NFXQtEJ0AxwhHinoyGPYSYgn5/ux86nY6avQeBThY3iHsyGvYQYkpISIioq4BAiDUoRvgDvdtDIBAIhASBhj0EAoFASBBo2EMgEAiEBIGGPQQCgUBIEGjYQyAQCIQEQTSTU0IUIUirhEAgEJID12FPckYCpFVCIBAIyYHEvkI0AoFAIBC9FfRuD4FAIBASBBr2EAgEAiFBoGEPgUAgEBIEGvYQCAQCIUGgYQ+BQCAQEgQa9hAIBAIhQaBhD4FAIBASxP8DQtV/SNcGr9UAAAAASUVORK5CYII=\n\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mentionnons une possibilité amusante, actuellement non intégrée à Mocodo : <a href=\"https://fskpf.github.io\">Svg2Rough.js</a> pourra donner à votre travail une touche finale plus informelle, dans un style « tracé à main levée ».</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [146]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Image</span><span class=\"p\">(</span><span class=\"s2\">\"../examples/svg2roughjs.png\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[146]:</div>\n<div class=\"jp-RenderedImage jp-OutputArea-output jp-OutputArea-executeResult\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" class=\"\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnIAAAB+CAMAAACXrQz1AAAA+VBMVEX///8AAAD9/f0HBwf6+vrv7+9MTEyfn58NDQ0hISFISEjn5+fd3d04ODjQ0NDY2NgsLCzGxsaGhoYmJiYXFxff39+urq5XV1e6urpAQEBERETV1dVmZmbs7OyioqISEhJjY2P19fVpaWlgYGCTk5N+fn56enrj4+P39/fCwsKQkJDz8/Orq6txcXFbW1uKiopUVFS/v7+NjY2ZmZlRUVExMTF0dHScnJyWlpYpKSnp6emxsbGBgYE0NDRubm63t7c8PDx3d3fx8fHKysrNzc2mpqYbGxvh4eG0tLSoqKi8vLykpKTa2tqDg4Nra2sdHR3S0tLFxcVdXV05thBaAAAszElEQVR42uzaZ2/aUBQG4PdcbPaGmL0aB8JeCVAgzLJCSUn+/4+pF47VFqmVoHFVP9+MEEaHY9/j9wKLxWKxWCwWy7+OEwuwWP6iI8VhxBUWfMZT2tx8DaT8X5ah1/ZzfDoSart91tHvDsRKMxwe3xXnvfrkJZ2/bcRiD3a7O5mY+Z4eg58jrnU050wvYLGcE6AtGP81NOqHJ7GZy0Z/wObMrV2R4OOTL5F02x9ijdv8p0m916AVLJZzbijhVvss+uhuTMaVQdeR3e9qwmgaf26XQ8sv/lTgq3dT8niGmQzPL6qFwj3HMYazvDSCxXJOich3e1iFPAyXkqIpLJZzhpTFhfmpDYvlHJ4cuLAQvcJiOadKXVxYmZawWM65JxEX9kx+WIyGW/zXPAEYMOrgwqYUgMXoQAz/HMa4+0J1wfOZoUcKajebksSjGA6HGQmvWPBqkOuVktyjEuWW2/H4dCuFuSslzE3hzQcjauLCRuSF2XD4SPUoTI7x3uV0L959arkTvmBk7bTRxRRhT8KIDj+eHSgx/GQ3rbwlffZiCDgWoOHxCzW6gcm8kjgVdtn+oBIeF3sv6bfYgzsxSygJdkuOsNNyhj0v3o0P4WZHHHT7Uji5qgnCaKvEk69yPuk/ygnlzaYkJZRyPskxrrDIDEs33kDKvwxJ1/Z2JJ3EIZ2lEz7cFXv1l/RtQ9qdcVMQZsWF82LdHiGVMzKTSiJVRC6IVI+xWg1HdlWT7Ha71Wq13++zEoeiL9FrNY3HT6UyVKrK4IvByHaHd16x9Zbb+WkMlfDgTtob84EHXjrx1sjNoNhSH2y2nrVirYdWflKMQ7YiD8wlo++WRL+5PgfV3RL5S9vd2l6dsln3LRrNOW02uqic6ylBSZhVkYhciUavs38+ehiuI/IJRs4idCuS1beUPr2XVDPcEDXEkdBJ56sdojAUewqCm5FuDVmWhjAZB+0XDL+PFeT5pKTMJym/NqA8KwPKaUIZDMRKRRz0tb2a7VS9wpVboXx9yzfCe45B5ovBrDb0xHBtufm5Q5EoLeQpL9ALVDfx9jdqNos1LCgHTZ9IS94CRPfgUu1pgz7FhWxXfdVBPEymTF/wgSJpmFYwj6ujMIzW9fffhQSAZQMrmkDnog0kC4pCI5CN1hlIGFEJsorxQ7tkun+SxCmFD5Sbw7RcL7i2Aokwck2gqrqof1qG6tDZKAOJhyLvv19jTkkOkigFtLW0B92ATPcXvA9+iKYwTCvaw7UNKfvr0a5ISQZFl+bQkdpAAcodXlq+tTOLZ8ozt3ojfKSjFsXdQlchDiazoxL+lKnj9sux3eHavCTAKJjWV9CjPtONccKIGCRb0mxRpjT4iBKu+LQFa0l26DrmCz4/9okmQw6YFoVxbX6Kw+jx9lSXHIOqSR3otJaL05NjuvQuAKXlELBRE0hoLfeVfNA1CWbT/3m8ZDirevZYtwhAwxUAFMoMJ9690HvwJRtdHpoN1WBWHFWgWdTEQZmDZMOzc91Twp8LUQhGTw0o2pSE5kAD6GzqMvn+FCsvrEoPUgVJbZYrGcPOsPlaTqR7/BQ/KiUMJ52RtxqDLPC5C8mrLYwfj3XdNiQsQmWoHr9zd6Z9iSNBGH+ehDNcQYKIIKdccohyjKhcHjiOB67f/8MsdBKM9Di4v9UdZ/+vbAYYUlS6q56uLuZ5wMPYtQsmOVoUYBHh191jdZR1JLhAvwJGpNrNiOtZs9ElWbiHxVMrD0FN24sXNU1rF7a+SzqtcJUn2Dg1owjpFv9+qJSd4V7WjOUaHL2kD8/mI+x4GLSmSP+XdrljKpDkRyEsmmjCvgX6XML0PgXyWOCl3wo3jFMIZtwGDJLGgTmTpqmXr8fecuLsTyggdCz6A+6PDKop+LmklwKwZqMMF7SjEDzyEoIifzRocSTrtNheS94mbQgUP5uK8tQmbwocA1AiYXOWq+frwA+mX9K/hGV+0nqzKlWsOFfx1dgiIMmPwAE5+nHztJ81AxqDDAOKj4xDGgsiKhkwb0R6FMveD8Cc5wPSJ5ysTC/kheWrUuE1LPwqoBwygSEjkZJBNQys2eiOyRzJhBAx2vadlODYdbTzwMlJqXwq67S4YwBOkt3VeklfllTv0OK37ydFgwzsdIdccoIUY0/xYCRcq+KORVsNIQN/hMstP5IkPyJMNqyHsgDiJL1i8eAO1scC19D+e0CVx1bkWgD8DChHGtk3Xe4PquZyZJNGFoDCGTReAq4cdQVrNrrlCHuHPs4iADy2y3WFTW7NSELSaWWhdtcDi5qfzBYrQJ8CNe1qWXuT11B0mnyDlyX7ne0lx+XPYUXp67lc2QdI8iN2V4bx0Q2ckcwBU5L7gDQW1xsrm68J8bvPdL4Mi8BAiDDfhIuO2PiDqrkiHMNCjYkgwIOkuEVcPsbXbGRF9IEhB3WHyyXFCtsxtVlJp5UlDE3DikDc/BjaJDHdr1WBvR/hUwWCYL89jOnDbgWBURwWQduWivLq+/1q9A1Akh9T9F3ARGcKKDHJGRSDaRYAeYy4yugOhb0mDNao3gv1KAHovLGcNI4WW9Oipvv0Kiy2v2A1l02YP1a5awiB6xkziPHGvNr4uo3OTEtcJDkCurbL6bwHcGDORLJOiwfiFR4NH8KXdrnRHJDkx20+w0RReQH0eKYyHmU2xRAgj9Flv3JNVRE3dhwdzm+AHSaAnhXtacygR5NB/msI0b/mkrWXcps5yaYI3/dS+1lqko3sgo8oDaBte6vBPREvHzre1fO2Q4jyuf+9yxX8gCQ/bq3WjDgNIEC6PbxusqmQeXmMDk2exJocBx7pr+CILUC3nOqEBYR43jhKBVxfRYjeVEl4uTIC1ViiBrhoknNLNjJnOZFS3SBnZR6npnR7bLqcrNOKG95JNwn8DpdTItslD/8lheuggneQHgCS/Hi4Wgn6LAIZhnDAXJZRhFiTxykuMNpDes2FFXDtMhb4i8+A33KqfZYxYEUSot3YTD665eMKdaZPdneTyeQkFAoNlwV9uj4YxGL+BfPZzDCMbDZrGLP53O9fPJpV+QpjK/5PD6qkbE3CTUEUso1u2bSnPDceLB87M016wgdHHqzL1l/Rnny4y2WxmfCQH0PCjc0UdUCSH39Qr9rSRwp4ZFlkpzMFfW7J4wb9O6dARgjhIZERXISof1+Os1ZO5uEOYlKF6gnr7/nuP5q2G5sZMwWTK45gyw+NJKl2FGDNRl6WrYUzBOyIlBbICTXZziplnRatIV6RCP0Gl3NtcZYL0Th2493Im1TVbY0LLrEJcdGS/Fj3s+UGkMqyKCauMVyqEDoanEhjpccTK+lwWfkG4O5RZQ5QWTV9S73AhHFp78OFDQhtoNhwi+rQwM3909VfP8bb197OonJ+2iwUE57dyXDgN3w+w6/3QkmtmyimR/3y+eHBiTfTOBv/qF2GU8GbgLsuykIrj1zwrGATZ7xfuVwTAoUEUhr57MKajazd9z2xw143eGDeKxXz4kv5uguyaIZ28ve7XL7LRI7ZD+gzFimQbEBGvkhJfkSY9OVKu6QnL9aKOOAhr0RY414fR+mrWz67A8wt3eN0IAJuslQL/tUnx0CCB8FgJFUL/oM6hyrJhzw+FKVMbk6VG4yvuxxIBVAeyOKajXDMYSbydKczWRVpEbWtnMoOUH1MZrnAyEN2OU17YwL472I5pc3nGcsX+AjiGnmy0eUmgCQ/AuEkSXE3A26hMV4zaSq9R+vjMx7YwmbG3AYUVHSeACGadEQibJJ9/w6gQn5GUuvyc4MI7TyoElxlCn5Tbd3JetZshDFNBnvm7WuQ9B2KeEWgDl2yTit2G5wUe4DiyteXxxUr8aA4ixiN1o6sk4iizP/g+HDrwWwqVyg8jpr9/rRcLi2PQ20dHh4vjwAsz0R5M5m769vGdleNbtpk91MP46NokNt4G3lqD8RhoYSvj8duCLziE0WFzWoFtzSuwCKiAHf7sHDVqoCykwv1PNOIeM/bxCQ20JPX79+OIangMzjhpmTZyz1Y3Cj2H0EIXMq6jbB34NGTreuqbb+boyvzVZfRe/EcWaeVj34UZ7rKTaiqz7fMj5bZkUiZRMbk8/nUJfLT3fgFQZLFPD6OGmV5X0rLfxubt2OmpILPYSS/tZxNfzZ6Ea/IzdqtYvqxOS09LELRb967RSy6cxRdBKP38cqpiEbfxfJs94WYKh/VU/yKNjn9WBPvyzfzh4mPnx9ppMg9fBIKWYLMf3hqQD5TiJwOiU+9qa/IkYKPJURV+bouNzU2eEUHn0Z8w934X5wamI8klfQj2Ry6hDhRHEWom5GLbd2Btde5N6QQmobfxOb+ELfS2vdGOwQFqAYgYZfxyl0VBAkmNlUSfi7yiZ5CDCauunMq6tXE95zpyE4ROPs3LndBVl4VoVrEz6uwUP7qHHw/hUlg+zBzqbwqtr1Xydg0shYn17+sy43m+AW0tipfCmtft0Nw1jG36bYVkIb1R+6bs4zX2VUBglOyuqGS8LPxlX/uckqMTHYUCMJqbM/MidUU5Gi3iuhuHDJVqXBA5oTaWhGqoB7jLUxqPdJW2+pTLukpzmLbBgVbeCFP3uFthlRfwxeWQ5/PsXs00PVebzgMhSbLriW7mubxdLvtdiLRahWLuVw6XXhcZO128Ju53f6+iH2vwpFgxRRiJR79eJuUPcm9FNa+bofgrGO2ywdQoQeCe07gKON1dlWASZbjDfPDe7swiVDdarJkdlmyuhiYbVvMZiSiG0m8Ugmcmp2lqy5FPf/5jnedfo/KYtWUO7Nxcw38VoVEny5sq2FI1NXM5huHDK4VoQoKtJXIDJnc8p7nogDcSRpp735z+qryccxifVsjy3ihRA/eJukvCc4tHpZsmTycl0rl8kIB6jebo8fHQjqdyxWLrVYi0W53l78woC33OicTe6tTbHTO5zPjje5EquHvTbREbjR9OO5ktse1SiGGt+nbl/FSWLvWDsFRxxyz5bswkxA8cQhnGe8Fs9L+wuSXgbdnmNTarfRoen64dW4278k9J9rdZbeWYU+P+Wc+/kt88Z/eggpzuChaX1w6amrIaUBmJMRpyLjZ33zCi1wvQrXLIUNYEiCPHNO+VoXA6XJR8SmjPu68mizwNpoHn4C9O5W6ih6Nz24znf3Dh3L/MdeyOmZZe+3+dAxvQ8YdYV1BbofgrGOe28Ltpe1yVwzBWcZ7QUM6UMNfZtPTVlebDAfzrCrEMEP8rkJokrR+VsHZkmohwHYcTVjsPktPywlvqeXafeVur+1fCRGKLrULOBn5YaImAMVjXpMZjQb5bc3C4QsAj4TAft7FiUuJVoBghOlUYFNESq4XoS5wG+yQeWFMpxDvYVOBwFlsW2PbXKKbeGGTy/0e8oH78E168B57mIW1cjsEZx2zwdM1lzuiB84y3gAl/yY3ZNOfgdw1U3Y5hUXxbXqBI53ZQl7Z8nAW67qw4sZPti+QJuD1wH4evvNMJ69SXGIoG/Jucr0IdUGTmhKiObXOyGRxa0exOu7M2yNvHHAW226zYL6oiBfIL5s+5PR3uZxdWLvWDkHUMTuKwQVXtsudsQhHGa+jq8L7LNOc4bNxcf/n6ZRbzBnn9CJMNa1zf88g55NnF2xcPbX0zB3kCORU2M/DmGSBU+UwzVh/H9hnfpOJnUWowoBqJKxZm5iVcogLhnERUyeyXHAAZ7Fth+f5yrhN1v5nLmcW1q61Q3DUMWOVfYY5WZ0ycJbxOrsq2JDKhmz6c8nz5Of/Z5x/U3clWqnkQLRuutn3fRcBZRFEUVFRcEHccPf/P2ZIIKSxhYZ5MMs9Z47K9LNjdXVSublVVbo8dsNlowQqtnfsUfUaNTLgBS9EOaKSRpTI0/S6J/73tfm0h+3x8lC3NrESoRJV2uBQBFK9theVulLmbXwDSaPY9g0C0Qb9P1yutKTLCWGtqRwC1zGbLvbCJXcfB0YZr6qqoAAl4LPaTZuxiaL7+x/yveF49xBph0dONHWi5KwULS0SicfuZnep6+65d6R6fN5vWh/bAUqEOsGJmNVKyJOCxxjSneLdKLYtg8NetY5YzAkeOV2dO28IeotMyglre0hhrakcgkHHrENTpJBOHEF8KRmvqqpgxBw5ieLIrHlZa9QKC1qLnP2+mPvxAGhxseLBLYafhPgi4SxNPOSBKNVR152hQXTDzRo9HM/1uYUmZkqEKhnB8qdOFBX0iYekut5L9b4Mq9+NYtsu9m+dgNu7vMvJp3YhWdZEijaFe1T+pss5sGsuh2DQMffxoM5w4sInkGdGGa+qqqAA1GguskGy5mWtUVeL54SzrVq7XAA7j2UN27oO193YbYezY/24IYF0hCjdoel1e9xV3FFOtdmtawUD+g9F4CXyYnwJ7PAfTif6wgdGwWhATIguxI1i2wPsUeFMg9PwRrDFLicdLIbJ35/YXA3tHVz8HZdTwtrZcggGHXMFPfEMa3XaQadCxFK4mpXxDs3EFnBtsehb8bLWiCm34pyt5GiNNSjMLufFgXi4CTpBOJQ8xBdNYjlvRbK1b/74zROf0MTCKq87wiNRCYwokh6/nY80HxoKP1zOjaNJrOgT6/vN7nH2Q2TFN+HcPu6mgaZuFNvuQagCO0DGeMq6jHgpB2iesdsOaUMIo7C6yxmFtT/KISgdcwa91v2uD9inahD5/XAbndysjFdVVVAWX1SF57tH1rysNTJ4pimY5GgXu1zBi4NCVbcdOvWLNABtl9E9/GKJi5CAzccN8kknJ0T7aSJ53Ra8RG/81XY1rUtW5mH7IUINRsefFB74UO7z4Ejd8cEmwOHs6jNi2+fxLF4vGRb+yiKXUzlFVUTRHPt3XPfzP+qCKreMeYlY3cxBSgPSrpdiVXHK/vPyAuMcrpdiAzb+mcoQd6ou5XJqdlbC2h/lEJSO2QMBoW/tZ9W+Xsl4DVUVLFxOSfSX5WVDhslyrKtg0qr6AEnyCKaG/w/F0aoimmaXO41yvaUsVR/94AR0B+5Ec7t4ky7vhoWWbrcYvhzWki1e1v/Rc2HzX38yokKLW5p7ckv42tMCwaRiM5UItd+XM5UYI/PG9+LyN9RD545h/YfYloV0UwORAJy0hGEZsrtoiEG+PMMrdPgO+H04PNJwTiYOko6CWqlKOex1kb+MwM1mLw/54LyqMpzuQ/jJ8QcivShRzg6k/UuQJLp0OSWsNZVDUDrmo5S9+NbwTmzjT16YZLyqqoLFwqpexmV5WV/n9KGzRXT7/uSCj8hWyj8c88DPB42ffxz2iAo44pyt5GgXuJwC453OZfuM61ry+rJxz5tnHPDeGVfZ0WGO3Z2+8fGzN94kQXZT8ImRqXJi8/GwmTxiP9pLZXihqPucFWHbAx4ApIJ0AB/yQASamYPswhnFLb2OL9E+8DRzeRLO0xRqBOAkEuVhnNZ0IUh6EPYT+JZwuQJAGwaQtAg5luNlg4JJ9dMJEPUhV20jAoTIC7jTQIDaPiIPwpyzlRytpcutDpk24blYuuJ9dDMS2BZOyAzz0oZ38mptG4XgOEWBuJ2OgcYBuqyL158cpAfteiHVGX3FdwapCz8OjJdXP5wxOkCFAdvsCLaC010n24OPGnAwh+ZbQpJY/ydcrmWxl1+Ol03hku5wTnYUWRwXfPnPcA+DlyiLGOUPibzY4SSa5GjnuNw66WfrcmrMuZlZ7gVXS/H/KPJYMF0dYOsWutjxvOCAHPBSEsOfHGScs5hh2PrwVW04Iqa9Gy8f4Ej87zrgpWN4P0Xw405R0dnoIRJYwuVs/4TL3VmT5Na8rNgyMi1L9ocCsRYl4CGKnIz3jA54KNok+oSDXyc42rkud/WxbpJ0sOitcgARd7Z7du1fb/ueI4QXTMSK8ERWnM42/bg/QJ0o4qYzfFIcA8rA8ZOD3OFGdyCWwxvpPFjrzFweR5KH+P0LJPi13jGR6b4hN+By6Ipu/Zdd7tPC5ZbjZQ+jnClLkd1HHDf8x3SPcCoea4XaJyRsmOqQ4GgtXG6dJGlmUezQb/dui26D9lFIH7O3ZZGyyKWPMmNRpCwejQQzImVxmrPYGCU6nh3v7I3EXeXb/ffiFDtxngM5Fs1wzQwXf4lfOlLfJFwyRhPzPWsijWcHX0g7aeIkzxeeKIfdnxzkJc6J7ND5ekH5bSK3y3h5i398j5gXR9zqoQBuSRzElMAd7tVr7XI54PlFDfqtO8ndzG6XmolpQ7tyeSweEtqh++dJN7uvkD/jreT6VUaLgEUUZNpOy/KyJSdRBSXpck1UKIdvCn4w4lM8udvC5ThnKzjauSTJlWvdJOkrLhcaoOPErxDqXJG7+MDVuR2uzlXiXIODfk+0uVfcQW9lSq0/JlsJThWpBV1nbCb7oD8OMappID7EfiPsTFMYHgrAIfZs/cEMB+nRPrZukaUAX2CDbqIsmOHyCwRrAzu2XrFDXFDDeti/3kaU7nFyHepq+0u5nPHPF9pkVyQihMm8AI7QhIo0znyep3DOMV3+I9hL2ROl4ulueO94q/E0DPkDMY9NFxa30Vyk7LQsL1vCaTiKa+lyL7A33EjSAdzxPQ0hKuJlq4izycIaSVu43DpJ0kecYRHc++HjRstfKRAH6z9+1p7i9w4ucNy9vSqWeONKX5sX4Mg/RIK9m3EBjvf9EVVztHMssh6HE21gJuCNjXvPppFcpqShZzKT9X3IsDSEMPQZAfLweaqTond8znCQ9wB6F1RHmCjV5vSjx3j5Dr9Kc9v4jxmc0WsQgE8j2gUAe4U4PrPRRiPOodpHirG/jt4PP5DJ1XVaAazaz3keR3Tv3bhuyflReJcLQ0dm6wVdUQ0zcH4Adg43lzenUyOId1i8woeJ/Il0DCExWsTLlgAgPM1DZwmI7FA9C6CtDSkm7rwjOFvJ0XLY4DBJCUwkqWT5FOu5CjxwqI6kRSFqtrtTnFjpuD6i2ExF+jRCi4SIeZrgPEYC4u/yJ3N3T8RajHTfJdFXnL5OCyTAao4v7gix5xb/ZGAjeisS5Q6Y8XKKPQ31QI1CfB6Je4h0f7IijokvvkJ1FcsZCSjuLZmRjParNkw+xR1AnNYMve+JZe5q1/Gt46O32yugVqt9fYVCobu7kbMP/H7/gKt4v7iMNzgNuQLVKdf5Osww7gnjhOQ9h1xYK37+d3ol0x+6/5w0F/QzHpnXh3dVB7crCY527hlr0WUmSSXLZyJJLaBuMR/YzI61h8wqyct67vUu+Xz+tp8dTar2dGr0PrgeeMpNlPdrvUm7TzgJzksb8XXq+TJZuxMLVYH9OufEAp+DUC05nqxHk87tfnG7WZLrWfbf3j7QHFj07WQ2+hHL/S30cWxSr5hIUsnyGVjPtbWs2lBqemfhkcfuxFrsvORzwoD8aOX2TWT+2eIoaJfL+kfUiRWg6hC6E9nT7tHxffy6xv4rJMmiV7WpxEv8COCVvzxfvIE236adj96f7ugFuhq9QYkoRq/mjaFTN69OM9Oo+17kRAyrFhLNbMRMkkqWz0iSLg+Gg4UGsNEGEEFmiQICTEQ3vubt3k/siI2x2Bk7tvjemG+Oefh1efn0dD2KwZLDYas1WqBGiTVx3vP7nvf7djjO+MlMt8yntXH39F4wMnJXDUFmEAj9y1QwzUf7e0qXjEJn1/QN/OZz/ChvUoTPW/e8aog9ejcQiTVfohtyPP5sLJKkNtrNisUUlO2YSVLJ8hlJ0hWgdRcaoE4bQAeDpbI1WYz+GSiP2/iBVz9RtnQ56w7AdWbwkgDNgr1UydZ4VbdbAQx7JmLeRJJKls9Ekq7W8ZZdyLB5/EXJ99eP3nT7oOvmZm9vmsp39V0yU8b3ZlFqq5Epa5iO9Uk/T7gi23GaAzXWgr2hfhEVfEhauNz8x9HJTo+FdpXCshs1nSg1iKIJdbs/WfW2g2aSVLJ8ZpLUGqqr8HUeDwNBUfi4oeKHShW8frjlkUft4Ux8Pdcyv5VBKAHoNEwZ3xvFd1uNTFnDJC0dBIHIB1CeYyA11pwzzLlYu9Tlv1gsrPMfh6qKpONKKSxNGRFfiBPlE/J2f9Z/s9Q2k6SS5TOwnqu3a7dhz7brYmLqPBBMPpMG2ABKuJS6ubNJLnbgN5fbxuAGOGWmjO8NotlTI5u1htEetrzojeV3mh6peaxMvGV5Etg6sorl5j8O1XS8in0VErxHaBY1bl5nU93uTwKt77aZJJUsn5H1NMFq453scFbYL/aLWozID9sGXa482RaxYUo82Is7/DrLZcGYQ8PuhOCYURPaGG0ECZ8a2aw1jPa4mqSJfyE1rr3EvNMx+p+oXysYx0o5r9sZeJVi0EUAFjyOB+loBeOLV+xQoW9Mjx9yNlUrydv9WRmcZs9MkkqWz8h6mmB1btctEjHtkj/wRDHNKAbPBl3OMbVY+3kyH1R+60pchE50p3Hb5741uANSTSgTwTeAwxs1MoM1fub1RgpSJFTp40j0YZqMkUrRpIZgVY7V236lDji+pBh0AYC5j0PF3VSH+G6cFV/Ml4C0R6XHJ3Eton11u5Vi+41WRFeyvwTfGouw6eC77tojDyobdLka3DKSvJ4cu/V/c7kr6CIadpPtA4krXEk1oUwE3wDsKTWyH9ZQ9mhNCdNj1F6xw78GJmOkbSBygpAc6zWGlHz/wNWuR4pBFwCY/zjUDGSD+G6cFV8EEqLEiUqPTwpOQ95uJTzsb9Tl1FpdDhMxtMTfSHe4zG10lnucCtEneV8ZMKPLqdImVbH2a2wfDhKPlrBNKhF8A3C71ch+WEPZY2e65b7G8xcaxDdvcowlRHNebMmxNsS1WRApMeh8APMfh4qzKgjTNE353ZnhLh83pMe3OHMrb7dq4daNdrdRBxr3J0QxkXkTbhKdI7lRl1M7P/jFl4H2a63I7Pi7W1RcPe6XW1JNKIWJG0Darkb2wxrKHmdTleETtkKIE3WRk2M8AZ+W9uRYt+CXFbCkGHQBgEWPIzxVkuwpJeZ+UET33alV4vgiHacWt7Pg/kzi94vaMMBoBjtt/e+3ogxgaEv0RMCc4A9ZQ26DLqdiIi3OxLE8Kr+5XAljuzpFxlwML0JNqISJm0DqRI3shzXUuO9QJvJkvdyVAgG8CNWKHGNas1EFR1L5eIyMeG0KJMWgiwDMfxyKM/uUCztXWJ4Gx0vt1CovGFAf5QW3szxUM4vfWR6A73U2IfP9T4oF7wDRDNF37JTTjazk1P8Bl/MAqNFO/BLQCr+43KEYW0Y7Ib481LE3URMqYeL64UsYR6asMVuJqoNPGuDhMQ4Xy40V7jk5xl6Pe8CtVD6eCZfrwkZKDDofwPzHoU9DiZDMROUKy3JQzKUvU6vwQ4ELdNXtVsHN4e+BRh37rbLmqhtbdZ4wWh3qARe8jGgQ1b1jR87Rpl1OCumrPBRhvy6sdu1OZyEXQmSH4/UA9omaUAkT14/et3Fkyhqz1HgIzri+jzycAWKaL35+gws5Rp48xdAUY50urF1ckBKDWp/imh+H8cg9icvHWjjVY3xhLWvdpyvtozC1yg5e6REH6narx7Lmn/s8km4YD1NfS31aFeZe6peOTStJzIqM2Pvcut9XEIgT+aMAXNOM76kwcf0Ibs8fGQEZaSknEJ0kPZ+B41GO0d4moZmfjLWlPYqzO52UGHQunpEi0+MwC82+IJAVCkvxS4MZZZV7LUc57V7dbnUGwxzbXsBBFIMYUV14BavTbCI6W1K1+bKoKAnQoA3gbWEQsKe2r4NyIhv2CnO34p76C5NqQilMXD9cRZqPiCJmHt/sqdMwtCS38/Wr7YjJMcYCPBqokRwrGysjiaQYdAGwSLyam6bCsLft8nHLNv7lhVw/FGBGq3jFf+p2q1Ph5p5eMTxzZwmFHgJuaAFi3TzaZ6QS0UXeupVq07qX/AEitAEAFxYu9+/hYX9hFPJAM0hquKf14XHhoXbF4l4bKemYOpQ7lhd/WIsU7gHY4aA3RLJOxGQiusxbt1BtWqfre4AMrR1PwL/YUMOafZ+PiqkBmf+jR+sDFqqAYojTxnHl+n07EQIAV4C24MrVtTObZmf+NrwyEV3mrS+j2vzC3eImabRuMCCwmsvptBGsrh+kkqlIfsFGa8PZYmsH8EQmkmzduM3/Ln5PYrvbqBJtoUU06A+xtw3tjGQiusxbt1BtWudOkw680ZrxgBQt6XLMzuecWPScTFAStPUK6hC22Ph80qbgt2j0+okkmUkyKZtbCFW50OrfdLXfXe5yst5t4VGW07v1EMlEdJm3bqXalK/O4qUkSWtFGWDLulwIKPDgLkgmKAkarVNQp2PPKijQaTMIAGcWlRVqZCbJpGxuDkyVCy3+zQHYr9RwHAGjy13i20NUqMlEdJm3voxqM2axKW0B17RGHAAXtKzL7QF+oubvTurOzxGprbE8sxltbKhD5SVwYl0/Zg5JxsgCzGwaZtmA08hTxvE6cbmYiPK1h/vBi8spE9Fl3rqValMWoViILeBQp3XhBgjQ0i63DTSIRWWZcKaIIIMEjQrmFip/Gzk4rPucB2jt8CaACLMqWOWneSQZUWvAR3cgxiYrFkrtnoAyzUy2pUc3yA/NxaPbE9eR58zP8Ki+6ZGkTESXeetWqk2ZuLgYQ6yNnrsDELOeB9UrBpxSAEBIEj+SCJpK0NjeB4L3phYqfxcVPFs3TUW3sOY1NQvAbvVLr5GhX0kyIZtLa69Eu+MJRFYslNq9mcqForKj+EgWPDTKDxuI/epy5PlRQr46GPKPZCK6yFu3Um2q4MUCNhcA5zNb3B6P6Xq1WuWFReZcWN8HENFpeZfTcaPxknJFbE2JnwkRJCVoVES7nHeaWqisvUaLwmMHQOK6SmtCtZEGgB1pNisK1UySCdncF3r6OW6EfWXFQqndM1QulJUd+Uey4KGSHyq/NpzGrB0IkyU+sSbckTXCUMHLbhpVO15RJkn8SCJoIkH7wolO7RtTC5XVoXaFVmBbMEKL3By+82pL42JLL7zWkmzJpuo08UJN5bJIHy01x2U4XFBoPpIlnlGhX0mycWHCHfhw0ycBWbFQavdU5UJZ2ZF/JAseGuWHNdxt3OW03aXC6stv/CHyuwGilVwujGQX17CTM02S+JFE0ESCtsu/69hnW6j8Ae6W0gpUA2dprA2u85ZnOf1+jn4lycb1k1gEQUkSyoqFUrunKhfKyo78I1nw0Cg/9KO1nMs9BtbQ2XotYHrBJmoNffrveL2lQCWnotUVXS4NWxIdOMit6ZL4kUTQRIKWAOeO7LMtVP4ALQxoBbD6RSwwqF03HHtvt8Wm/Sb4oMESzk4qcfUmK1otB9X8ykySUaojfkBUuq6sWCi1e6pyoazsKD4SpcCk/NAcWcjcWYV7FaGd3NDKUIms/y2oRtjOINkAeGgXA0n8SCJoIkG7QozoxEczLVT+AE/r2Y4y/t7FXjP+u9rw+rIhSp6F/JnXWCVns3gDLQ6fTSSZlM3FETmWlS5lxUKp3TNULpSVHSktXW5WfujBy3yX8yOiOOI0/V0Es/TfwpT/vkCWKIgUf6uPJPEjiaCJBG0L24GnKHIzLVT+ALz1yn8VYRCZSDKpR0/CVRFZrwKyYqHU7qnKhbKyo/hIuJySH0picp7LMZ+hfEPnkFaGopf/W9jVpmz7ObezKIl7KIkfSQRNJGhVN4AgHDMtVCxgFS/9VyGroJlJsv007fQ8RHpKY8QhKxZK7Z6qXCgrO/KPZMFDo/yQ4WCuyz1DyjxYnT6yJGlBlS+buRK9ZW07EbvxY7Py+L+FqWX1Z52Iib+xkZTEjySCpASNDeKf9FSZaaHyB+D9af+r4Gkqc0gyRrKjCQnIioVSu6cqF04rOxJTBQ+N8kNneZ7LVT80ETJTf1uDW7slSQvKfNlYCkCJqqcAwOTHv6Y0/bfwV3tn25Q2EATg24QAAYJA2sibKC8FJQ6giAQKFXAq0lGo/v8f091AlNbgaIeQ07nnAx9umIFJNsndZvee8SHzjxRIjFdKOtsB6nxTyNXhvEaZUWkEvYYMKbZKCz71y6pwYWgtNgDdqoLpDLv6K/iCLma/oFsst5Q7bAcMGxtCTgnLxoBm1leUtk5DxUkLOv2yU4hMyLilUdFwlDnDrjsi8MV7dN6f68fX8e1MRSLuISflgZCl5bpNgbaTFnT6ZcmCF4nTkwL0wmtdu40h44uSynyDlKfcshsD/L7mHnJTkIOpq0vIsfyhncyzVjma537ZvhWB8FcWmB3JEHKGXTji7SDne8w3qMGJW3az0Cup7iFnQdvOW3ZZCq4ZlYs4IbfeLzuzv8X64czzsNuklC/KHeYfGd4WUy+KOrymGnYPOV1W7JtbluVgYRkJGDtpQadftnrx/aQE1lmnmwyB9jT8AWYv79vr50Oe1i2sJT3jHCS3d6yTVUfCEWmdZYCwPnfSgk6/bB2QRP9OBuTsaZizBSLjbT2z4O3134vmM68JgeIWcs6OBQGKMuXkwZyYdlpwvT23dvWTmoAmD4Vk0Rn+EGkBP7M2VFfDLfKA7QADYl4XL32TGV/4mZuW4Jzxitf/zb2WJuHBTOOes5CLLkaKeRyQmB/Qth+8Qi0Db+MY1TcxMt9QGYvxs7B036OdFI1ULdtI1SNLSTZIJip0/I1RRdWsW12y/JlxSHs9uU0B4wljTUB5+EXVEx1thFqg1n55qXAZUPGtXXt7SwVBaOuK1fpUELQVpnDKeIXKil4imdFY/CF9GqqkxvPHi0xHDcPfyGjxXNCBHGorwdLjkW2QbQUjWTQEDhM9dPyQzROQwhRmL4w6W6bJ11tF8xSgvZIn2j6qcqNFrjiSJ+rqDR4ZcEeW6cj2OiToXF2+ZK26b6JlqEvGqtu0HaK/0dGJQTopBiT3OnRekX4V6VOZ5pJXs3azWmpEtPX4kr/ow2yr/KOaqoTQnYeO12nflN73E0pNMsHyutCoDgHGFbP4mySn9qPjmqRpxuzfR8fIVsQeukSn+x2g1+vpiKra1TncchDUw2sSPY2sd/eVkJFO5qbK1s7iIMbW0DwIuQocs0+LJB2bCoYnaVWxMj55ckYOtVNSqFm2f/3bsgMGKSHzefAyyrhFyefHqfYsndyLFtmO0PbZ1rE4rhAT+M7Ig5CjbTQFgh2+2O2CwgSCzTvEvwL1yxfNiaIc9KM4ffkau9ujGQyKYK9R1Y6a9tze3h0u12rR/oEyMYsBe80Wj3C2fBDwQ2AOEMS8CiYNVhmVTiKhq4sbJ6nyH4QXVSYQbCBwCZDNZEakTH9yppdImj5eWtOb53UygKP/G+XfM3Snozwdpd9nJw/J5Vrtu0FbFtCOBY7uel4qMIFgIzmOk0YCgUAgEAgEAoFAIBAIBALBZ+MPi2jQvTDed8sAAAAASUVORK5CYII=\n\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Annexe-A%C2%A0:-Miscellan%C3%A9es-acad%C3%A9miques\">Annexe A : Miscellanées académiques<a class=\"anchor-link\" href=\"#Annexe-A%C2%A0:-Miscellan%C3%A9es-acad%C3%A9miques\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"D%C3%A9compositions-d'un-MCD\">Décompositions d'un MCD<a class=\"anchor-link\" href=\"#D%C3%A9compositions-d'un-MCD\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Aussi surprenant que cela puisse paraître, tout MCD peut être transformé en un MCD équivalent dont les seules associations sont des dépendances fonctionnelles binaires non porteuses d'attributs, telles que celle ci-dessous :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [147]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> \nENTITÉ 1_: at 1 1, at 1 2, at 1 3\nDF, ?1 ENTITÉ 1_, XX ENTITÉ 2_\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTYiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgMzE2IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTYiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjU5IiB5MT0iNTYiIHgyPSIxNTgiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNTciIHkxPSI1NiIgeDI9IjE1OCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTU4IiBjeT0iNTYiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTQ1IiB5PSI2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTE0IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+PywxPC90ZXh0PgoJPHRleHQgeD0iMTg0IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+ICAgICA8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVElURV8xXyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTA5IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVOVElUw4kgMTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdCAxIDE8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjUzIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YXQgMSAyPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5hdCAxIDM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVOVElURV8yXyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMDciIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjA3IiB5PSIzOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMDciIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjA3IiB5MT0iMzkiIHgyPSIzMDciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjE2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVOVElUw4kgMjwvdGV4dD4KCTx0ZXh0IHg9IjIxNSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YXQgMiAxPC90ZXh0PgoJPGxpbmUgeDE9IjIxNSIgeTE9IjU5IiB4Mj0iMjUxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyMTUiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF0IDIgMjwvdGV4dD4KCTx0ZXh0IHg9IjIxNSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmF0IDIgMzwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La transformation peut demander jusqu'à trois opérations que Mocodo appelle <em>drain</em>, <em>split</em> et <em>explode</em>, et que nous allons découvrir dans la suite.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Vider-les-DF-de-leurs-attributs\">Vider les DF de leurs attributs<a class=\"anchor-link\" href=\"#Vider-les-DF-de-leurs-attributs\">¶</a></h3>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [148]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nEntreprise: nom entreprise, adresse, téléphone\nProposer, 0N Entreprise, 11 Stage: date proposition\nStage: num. stage, sujet\nAttribuer, 11 Étudiant, 01 Stage: date signature\nÉtudiant: num étudiant, nom\nSoutenir, 01 Étudiant, 0N Date: note stage\nDate: date\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NzYiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgODc2IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI4NzYiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQUk9QT1NFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNjgiIHkxPSI1NiIgeDI9IjIxNSIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0NSIgeTE9IjU2IiB4Mj0iMjE1IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjYwIDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTE4IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjc0IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTcwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDExOCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjI3IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTU2IiB5MT0iNTUiIHgyPSIyNzQiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3MiIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9wb3NlcjwvdGV4dD4KCQk8dGV4dCB4PSIxNjMiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGUgcHJvcG9zaXRpb248L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMzIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIyODAiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQVRUUklCVUVSIC0tPgo8Zz4KCTxsaW5lIHgxPSI2MDEiIHkxPSI1NiIgeDI9IjQ2OSIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0NSIgeTE9IjU2IiB4Mj0iNDY5IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNTA4IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTA2IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNTIyIDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINDMwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDEwNiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSI0MTYiIHk9IjI3IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iNDE2IiB5MT0iNTUiIHgyPSI1MjIiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjQyMyIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BdHRyaWJ1ZXI8L3RleHQ+CgkJPHRleHQgeD0iNDIzIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIHNpZ25hdHVyZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjUyOCIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjM5MiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBTT1VURU5JUiAtLT4KPGc+Cgk8bGluZSB4MT0iNjAxIiB5MT0iNTYiIHgyPSI3MjkiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI4MzciIHkxPSI1NiIgeDI9IjcyOSIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTc2NCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTk4IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNzc4IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINjk0IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjY4MCIgeT0iMjciIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjY4MCIgeTE9IjU1IiB4Mj0iNzc4IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI2ODciIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U291dGVuaXI8L3RleHQ+CgkJPHRleHQgeD0iNjg3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub3RlIHN0YWdlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNjU2IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCwxPC90ZXh0PgoJPHRleHQgeD0iNzgzIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFTlRSRVBSSVNFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIxMTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW50cmVwcmlzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZW50cmVwcmlzZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTE0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dMOpbMOpcGhvbmU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNUQUdFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMwMyIgeT0iMTgiIHdpZHRoPSI4NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMDMiIHk9IjQ4IiB3aWR0aD0iODQiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzAzIiB5PSIxOCIgd2lkdGg9Ijg0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMwMyIgeTE9IjQ4IiB4Mj0iMzg3IiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMxOSIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TdGFnZTwvdGV4dD4KCTx0ZXh0IHg9IjMxMSIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBzdGFnZTwvdGV4dD4KCTxsaW5lIHgxPSIzMTEiIHkxPSI2OCIgeDI9IjM3OCIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzExIiB5PSI4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5zdWpldDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRVRVRElBTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNTUxIiB5PSIxOCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NTEiIHk9IjQ4IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjU1MSIgeT0iMTgiIHdpZHRoPSIxMDAiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTUxIiB5MT0iNDgiIHgyPSI2NTEiIHkyPSI0OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTYwIiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsOJdHVkaWFudDwvdGV4dD4KCTx0ZXh0IHg9IjU1OSIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIMOpdHVkaWFudDwvdGV4dD4KCTxsaW5lIHgxPSI1NTkiIHkxPSI2OCIgeDI9IjY0MiIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTU5IiB5PSI4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub208L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IERBVEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iODA3IiB5PSIyNiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjgwNyIgeT0iNTYiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4MDciIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iODA3IiB5MT0iNTYiIHgyPSI4NjciIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iODE2IiB5PSI0Ny4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRhdGU8L3RleHQ+Cgk8dGV4dCB4PSI4MTUiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8bGluZSB4MT0iODE1IiB5MT0iNzYiIHgyPSI4NDMiIHkyPSI3NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Entreprise</strong> (<u>nom entreprise</u>, adresse, téléphone)</li>\n<li><strong>Étudiant</strong> (<u>num étudiant</u>, nom, <em>#num. stage</em>, date signature, date, note stage)</li>\n<li><strong>Stage</strong> (<u>num. stage</u>, sujet, <em>#nom entreprise</em>, date proposition)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le MCD ci-dessus comporte trois associations de dépendance fonctionnelle porteuses d'attributs. Certains auteurs considèrent cela comme une anomalie. En tout état de cause, Mocodo peut les déplacer dans les entités distinguées par les cardinalités 11. Nous appelons cette opération un « drainage des dépendances fonctionnelles » (option <code>-t drain</code>). Notez bien que ces deux MCD sont strictement équivalents, et produisent le même MLD.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [149]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --mld -t drain\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgOTAwIDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI5MDAiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQUk9QT1NFUiAtLT4KPGc+Cgk8bGluZSB4MT0iNjgiIHkxPSI1NiIgeDI9IjIwNyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0NyIgeTE9IjU2IiB4Mj0iMjA3IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjQ0IDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTAyIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjU4IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTcwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDEwMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjI3IiB3aWR0aD0iMTAyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTU2IiB5MT0iNTUiIHgyPSIyNTgiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE2NCIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9wb3NlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEzMiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjI2NCIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBBVFRSSUJVRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjYyMyIgeTE9IjU2IiB4Mj0iNDg5IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzQ3IiB5MT0iNTYiIHgyPSI0ODkiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik01MjggMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMDYgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik01NDIgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEg0NTAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTA2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjQzNiIgeT0iMjciIHdpZHRoPSIxMDYiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI0MzYiIHkxPSI1NSIgeDI9IjU0MiIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iNDQzIiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkF0dHJpYnVlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjU0OCIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjQxMiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsMTwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBTT1VURU5JUiAtLT4KPGc+Cgk8bGluZSB4MT0iNjIzIiB5MT0iNTYiIHgyPSI3NTMiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI4NjEiIHkxPSI1NiIgeDI9Ijc1MyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTc4OCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTk4IFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNODAyIDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBINzE4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjcwNCIgeT0iMjciIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjcwNCIgeTE9IjU1IiB4Mj0iODAyIiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI3MTEiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U291dGVuaXI8L3RleHQ+CgkJPHRleHQgeD0iNzExIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub3RlIHN0YWdlPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNjgwIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCwxPC90ZXh0PgoJPHRleHQgeD0iODA3IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFTlRSRVBSSVNFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIxMTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjExOCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW50cmVwcmlzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gZW50cmVwcmlzZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTE0IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dMOpbMOpcGhvbmU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNUQUdFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI4NyIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyODciIHk9IjM5IiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI4NyIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyODciIHkxPSIzOSIgeDI9IjQwNyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMjEiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U3RhZ2U8L3RleHQ+Cgk8dGV4dCB4PSIyOTUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gc3RhZ2U8L3RleHQ+Cgk8bGluZSB4MT0iMjk1IiB5MT0iNTkiIHgyPSIzNjIiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI5NSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c3VqZXQ8L3RleHQ+Cgk8dGV4dCB4PSIyOTUiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIHByb3Bvc2l0aW9uPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFVFVESUFOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1NzEiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTcxIiB5PSIzOSIgd2lkdGg9IjEwNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NzEiIHk9IjkiIHdpZHRoPSIxMDQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNTcxIiB5MT0iMzkiIHgyPSI2NzUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTgyIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPsOJdHVkaWFudDwvdGV4dD4KCTx0ZXh0IHg9IjU3OSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtIMOpdHVkaWFudDwvdGV4dD4KCTxsaW5lIHgxPSI1NzkiIHkxPSI1OSIgeDI9IjY2MiIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTc5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub208L3RleHQ+Cgk8dGV4dCB4PSI1NzkiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlIHNpZ25hdHVyZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREFURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI4MzEiIHk9IjI2IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iODMxIiB5PSI1NiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjgzMSIgeT0iMjYiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI4MzEiIHkxPSI1NiIgeDI9Ijg5MSIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI4NDAiIHk9IjQ3LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjgzOSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZTwvdGV4dD4KCTxsaW5lIHgxPSI4MzkiIHkxPSI3NiIgeDI9Ijg2NyIgeTI9Ijc2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Entreprise</strong> (<u>nom entreprise</u>, adresse, téléphone)</li>\n<li><strong>Étudiant</strong> (<u>num étudiant</u>, nom, date signature, <em>#num. stage</em>, date, note stage)</li>\n<li><strong>Stage</strong> (<u>num. stage</u>, sujet, date proposition, <em>#nom entreprise</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La première version peut être préférée pour des raisons de localité sémantique (<em>date proposition</em> dans PROPOSER), ou honnie parce qu'elle complique la définition d'identifiant d'association. Mocodo n'a pas d'opinion sur la question. Par contre, il se refuse à procéder au drainage <em>via</em> les cardinalités 01. Dans le MCD ci-dessus, le placement de <em>note stage</em> dans SOUTENIR indique qu'un étudiant peut ne pas se voir attribuer de note de stage ; si elle était mise dans ÉTUDIANT, la connaissance du fait que ce champ autorise la valeur <code>NULL</code> serait perdue.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9composer-les-DF-n-aires\">Décomposer les DF n-aires<a class=\"anchor-link\" href=\"#D%C3%A9composer-les-DF-n-aires\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>De même, d'aucuns regardent de travers les dépendances fonctionnelles d'arité $n$ supérieure à 2 :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [150]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nBataille: nom bataille, lieu, date\nRécolter, 0N Villageois, 0N Bataille, 11 Trophée\nVillageois: nom villageois, adresse, fonction\n\nTrophée: numéro, type, état\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODYiIGhlaWdodD0iMjEyIiB2aWV3Qm94PSIwIDAgMzg2IDIxMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODYiIGhlaWdodD0iMjEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRUNPTFRFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMzIwIiB5MT0iNTYiIHgyPSIxODQiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NyIgeTE9IjU2IiB4Mj0iMTg0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMTg0IiB5MT0iMTU2IiB4Mj0iMTg0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjIwIDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtMTAwIFY0MSBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjM0IDU1IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTQ4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTUgSDEwMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMzQiIHk9IjI3IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTM0IiB5MT0iNTUiIHgyPSIyMzQiIHkyPSI1NSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE0MiIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Sw6ljb2x0ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyMzkiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxMTAiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxODkiIHk9IjEwMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBCQVRBSUxMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI5NiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTA1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkJhdGFpbGxlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBiYXRhaWxsZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iOTMiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWV1PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBWSUxMQUdFT0lTIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI2MyIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjMiIHk9IjM5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI2MyIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNjMiIHkxPSIzOSIgeDI9IjM3NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNzIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VmlsbGFnZW9pczwvdGV4dD4KCTx0ZXh0IHg9IjI3MSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHZpbGxhZ2VvaXM8L3RleHQ+Cgk8bGluZSB4MT0iMjcxIiB5MT0iNTkiIHgyPSIzNTkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI3MSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjI3MSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmZvbmN0aW9uPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUUk9QSEVFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzOCIgeT0iMTA5IiB3aWR0aD0iOTIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTM4IiB5PSIxMzkiIHdpZHRoPSI5MiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzgiIHk9IjEwOSIgd2lkdGg9IjkyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEzOCIgeTE9IjEzOSIgeDI9IjIzMCIgeTI9IjEzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQ2IiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ucm9waMOpZTwvdGV4dD4KCTx0ZXh0IHg9IjE0NiIgeT0iMTU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bcOpcm88L3RleHQ+Cgk8bGluZSB4MT0iMTQ2IiB5MT0iMTU5IiB4Mj0iMTk2IiB5Mj0iMTU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTQ2IiB5PSIxNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dHlwZTwvdGV4dD4KCTx0ZXh0IHg9IjE0NiIgeT0iMTkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij7DqXRhdDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Bataille</strong> (<u>nom bataille</u>, lieu, date)</li>\n<li><strong>Trophée</strong> (<u>numéro</u>, type, état, <em>#nom villageois</em>, <em>#nom bataille</em>)</li>\n<li><strong>Villageois</strong> (<u>nom villageois</u>, adresse, fonction)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Toute DF de ce type peut en effet être « fendue » en $n-1$ DF. L'option <code>-t split</code> génère le MCD équivalent :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [151]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --seed=3 --mld -t split arrange:wide\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MzYiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgNjM2IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2MzYiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRUNPTFRFUjEgLS0+CjxnPgoJPGxpbmUgeDE9IjMwOSIgeTE9IjU2IiB4Mj0iMTg0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNTciIHkxPSI1NiIgeDI9IjE4NCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIyMCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTEwMCBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIzNCA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE0OCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTM0IiB5PSIyNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEzNCIgeTE9IjU1IiB4Mj0iMjM0IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNDIiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UsOpY29sdGVyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjQwIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMTEwIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFJFQ09MVEVSMCAtLT4KPGc+Cgk8bGluZSB4MT0iMzA5IiB5MT0iNTYiIHgyPSI0MzQiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI1NzAiIHkxPSI1NiIgeDI9IjQzNCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTQ3MCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTEwMCBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTQ4NCA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDM5OCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxMDAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzg0IiB5PSIyNyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM4NCIgeTE9IjU1IiB4Mj0iNDg0IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzOTIiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UsOpY29sdGVyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzYwIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iNDg5IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBCQVRBSUxMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI5NiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iOTYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTA1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkJhdGFpbGxlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBiYXRhaWxsZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iOTMiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWV1PC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBUUk9QSEVFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI2MyIgeT0iOSIgd2lkdGg9IjkyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI2MyIgeT0iMzkiIHdpZHRoPSI5MiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjMiIHk9IjkiIHdpZHRoPSI5MiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNjMiIHkxPSIzOSIgeDI9IjM1NSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNzEiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VHJvcGjDqWU8L3RleHQ+Cgk8dGV4dCB4PSIyNzEiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bcOpcm88L3RleHQ+Cgk8bGluZSB4MT0iMjcxIiB5MT0iNTkiIHgyPSIzMjEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI3MSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dHlwZTwvdGV4dD4KCTx0ZXh0IHg9IjI3MSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPsOpdGF0PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBWSUxMQUdFT0lTIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUxMyIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MTMiIHk9IjM5IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjUxMyIgeT0iOSIgd2lkdGg9IjExNCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1MTMiIHkxPSIzOSIgeDI9IjYyNyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MjIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VmlsbGFnZW9pczwvdGV4dD4KCTx0ZXh0IHg9IjUyMSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHZpbGxhZ2VvaXM8L3RleHQ+Cgk8bGluZSB4MT0iNTIxIiB5MT0iNTkiIHgyPSI2MDkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjUyMSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+YWRyZXNzZTwvdGV4dD4KCTx0ZXh0IHg9IjUyMSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmZvbmN0aW9uPC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Bataille</strong> (<u>nom bataille</u>, lieu, date)</li>\n<li><strong>Trophée</strong> (<u>numéro</u>, type, état, <em>#nom bataille</em>, <em>#nom villageois</em>)</li>\n<li><strong>Villageois</strong> (<u>nom villageois</u>, adresse, fonction)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9composer-les-associations-n-aires-non-DF\">Décomposer les associations n-aires non DF<a class=\"anchor-link\" href=\"#D%C3%A9composer-les-associations-n-aires-non-DF\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Toute association non DF d'arité $n$ peut être décomposée en un ensemble de $n$ associations DF : elle-même se voit alors remplacée par une entité liée aux $n$ entités originales. Cette nouvelle entité est appelée « entité-intersection », « entité-associative » ou « Gerund », cf. Song, Il-Yeol &amp; Evans, Mary &amp; Park, Eui Kyun. <em>A Comparative Analysis of Entity-Relationship Diagrams</em>. Journal of Computer and Software Engineering. 3 (1995). Dans les cours de <a href=\"https://laurent-audibert.developpez.com/Cours-BD/?page=conception-des-bases-de-donnees-modele-a#L2-3-3-b\">Laurent Audibert</a> ou de <a href=\"https://gestion.pumbo.fr/boutique/livre/modelisation-conceptuelle-de-donnees\">Patrick Bergougnoux</a>, l'opération est illustrée à l'aide du MCD suivant :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [152]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nFilm: id. film, titre, durée\nProjeter, 1N Salle, 1N Créneau, 1N Film: tarif\nSalle: num. salle, capacité\n\nCréneau: num. créneau, date, heure début\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iMjMwIiB2aWV3Qm94PSIwIDAgMzEwIDIzMCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMTAiIGhlaWdodD0iMjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBQUk9KRVRFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMjYyIiB5MT0iNTYiIHgyPSIxNDUiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNDUiIHkxPSIxNzQiIHgyPSIxNDUiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzOCIgeTE9IjU2IiB4Mj0iMTQ1IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTgwIDI3IGExNCAxNCA5MCAwIDEgMTQgMTQgVjU1IGgtOTggVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0xOTQgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMTAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIOTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOTYiIHk9IjI3IiB3aWR0aD0iOTgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI5NiIgeTE9IjU1IiB4Mj0iMTk0IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxMDQiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvamV0ZXI8L3RleHQ+CgkJPHRleHQgeD0iMTAzIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50YXJpZjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5OSIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjE1MCIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI3MiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgRklMTSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iNTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSI1OCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iNTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iNjciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RmlsbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pZC4gZmlsbTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNTkiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50aXRyZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZHVyw6llPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBTQUxMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMjMiIHk9IjE4IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIzIiB5PSI0OCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyMyIgeT0iMTgiIHdpZHRoPSI3OCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMjMiIHkxPSI0OCIgeDI9IjMwMSIgeTI9IjQ4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMzYiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U2FsbGU8L3RleHQ+Cgk8dGV4dCB4PSIyMzEiIHk9IjY1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gc2FsbGU8L3RleHQ+Cgk8bGluZSB4MT0iMjMxIiB5MT0iNjgiIHgyPSIyOTMiIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIzMSIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y2FwYWNpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDUkVORUFVIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijk0IiB5PSIxMjciIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOTQiIHk9IjE1NyIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5NCIgeT0iMTI3IiB3aWR0aD0iMTAyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijk0IiB5MT0iMTU3IiB4Mj0iMTk2IiB5Mj0iMTU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxMDYiIHk9IjE0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNyw6luZWF1PC90ZXh0PgoJPHRleHQgeD0iMTAyIiB5PSIxNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjcsOpbmVhdTwvdGV4dD4KCTxsaW5lIHgxPSIxMDIiIHkxPSIxNzciIHgyPSIxODciIHkyPSIxNzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxMDIiIHk9IjE5MS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPHRleHQgeD0iMTAyIiB5PSIyMDgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhldXJlIGTDqWJ1dDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Créneau</strong> (<u>num. créneau</u>, date, heure début)</li>\n<li><strong>Film</strong> (<u>id. film</u>, titre, durée)</li>\n<li><strong>Projeter</strong> (<u><em>#num. salle</em></u>, <u><em>#num. créneau</em></u>, <u><em>#id. film</em></u>, tarif)</li>\n<li><strong>Salle</strong> (<u>num. salle</u>, capacité)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La décomposition est invoquée par l'option <code>-t explode</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [153]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --seed=8 --mld -t explode arrange:balanced\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyODQiIGhlaWdodD0iMzMwIiB2aWV3Qm94PSIwIDAgMjg0IDMzMCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyODQiIGhlaWdodD0iMzMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjEzNyIgeTE9IjQ3IiB4Mj0iMzgiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzOCIgeTE9IjE1NiIgeDI9IjM4IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzOCIgY3k9IjQ3IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjI1IiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNjQiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI0MyIgeT0iMTAxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYxIC0tPgo8Zz4KCTxsaW5lIHgxPSIxMzciIHkxPSI0NyIgeDI9IjIzNiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIzNiIgeTE9IjE1NiIgeDI9IjIzNiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMjM2IiBjeT0iNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMjIzIiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTkyIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iMjQxIiB5PSIxMTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjIgLS0+CjxnPgoJPGxpbmUgeDE9IjEzNyIgeTE9IjQ3IiB4Mj0iMTM3IiB5Mj0iMTU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjEzNyIgeTE9IjI3NCIgeDI9IjEzNyIgeTI9IjE1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjEzNyIgY3k9IjE1NiIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIxMjQiIHk9IjE2MC44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTQyIiB5PSIxMDEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjE0MiIgeT0iMjE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVEVSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijg3IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9Ijg3IiB5PSIzOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4NyIgeT0iOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI4NyIgeTE9IjM5IiB4Mj0iMTg3IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9Ijk2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2pldGVyPC90ZXh0PgoJPHRleHQgeD0iOTUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmlkLiBwcm9qZXRlcjwvdGV4dD4KCTxsaW5lIHgxPSI5NSIgeTE9IjU5IiB4Mj0iMTY2IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI5NSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGFyaWY8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEZJTE0gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTA5IiB3aWR0aD0iNTgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTM5IiB3aWR0aD0iNTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMTA5IiB3aWR0aD0iNTgiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjEzOSIgeDI9IjY3IiB5Mj0iMTM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMTMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RmlsbTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSIxNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGZpbG08L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSIxNTkiIHgyPSI1OSIgeTI9IjE1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSIxNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGl0cmU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iMTkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kdXLDqWU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNBTExFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE5NyIgeT0iMTE4IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTk3IiB5PSIxNDgiIHdpZHRoPSI3OCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOTciIHk9IjExOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE5NyIgeTE9IjE0OCIgeDI9IjI3NSIgeTI9IjE0OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjEwIiB5PSIxMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TYWxsZTwvdGV4dD4KCTx0ZXh0IHg9IjIwNSIgeT0iMTY1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gc2FsbGU8L3RleHQ+Cgk8bGluZSB4MT0iMjA1IiB5MT0iMTY4IiB4Mj0iMjY3IiB5Mj0iMTY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjA1IiB5PSIxODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y2FwYWNpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDUkVORUFVIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9Ijg2IiB5PSIyMjciIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iODYiIHk9IjI1NyIgd2lkdGg9IjEwMiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4NiIgeT0iMjI3IiB3aWR0aD0iMTAyIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9Ijg2IiB5MT0iMjU3IiB4Mj0iMTg4IiB5Mj0iMjU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI5OCIgeT0iMjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q3LDqW5lYXU8L3RleHQ+Cgk8dGV4dCB4PSI5NCIgeT0iMjc0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gY3LDqW5lYXU8L3RleHQ+Cgk8bGluZSB4MT0iOTQiIHkxPSIyNzciIHgyPSIxNzkiIHkyPSIyNzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI5NCIgeT0iMjkxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8dGV4dCB4PSI5NCIgeT0iMzA4IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5oZXVyZSBkw6lidXQ8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Créneau</strong> (<u>num. créneau</u>, date, heure début)</li>\n<li><strong>Film</strong> (<u>id. film</u>, titre, durée)</li>\n<li><strong>Projeter</strong> (<u>id. projeter</u>, tarif, <em>#id. film</em>, <em>#num. salle</em>, <em>#num. créneau</em>)</li>\n<li><strong>Salle</strong> (<u>num. salle</u>, capacité)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le nouveau MCD a vocation à être retouché pour :</p>\n<ul>\n<li>se rapprocher du plongement initial ;</li>\n<li>nommer judicieusement les nouveaux identifiant, entité et associations créés.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [154]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nFilm: id. film, titre, durée\nConcerner, 11 Projection, 1N Film\nProjection: id. projection, tarif\nAvoir lieu dans, 11 Projection, 1N Salle\nSalle: num. salle, capacité\n\nAvoir lieu pendant, 11 Projection, 1N Créneau\n\nCréneau: num. créneau, date, heure début\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NjIiIGhlaWdodD0iMzAzIiB2aWV3Qm94PSIwIDAgNjYyIDMwMyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI2NjIiIGhlaWdodD0iMzAzIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBDT05DRVJORVIgLS0+CjxnPgoJPGxpbmUgeDE9IjMwMCIgeTE9IjU2IiB4Mj0iMTU0IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzgiIHkxPSI1NiIgeDI9IjE1NCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTE5OCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTExNiBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIxMiA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDExMCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxMTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOTYiIHk9IjI3IiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iOTYiIHkxPSI1NSIgeDI9IjIxMiIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTA0IiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNvbmNlcm5lcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIxOCIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjcyIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEFWT0lSX0xJRVVfREFOUyAtLT4KPGc+Cgk8bGluZSB4MT0iMzAwIiB5MT0iNTYiIHgyPSI0NjciIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI2MTQiIHkxPSI1NiIgeDI9IjQ2NyIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTUzMiAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTE1OCBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTU0NiA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQwMiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxNTgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMzg4IiB5PSIyNyIgd2lkdGg9IjE1OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjM4OCIgeTE9IjU1IiB4Mj0iNTQ2IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIzOTYiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXZvaXIgbGlldSBkYW5zPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzY0IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iNTUxIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIEFWT0lSX0xJRVVfUEVOREFOVCAtLT4KPGc+Cgk8bGluZSB4MT0iMzAwIiB5MT0iNTYiIHgyPSIzMDAiIHkyPSIxNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzAwIiB5MT0iMjQ3IiB4Mj0iMzAwIiB5Mj0iMTQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTM4MCAxMTggYTE0IDE0IDkwIDAgMSAxNCAxNCBWMTQ2IGgtMTg4IFYxMzIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTM5NCAxNDYgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgyMjAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYxNDYgSDE4OCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyMDYiIHk9IjExOCIgd2lkdGg9IjE4OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjIwNiIgeTE9IjE0NiIgeDI9IjM5NCIgeTI9IjE0NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjIxMyIgeT0iMTM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXZvaXIgbGlldSBwZW5kYW50PC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMzA1IiB5PSIxMTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjMwNSIgeT0iMTkyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEZJTE0gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNTgiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjY3IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkZpbG08L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGZpbG08L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjU5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGl0cmU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmR1csOpZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVDVElPTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNDEiIHk9IjE4IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0MSIgeT0iNDgiIHdpZHRoPSIxMTgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjQxIiB5PSIxOCIgd2lkdGg9IjExOCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyNDEiIHkxPSI0OCIgeDI9IjM1OSIgeTI9IjQ4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNTAiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvamVjdGlvbjwvdGV4dD4KCTx0ZXh0IHg9IjI0OSIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIHByb2plY3Rpb248L3RleHQ+Cgk8bGluZSB4MT0iMjQ5IiB5MT0iNjgiIHgyPSIzMzMiIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjI0OSIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGFyaWY8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFNBTExFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU3NSIgeT0iMTgiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NzUiIHk9IjQ4IiB3aWR0aD0iNzgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTc1IiB5PSIxOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU3NSIgeTE9IjQ4IiB4Mj0iNjUzIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU4OCIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TYWxsZTwvdGV4dD4KCTx0ZXh0IHg9IjU4MyIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBzYWxsZTwvdGV4dD4KCTxsaW5lIHgxPSI1ODMiIHkxPSI2OCIgeDI9IjY0NSIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTgzIiB5PSI4Mi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jYXBhY2l0w6k8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENSRU5FQVUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjQ5IiB5PSIyMDAiIHdpZHRoPSIxMDIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjQ5IiB5PSIyMzAiIHdpZHRoPSIxMDIiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjQ5IiB5PSIyMDAiIHdpZHRoPSIxMDIiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjQ5IiB5MT0iMjMwIiB4Mj0iMzUxIiB5Mj0iMjMwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjEiIHk9IjIyMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNyw6luZWF1PC90ZXh0PgoJPHRleHQgeD0iMjU3IiB5PSIyNDcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjcsOpbmVhdTwvdGV4dD4KCTxsaW5lIHgxPSIyNTciIHkxPSIyNTAiIHgyPSIzNDIiIHkyPSIyNTAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNTciIHk9IjI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPHRleHQgeD0iMjU3IiB5PSIyODEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmhldXJlIGTDqWJ1dDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Créneau</strong> (<u>num. créneau</u>, date, heure début)</li>\n<li><strong>Film</strong> (<u>id. film</u>, titre, durée)</li>\n<li><strong>Projection</strong> (<u>id. projection</u>, tarif, <em>#id. film</em>, <em>#num. salle</em>, <em>#num. créneau</em>)</li>\n<li><strong>Salle</strong> (<u>num. salle</u>, capacité)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9composer-les-associations-binaires-non-DF\">Décomposer les associations binaires non DF<a class=\"anchor-link\" href=\"#D%C3%A9composer-les-associations-binaires-non-DF\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Considérons le MCD suivant, qui comporte deux associations binaires non DF, l'une porteuse d'attribut, l'autre non :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [155]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nCOMMANDE: num. commande, date, montant\nLIGNE COM., 1N COMMANDE, 0N PRODUIT: quantité\nPRODUIT: réf. produit, libellé, prix unitaire\nDISPONIBILITÉ, 1N PRODUIT, 0N PAYS\nPAYS: code pays, nom pays\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3MTQiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgNzE0IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI3MTQiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBMSUdORV9DT01fIC0tPgo8Zz4KCTxsaW5lIHgxPSI3MiIgeTE9IjU2IiB4Mj0iMjI2IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzY3IiB5MT0iNTYiIHgyPSIyMjYiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNzQgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMjQgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yODggNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzggYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTI0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE2NCIgeT0iMjciIHdpZHRoPSIxMjQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNjQiIHkxPSI1NSIgeDI9IjI4OCIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTcxIiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkxJR05FIENPTS48L3RleHQ+CgkJPHRleHQgeD0iMTcxIiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5xdWFudGl0w6k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxNDAiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyOTMiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gRElTUE9OSUJJTElURSAtLT4KPGc+Cgk8bGluZSB4MT0iMzY3IiB5MT0iNTYiIHgyPSI1MjIiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI2NjYiIHkxPSI1NiIgeDI9IjUyMiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTU4NCAyNyBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NSBoLTE1MiBWNDEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTU5OCA1NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDQ2MCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU1IEgxNTIiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iNDQ2IiB5PSIyNyIgd2lkdGg9IjE1MiIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjQ0NiIgeTE9IjU1IiB4Mj0iNTk4IiB5Mj0iNTUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI0NTQiIHk9IjQ4LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RElTUE9OSUJJTElUw4k8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0MjIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSI2MDMiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENPTU1BTkRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iMzkiIHdpZHRoPSIxMjYiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMzUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q09NTUFOREU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTIxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPRFVJVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMTciIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzE3IiB5PSIzOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMTciIHk9IjkiIHdpZHRoPSIxMDAiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzE3IiB5MT0iMzkiIHgyPSI0MTciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzI2IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBST0RVSVQ8L3RleHQ+Cgk8dGV4dCB4PSIzMjUiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnLDqWYuIHByb2R1aXQ8L3RleHQ+Cgk8bGluZSB4MT0iMzI1IiB5MT0iNTkiIHgyPSIzOTciIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMyNSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bGliZWxsw6k8L3RleHQ+Cgk8dGV4dCB4PSIzMjUiIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQQVlTIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjYyNyIgeT0iMTgiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI2MjciIHk9IjQ4IiB3aWR0aD0iNzgiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNjI3IiB5PSIxOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjYyNyIgeTE9IjQ4IiB4Mj0iNzA1IiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjY0MiIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QQVlTPC90ZXh0PgoJPHRleHQgeD0iNjM1IiB5PSI2NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb2RlIHBheXM8L3RleHQ+Cgk8bGluZSB4MT0iNjM1IiB5MT0iNjgiIHgyPSI2OTciIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjYzNSIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHBheXM8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>COMMANDE</strong> (<u>num. commande</u>, date, montant)</li>\n<li><strong>DISPONIBILITÉ</strong> (<u><em>#réf. produit</em></u>, <u><em>#code pays</em></u>)</li>\n<li><strong>LIGNE COM.</strong> (<u><em>#num. commande</em></u>, <u><em>#réf. produit</em></u>, quantité)</li>\n<li><strong>PAYS</strong> (<u>code pays</u>, nom pays)</li>\n<li><strong>PRODUIT</strong> (<u>réf. produit</u>, libellé, prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Par souci de concision, quand on parle d'associations $n$-aires dans ce document, c'est par opposition aux associations binaires ; mais bien sûr, la règle de décomposition énoncée à la section précédente est également valable pour $n=2$, même si par défaut elle ne s'applique qu'aux associations d'arité minimale 3. En réduisant la valeur de <code>arity</code> à 2, toutes les associations binaires non DF seront également décomposées :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [156]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i=sandbox --seed=1 --scale=0.9 --mld -t explode:arity=2 arrange:wide=9\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iMTAyIiB2aWV3Qm94PSIwIDAgOTAwIDEwMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI5MDAiIGhlaWdodD0iMTAyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjI2NyIgeTE9IjUxIiB4Mj0iMTY1IiB5Mj0iNTEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KCTxsaW5lIHgxPSI2NCIgeTE9IjUxIiB4Mj0iMTY1IiB5Mj0iNTEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjE2NSIgY3k9IjUxIiByPSIxOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIxNTMiIHk9IjU2LjciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNi4yIj5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE4OSIgeT0iNjYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI5LjkiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjEyNSIgeT0iNjYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI5LjkiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjEgLS0+CjxnPgoJPGxpbmUgeDE9IjI2NyIgeTE9IjUxIiB4Mj0iMzY5IiB5Mj0iNTEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KCTxsaW5lIHgxPSI0NTkiIHkxPSI1MSIgeDI9IjM2OSIgeTI9IjUxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC45Ii8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzNjkiIGN5PSI1MSIgcj0iMTgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjM1IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMzU3IiB5PSI1Ni43IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTYuMiI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzMjkiIHk9IjY2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOS45Ij4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIzOTIiIHk9IjY2LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iOS45Ij4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYyIC0tPgo8Zz4KCTxsaW5lIHgxPSI2NjMiIHkxPSI1MSIgeDI9IjU0OSIgeTI9IjUxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC45Ii8+Cgk8bGluZSB4MT0iNDU5IiB5MT0iNTEiIHgyPSI1NDkiIHkyPSI1MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iNTQ5IiBjeT0iNTEiIHI9IjE4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjUzNyIgeT0iNTYuNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE2LjIiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iNTczIiB5PSI2Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjkuOSI+MSwxPC90ZXh0PgoJPHRleHQgeD0iNTA5IiB5PSI2Ni4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjkuOSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIERGMyAtLT4KPGc+Cgk8bGluZSB4MT0iNjYzIiB5MT0iNTEiIHgyPSI3NzciIHkyPSI1MSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOSIvPgoJPGxpbmUgeDE9Ijg1NyIgeTE9IjUxIiB4Mj0iNzc3IiB5Mj0iNTEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KCTxnPgoJCTxjaXJjbGUgY3g9Ijc3NyIgY3k9IjUxIiByPSIxOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI3NjUiIHk9IjU2LjciIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNi4yIj5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjczNyIgeT0iNjYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI5LjkiPjEsMTwvdGV4dD4KCTx0ZXh0IHg9IjgwMCIgeT0iNjYuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSI5LjkiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOCIgeT0iOCIgd2lkdGg9IjExMiIgaGVpZ2h0PSIyNyIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4IiB5PSIzNSIgd2lkdGg9IjExMiIgaGVpZ2h0PSI1OSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4IiB5PSI4IiB3aWR0aD0iMTEyIiBoZWlnaHQ9Ijg2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI4IiB5MT0iMzUiIHgyPSIxMjAiIHkyPSIzNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE1IiB5PSIyNy40NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE2LjIiPkNPTU1BTkRFPC90ZXh0PgoJPHRleHQgeD0iMTUiIHk9IjUwLjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTMuNSI+bnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIxNSIgeTE9IjUzLjMiIHgyPSIxMDgiIHkyPSI1My4zIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC45Ii8+Cgk8dGV4dCB4PSIxNSIgeT0iNjYuNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMy41Ij5kYXRlPC90ZXh0PgoJPHRleHQgeD0iMTUiIHk9IjgyLjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTMuNSI+bW9udGFudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTElHTkVfQ09NXyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMTAiIHk9IjE2IiB3aWR0aD0iMTE0IiBoZWlnaHQ9IjI3IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxMCIgeT0iNDMiIHdpZHRoPSIxMTQiIGhlaWdodD0iNDMiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjEwIiB5PSIxNiIgd2lkdGg9IjExNCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjEwIiB5MT0iNDMiIHgyPSIzMjQiIHkyPSI0MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIxOCIgeT0iMzUuNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNi4yIj5MSUdORSBDT00uPC90ZXh0PgoJPHRleHQgeD0iMjE3IiB5PSI1OC40IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEzLjUiPmlkLiBsaWduZSBjb20uPC90ZXh0PgoJPGxpbmUgeDE9IjIxNyIgeTE9IjYxLjMiIHgyPSIyOTEiIHkyPSI2MS4zIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC45Ii8+Cgk8dGV4dCB4PSIyMTciIHk9Ijc0LjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTMuNSI+cXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQxNCIgeT0iOCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjI3IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQxNCIgeT0iMzUiIHdpZHRoPSI5MCIgaGVpZ2h0PSI1OSIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MTQiIHk9IjgiIHdpZHRoPSI5MCIgaGVpZ2h0PSI4NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDE0IiB5MT0iMzUiIHgyPSI1MDQiIHkyPSIzNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMzUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQyMiIgeT0iMjcuNDUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxNi4yIj5QUk9EVUlUPC90ZXh0PgoJPHRleHQgeD0iNDIxIiB5PSI1MC40IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEzLjUiPnLDqWYuIHByb2R1aXQ8L3RleHQ+Cgk8bGluZSB4MT0iNDIxIiB5MT0iNTMuMyIgeDI9IjQ4NiIgeTI9IjUzLjMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KCTx0ZXh0IHg9IjQyMSIgeT0iNjYuNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMy41Ij5saWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjQyMSIgeT0iODIuNCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxMy41Ij5wcml4IHVuaXRhaXJlPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBESVNQT05JQklMSVRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU5NCIgeT0iMjQiIHdpZHRoPSIxMzgiIGhlaWdodD0iMjciIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTk0IiB5PSI1MSIgd2lkdGg9IjEzOCIgaGVpZ2h0PSIyNyIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1OTQiIHk9IjI0IiB3aWR0aD0iMTM4IiBoZWlnaHQ9IjU0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1OTQiIHkxPSI1MSIgeDI9IjczMiIgeTI9IjUxIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIvPgoJPC9nPgoJPHRleHQgeD0iNjAyIiB5PSI0My40NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE2LjIiPkRJU1BPTklCSUxJVMOJPC90ZXh0PgoJPHRleHQgeD0iNjAxIiB5PSI2Ni40IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjEzLjUiPmlkLiBkaXNwb25pYmlsaXTDqTwvdGV4dD4KCTxsaW5lIHgxPSI2MDEiIHkxPSI2OS4zIiB4Mj0iNjg2IiB5Mj0iNjkuMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuOSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBQQVlTIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjgyMiIgeT0iMTYiIHdpZHRoPSI3MCIgaGVpZ2h0PSIyNyIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI4MjIiIHk9IjQzIiB3aWR0aD0iNzAiIGhlaWdodD0iNDMiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iODIyIiB5PSIxNiIgd2lkdGg9IjcwIiBoZWlnaHQ9IjcwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI4MjIiIHkxPSI0MyIgeDI9Ijg5MiIgeTI9IjQzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4zNSIvPgoJPC9nPgoJPHRleHQgeD0iODM2IiB5PSIzNS40NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE2LjIiPlBBWVM8L3RleHQ+Cgk8dGV4dCB4PSI4MjkiIHk9IjU4LjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTMuNSI+Y29kZSBwYXlzPC90ZXh0PgoJPGxpbmUgeDE9IjgyOSIgeTE9IjYxLjMiIHgyPSI4ODUiIHkyPSI2MS4zIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMC45Ii8+Cgk8dGV4dCB4PSI4MjkiIHk9Ijc0LjQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTMuNSI+bm9tIHBheXM8L3RleHQ+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>COMMANDE</strong> (<u>num. commande</u>, date, montant)</li>\n<li><strong>DISPONIBILITÉ</strong> (<u>id. disponibilité</u>, <em>#réf. produit</em>, <em>#code pays</em>)</li>\n<li><strong>LIGNE COM.</strong> (<u>id. ligne com.</u>, quantité, <em>#num. commande</em>, <em>#réf. produit</em>)</li>\n<li><strong>PAYS</strong> (<u>code pays</u>, nom pays)</li>\n<li><strong>PRODUIT</strong> (<u>réf. produit</u>, libellé, prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cette décomposition devient un peu extrême ! Vous pouvez conserver certaines associations binaires non DF, à savoir celles qui ne portent aucun attribut, en mettant <code>arity</code> à <code>2.5</code> (à lire comme « intermédiaire entre <code>2</code> et <code>3</code> ») :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [157]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i=sandbox --mld -t explode:arity=2.5 arrange:wide --seed=1\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTQiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgODU0IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI4NTQiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBESVNQT05JQklMSVRFIC0tPgo8Zz4KCTxsaW5lIHgxPSIzNDciIHkxPSI1NiIgeDI9IjE5MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNTYiIHgyPSIxOTIiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNTQgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xNTIgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjggNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMzAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTUyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMjciIHdpZHRoPSIxNTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMTYiIHkxPSI1NSIgeDI9IjI2OCIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTI0IiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRJU1BPTklCSUxJVMOJPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjczIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iOTIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8Zz4KCTxsaW5lIHgxPSI1NTgiIHkxPSI1NiIgeDI9IjQ0NiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0NyIgeTE9IjU2IiB4Mj0iNDQ2IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI0NDYiIGN5PSI1NiIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI0MzMiIHk9IjYwLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0NzIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI0MDIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYxIC0tPgo8Zz4KCTxsaW5lIHgxPSI1NTgiIHkxPSI1NiIgeDI9IjY3MCIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9Ijc4MiIgeTE9IjU2IiB4Mj0iNjcwIiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI2NzAiIGN5PSI1NiIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI2NTciIHk9IjYwLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI2MjYiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI2OTUiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBBWVMgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTgiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI0OCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE4IiB3aWR0aD0iNzgiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjQ4IiB4Mj0iODciIHkyPSI0OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjQiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UEFZUzwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI2NS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb2RlIHBheXM8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI2OCIgeDI9Ijc5IiB5Mj0iNjgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIHBheXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFBST0RVSVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjk3IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5NyIgeT0iMzkiIHdpZHRoPSIxMDAiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjk3IiB5PSI5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI5NyIgeTE9IjM5IiB4Mj0iMzk3IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMwNiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QUk9EVUlUPC90ZXh0PgoJPHRleHQgeD0iMzA1IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjMwNSIgeTE9IjU5IiB4Mj0iMzc3IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIzMDUiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iMzA1IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgTElHTkVfQ09NXyAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI0OTUiIHk9IjE4IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5NSIgeT0iNDgiIHdpZHRoPSIxMjYiIGhlaWdodD0iNDYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDk1IiB5PSIxOCIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0OTUiIHkxPSI0OCIgeDI9IjYyMSIgeTI9IjQ4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1MDMiIHk9IjM5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+TElHTkUgQ09NLjwvdGV4dD4KCTx0ZXh0IHg9IjUwMyIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aWQuIGxpZ25lIGNvbS48L3RleHQ+Cgk8bGluZSB4MT0iNTAzIiB5MT0iNjgiIHgyPSI1ODUiIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjUwMyIgeT0iODIuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDT01NQU5ERSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI3MTkiIHk9IjkiIHdpZHRoPSIxMjYiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNzE5IiB5PSIzOSIgd2lkdGg9IjEyNiIgaGVpZ2h0PSI2NCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI3MTkiIHk9IjkiIHdpZHRoPSIxMjYiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNzE5IiB5MT0iMzkiIHgyPSI4NDUiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNzI4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNPTU1BTkRFPC90ZXh0PgoJPHRleHQgeD0iNzI3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0uIGNvbW1hbmRlPC90ZXh0PgoJPGxpbmUgeDE9IjcyNyIgeTE9IjU5IiB4Mj0iODMxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI3MjciIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8dGV4dCB4PSI3MjciIHk9IjkwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tb250YW50PC90ZXh0Pgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>COMMANDE</strong> (<u>num. commande</u>, date, montant)</li>\n<li><strong>DISPONIBILITÉ</strong> (<u><em>#réf. produit</em></u>, <u><em>#code pays</em></u>)</li>\n<li><strong>LIGNE COM.</strong> (<u>id. ligne com.</u>, quantité, <em>#réf. produit</em>, <em>#num. commande</em>)</li>\n<li><strong>PAYS</strong> (<u>code pays</u>, nom pays)</li>\n<li><strong>PRODUIT</strong> (<u>réf. produit</u>, libellé, prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9composer-en-cr%C3%A9ant-des-entit%C3%A9s-faibles\">Décomposer en créant des entités faibles<a class=\"anchor-link\" href=\"#D%C3%A9composer-en-cr%C3%A9ant-des-entit%C3%A9s-faibles\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ci-dessus, le processus de modification a créé un identifiant <em>id. ligne com.</em> qui peut sembler superfétatoire. Si l'on a introduit la notion d'entité faible, on aura ici avantage à utiliser l'option <code>weak</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [158]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i=sandbox --mld -t explode:arity=2.5,weak arrange:wide --seed=1\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTQiIGhlaWdodD0iMTEyIiB2aWV3Qm94PSIwIDAgODU0IDExMiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI4NTQiIGhlaWdodD0iMTEyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBESVNQT05JQklMSVRFIC0tPgo8Zz4KCTxsaW5lIHgxPSIzNDciIHkxPSI1NiIgeDI9IjE5MiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4IiB5MT0iNTYiIHgyPSIxOTIiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNTQgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xNTIgVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNjggNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMzAgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTUyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjExNiIgeT0iMjciIHdpZHRoPSIxNTIiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMTYiIHkxPSI1NSIgeDI9IjI2OCIgeTI9IjU1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTI0IiB5PSI0OC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRJU1BPTklCSUxJVMOJPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjczIiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iOTIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYwIC0tPgo8Zz4KCTxsaW5lIHgxPSI1NTgiIHkxPSI1NiIgeDI9IjQ0NiIgeTI9IjU2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjM0NyIgeTE9IjU2IiB4Mj0iNDQ2IiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI0NDYiIGN5PSI1NiIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI0MzMiIHk9IjYwLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSI0NzIiIHk9IjcyIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iNDcyIiB5MT0iNzQiIHgyPSI0OTAiIHkyPSI3NCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQwMiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjEgLS0+CjxnPgoJPGxpbmUgeDE9IjU1OCIgeTE9IjU2IiB4Mj0iNjcwIiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzgyIiB5MT0iNTYiIHgyPSI2NzAiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjY3MCIgY3k9IjU2IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjY1NyIgeT0iNjAuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjYyNiIgeT0iNzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSI2MjYiIHkxPSI3NCIgeDI9IjY0NCIgeTI9Ijc0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNjk1IiB5PSI3MiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQQVlTIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjE4IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iNDgiIHdpZHRoPSI3OCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSI0OCIgeDI9Ijg3IiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI0IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBBWVM8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y29kZSBwYXlzPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNjgiIHgyPSI3OSIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTciIHk9IjgyLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5vbSBwYXlzPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI5NyIgeT0iOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyOTciIHk9IjM5IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI5NyIgeT0iOSIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI5NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyOTciIHkxPSIzOSIgeDI9IjM5NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMDYiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UFJPRFVJVDwvdGV4dD4KCTx0ZXh0IHg9IjMwNSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+csOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzMDUiIHkxPSI1OSIgeDI9IjM3NyIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzA1IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5saWJlbGzDqTwvdGV4dD4KCTx0ZXh0IHg9IjMwNSIgeT0iOTAiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByaXggdW5pdGFpcmU8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IExJR05FX0NPTV8gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNDk1IiB5PSIyNiIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0OTUiIHk9IjU2IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ5NSIgeT0iMjYiIHdpZHRoPSIxMjYiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iNDk1IiB5MT0iNTYiIHgyPSI2MjEiIHkyPSI1NiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNTAzIiB5PSI0Ny4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkxJR05FIENPTS48L3RleHQ+Cgk8dGV4dCB4PSI1MDMiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnF1YW50aXTDqTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNzE5IiB5PSI5IiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjcxOSIgeT0iMzkiIHdpZHRoPSIxMjYiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNzE5IiB5PSI5IiB3aWR0aD0iMTI2IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjcxOSIgeTE9IjM5IiB4Mj0iODQ1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjcyOCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01NQU5ERTwvdGV4dD4KCTx0ZXh0IHg9IjcyNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSI3MjciIHkxPSI1OSIgeDI9IjgzMSIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNzI3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPHRleHQgeD0iNzI3IiB5PSI5MCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bW9udGFudDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>COMMANDE</strong> (<u>num. commande</u>, date, montant)</li>\n<li><strong>DISPONIBILITÉ</strong> (<u><em>#réf. produit</em></u>, <u><em>#code pays</em></u>)</li>\n<li><strong>LIGNE COM.</strong> (<u><em>#num. commande</em></u>, <u><em>#réf. produit</em></u>, quantité)</li>\n<li><strong>PAYS</strong> (<u>code pays</u>, nom pays)</li>\n<li><strong>PRODUIT</strong> (<u>réf. produit</u>, libellé, prix unitaire)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>Cas des agrégats.</strong> Comme on sait, la notion d'entité faible peut souvent permettre de se passer de celle d'agrégat. Ainsi, le MCD ci-dessous :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [159]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t --colors ocean\nChambre: num. chambre, tarif\nRéservation, /1N Client, 1N Chambre, 0N Date: durée\nClient: réf. client, nom client\n\nDate: date\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MzIiIGhlaWdodD0iMTk3IiB2aWV3Qm94PSIwIDAgNDMyIDE5NyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0MzIiIGhlaWdodD0iMTk3IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVNFUlZBVElPTiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIzMjQiIGN5PSI1NiIgcj0iNiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNjMGQ0ZmY1NSIvPgoJPGxpbmUgeDE9IjM3MiIgeTE9IjU2IiB4Mj0iMjI3IiB5Mj0iNTYiIHN0cm9rZT0iIzcyNmY4MyIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzEiIHkxPSI1NiIgeDI9IjIyNyIgeTI9IjU2IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIyNyIgeTE9IjE0OSIgeDI9IjIyNyIgeTI9IjU2IiBzdHJva2U9IiM3MjZmODMiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIwIDEzIEwyODkgMTMgYTcgNyAwIDAgMSA3IDcgTDI5NiAxNzcgYTcgNyAwIDAgMSAtNyA3IEwxNjUgMTg0IGE3IDcgMCAwIDEgLTcgLTcgTDE1OCAxMDYgYTcgNyAwIDAgMCAtNyAtNyBMMjAgOTkgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC4zIi8+CgkJPHBhdGggZD0iTTIwIDEzIEwyODkgMTMgYTcgNyAwIDAgMSA3IDcgTDI5NiAxNzcgYTcgNyAwIDAgMSAtNyA3IEwxNjUgMTg0IGE3IDcgMCAwIDEgLTcgLTcgTDE1OCAxMDYgYTcgNyAwIDAgMCAtNyAtNyBMMjAgOTkgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yNzcgMjcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTUgaC0xMjggVjQxIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiNiMmJiYTQiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yOTEgNTUgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzcgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY1NSBIMTI4IiBmaWxsPSIjY2NkNmJhIiBzdHJva2U9IiNjY2Q2YmEiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE2MyIgeT0iMjciIHdpZHRoPSIxMjgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjODU5NTZiIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNjMiIHkxPSI1NSIgeDI9IjI5MSIgeTI9IjU1IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTcxIiB5PSI0OC4zIiBmaWxsPSIjMjczNjBjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDqXNlcnZhdGlvbjwvdGV4dD4KCQk8dGV4dCB4PSIxNzAiIHk9IjczLjEiIGZpbGw9IiM2MDc3MzQiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmR1csOpZTwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjMwMSIgeT0iNzciIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjEzNCIgeT0iNzciIGZpbGw9IiM3MjZmODMiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjIzNyIgeT0iMTA2IiBmaWxsPSIjNzI2ZjgzIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENIQU1CUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTgiIHk9IjE4IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE4IiB5PSI0OCIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI0NiIgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iMTgiIHdpZHRoPSIxMDYiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTgiIHkxPSI0OCIgeDI9IjEyNCIgeTI9IjQ4IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMSIgeT0iMzkuMyIgZmlsbD0iIzEzMTExNCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DaGFtYnJlPC90ZXh0PgoJPHRleHQgeD0iMjYiIHk9IjY1LjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gY2hhbWJyZTwvdGV4dD4KCTxsaW5lIHgxPSIyNiIgeTE9IjY4IiB4Mj0iMTE1IiB5Mj0iNjgiIHN0cm9rZT0iIzNlM2M0MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIyNiIgeT0iODIuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGFyaWY8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENMSUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMzAiIHk9IjE4IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzMwIiB5PSI0OCIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjYzBkNGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMzMCIgeT0iMTgiIHdpZHRoPSI4NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMzAiIHkxPSI0OCIgeDI9IjQxNCIgeTI9IjQ4IiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNDIiIHk9IjM5LjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iMzM4IiB5PSI2NS4xIiBmaWxsPSIjM2UzYzQyIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iMzM4IiB5MT0iNjgiIHgyPSIzOTciIHkyPSI2OCIgc3Ryb2tlPSIjM2UzYzQyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjMzOCIgeT0iODIuMSIgZmlsbD0iIzNlM2M0MiIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGNsaWVudDwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgREFURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxOTciIHk9IjExOSIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE5NyIgeT0iMTQ5IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTk3IiB5PSIxMTkiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxOTciIHkxPSIxNDkiIHgyPSIyNTciIHkyPSIxNDkiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIwNiIgeT0iMTQwLjMiIGZpbGw9IiMxMzExMTQiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjIwNSIgeT0iMTY2LjEiIGZpbGw9IiMzZTNjNDIiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmRhdGU8L3RleHQ+Cgk8bGluZSB4MT0iMjA1IiB5MT0iMTY5IiB4Mj0iMjMzIiB5Mj0iMTY5IiBzdHJva2U9IiMzZTNjNDIiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Chambre</strong> (<u>num. chambre</u>, tarif)</li>\n<li><strong>Client</strong> (<u>réf. client</u>, nom client)</li>\n<li><strong>Réservation</strong> (<u><em>#num. chambre</em></u>, <u>date</u>, <em>#réf. client</em>, durée)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>... se verra décomposé de la même façon que sans agrégat, à ceci près que la patte distinguée par le <code>\"/\"</code> produira une cardinalité <code>11</code> au lieu d'une cardinalité <code>_11</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [160]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --mld -t explode:weak arrange:wide=5 --seed 21\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MzQiIGhlaWdodD0iMTc4IiB2aWV3Qm94PSIwIDAgNTM0IDE3OCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI1MzQiIGhlaWdodD0iMTc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjI3OCIgeTE9IjQ3IiB4Mj0iMTY0IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjIiIHkxPSI0NyIgeDI9IjE2NCIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTY0IiBjeT0iNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTUxIiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTkwIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjE5MCIgeTE9IjY1IiB4Mj0iMjA4IiB5Mj0iNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxMjAiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNzgiIHkxPSI0NyIgeDI9IjM5MiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4MyIgeTE9IjQ3IiB4Mj0iMzkyIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzOTIiIGN5PSI0NyIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIzNzkiIHk9IjUxLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzNDgiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI0MTciIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYyIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNzgiIHkxPSI0NyIgeDI9IjI3OCIgeTI9IjEzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIxNjQiIHkxPSIxMzkiIHgyPSIyNzgiIHkyPSIxMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIyNzgiIGN5PSIxMzkiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMjY1IiB5PSIxNDMuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjI4MyIgeT0iOTMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsMTwvdGV4dD4KCTxsaW5lIHgxPSIyODMiIHkxPSI5NSIgeDI9IjMwMSIgeTI9Ijk1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMTk5IiB5PSIxNTUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0hBTUJSRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMDYiIGhlaWdodD0iNzYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjM5IiB4Mj0iMTE1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyIiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNoYW1icmU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bnVtLiBjaGFtYnJlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSIxMDYiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij50YXJpZjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUkVTRVJWQVRJT04gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjEzIiB5PSIxNyIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTMiIHk9IjQ3IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxMyIgeT0iMTciIHdpZHRoPSIxMzAiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjEzIiB5MT0iNDciIHgyPSIzNDMiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjIyIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlLDqXNlcnZhdGlvbjwvdGV4dD4KCTx0ZXh0IHg9IjIyMSIgeT0iNjQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZHVyw6llPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iNDQxIiB5PSI5IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDQxIiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ0MSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQ0MSIgeTE9IjM5IiB4Mj0iNTI1IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ1MyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DbGllbnQ8L3RleHQ+Cgk8dGV4dCB4PSI0NDkiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnLDqWYuIGNsaWVudDwvdGV4dD4KCTxsaW5lIHgxPSI0NDkiIHkxPSI1OSIgeDI9IjUwOCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDQ5IiB5PSI3My4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gY2xpZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBEQVRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzNCIgeT0iMTA5IiB3aWR0aD0iNjAiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTM0IiB5PSIxMzkiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzQiIHk9IjEwOSIgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEzNCIgeTE9IjEzOSIgeDI9IjE5NCIgeTI9IjEzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQzIiB5PSIxMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5EYXRlPC90ZXh0PgoJPHRleHQgeD0iMTQyIiB5PSIxNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZGF0ZTwvdGV4dD4KCTxsaW5lIHgxPSIxNDIiIHkxPSIxNTkiIHgyPSIxNzAiIHkyPSIxNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Chambre</strong> (<u>num. chambre</u>, tarif)</li>\n<li><strong>Client</strong> (<u>réf. client</u>, nom client)</li>\n<li><strong>Réservation</strong> (<u>date</u>, <u><em>#num. chambre</em></u>, durée, <em>#réf. client</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Cette décomposition peut quelquefois se simplifier. Ici, on remarque que l'entité DATE est indépendante et réduite à son identifiant. Si l'on anticipe sur le passage au relationnel, on peut donc la supprimer, après avoir pris soin, bien sûr, de déplacer dans RÉSERVATION son unique attribut. Celui-ci renforçant une entité faible, il doit garder son caractère identifiant.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [161]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nChambre: num. chambre, tarif\nDF, _11 Réservation, 1N Chambre\nRéservation: date, durée\nDF, 11 Réservation, 1N Client\nClient: réf. client, nom client\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MzQiIGhlaWdodD0iOTQiIHZpZXdCb3g9IjAgMCA1MzQgOTQiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iNTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjI3OCIgeTE9IjQ3IiB4Mj0iMTY0IiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjIiIHkxPSI0NyIgeDI9IjE2NCIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTY0IiBjeT0iNDciIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTUxIiB5PSI1MS44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTkwIiB5PSI2MyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSwxPC90ZXh0PgoJPGxpbmUgeDE9IjE5MCIgeTE9IjY1IiB4Mj0iMjA4IiB5Mj0iNjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxMjAiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNzgiIHkxPSI0NyIgeDI9IjM5MiIgeTI9IjQ3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjQ4MyIgeTE9IjQ3IiB4Mj0iMzkyIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzOTIiIGN5PSI0NyIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIzNzkiIHk9IjUxLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIzNDgiIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSI0MTciIHk9IjYzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IENIQU1CUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9IjEwNiIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSI5IiB3aWR0aD0iMTA2IiBoZWlnaHQ9Ijc2IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjExNSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DaGFtYnJlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bS4gY2hhbWJyZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iMTA2IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNyIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGFyaWY8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFJFU0VSVkFUSU9OIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIxMyIgeT0iOSIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTMiIHk9IjM5IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxMyIgeT0iOSIgd2lkdGg9IjEzMCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMTMiIHkxPSIzOSIgeDI9IjM0MyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyMjIiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UsOpc2VydmF0aW9uPC90ZXh0PgoJPHRleHQgeD0iMjIxIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5kYXRlPC90ZXh0PgoJPGxpbmUgeDE9IjIyMSIgeTE9IjU5IiB4Mj0iMjQ5IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtZGFzaGFycmF5PSI0Ii8+Cgk8dGV4dCB4PSIyMjEiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmR1csOpZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ0xJRU5UIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQ0MSIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjQ0MSIgeT0iMzkiIHdpZHRoPSI4NCIgaGVpZ2h0PSI0NiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0NDEiIHk9IjkiIHdpZHRoPSI4NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI0NDEiIHkxPSIzOSIgeDI9IjUyNSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0NTMiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2xpZW50PC90ZXh0PgoJPHRleHQgeD0iNDQ5IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDQ5IiB5MT0iNTkiIHgyPSI1MDgiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ0OSIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bm9tIGNsaWVudDwvdGV4dD4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Chambre</strong> (<u>num. chambre</u>, tarif)</li>\n<li><strong>Client</strong> (<u>réf. client</u>, nom client)</li>\n<li><strong>Réservation</strong> (<u><em>#num. chambre</em></u>, <u>date</u>, durée, <em>#réf. client</em>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Conclusion-sur-ces-d%C3%A9compositions\">Conclusion sur ces décompositions<a class=\"anchor-link\" href=\"#Conclusion-sur-ces-d%C3%A9compositions\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Comme l'indique le nom que nous leur avons malicieusement attribué, certaines de ces décompositions peuvent littéralement faire <em>exploser</em> la taille du MCD. Cependant :</p>\n<ul>\n<li>elles sont intéressantes d'un point de vue <s>terroriste</s> théorique ;</li>\n<li>elles peuvent permettre la détection d'erreurs de conception ;</li>\n<li>elles peuvent conduire à des améliorations fines du MCD (c'est ce qu'on a fait sur celui des réservations de chambre) ;</li>\n<li>elles décrivent le MCD dans un langage volontairement appauvri, ce qui le rendra plus aisément portable dans une autre notation, comme UML ou <em>crow's foot</em>.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"%C3%89quivalences-avec-la-convention-Look-Across\">Équivalences avec la convention <em>Look Across</em><a class=\"anchor-link\" href=\"#%C3%89quivalences-avec-la-convention-Look-Across\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La convention <em>Look Across</em> s'oppose à la convention <em>Look Here</em> de Merise. Elle est plus répandue internationalement.\nNous allons l'étudier par le biais du formalisme graphique de Chen, auquel cette section pourra du même coup servir d'introduction pour les personnes familières avec Merise.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Associations-binaires-en-Look-Across\">Associations binaires en <em>Look Across</em><a class=\"anchor-link\" href=\"#Associations-binaires-en-Look-Across\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Cardinalit%C3%A9s-minimale-et-maximale\">Cardinalités minimale et maximale<a class=\"anchor-link\" href=\"#Cardinalit%C3%A9s-minimale-et-maximale\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Considérons un MCD Merise avec une association de dépendance fonctionnelle :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [162]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nEmployé: employé\nTravailler, 11 Département, 1N Employé\nDépartement: département\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTgiIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCA0MTggNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iNDE4IiBoZWlnaHQ9Ijc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBUUkFWQUlMTEVSIC0tPgo8Zz4KCTxsaW5lIHgxPSIzNDIiIHkxPSIzOSIgeDI9IjE4OSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjU2IiB5MT0iMzkiIHgyPSIxODkiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMzIgMTAgYTE0IDE0IDkwIDAgMSAxNCAxNCBWMzggaC0xMTQgVjI0IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yNDYgMzggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNDYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYzOCBIMTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjEzMiIgeT0iMTAiIHdpZHRoPSIxMTQiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxMzIiIHkxPSIzOCIgeDI9IjI0NiIgeTI9IjM4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTM5IiB5PSIzMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRyYXZhaWxsZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNTIiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIxMDgiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVNUExPWUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjEwMyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOCIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FbXBsb3nDqTwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5lbXBsb3nDqTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjU5IiB4Mj0iNzEiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgREVQQVJURU1FTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjc1IiB5PSI5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI3NSIgeT0iMzkiIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc1IiB5PSI5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NSIgeTE9IjM5IiB4Mj0iNDA5IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4MyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Ew6lwYXJ0ZW1lbnQ8L3RleHQ+Cgk8dGV4dCB4PSIyODMiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmTDqXBhcnRlbWVudDwvdGV4dD4KCTxsaW5lIHgxPSIyODMiIHkxPSI1OSIgeDI9IjM2NCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans le formalisme graphique de Chen, cela donnera :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [163]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjQ4MHB0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNDc5LjY1IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDQ3NS42NSwtNTQuNCA0NzUuNjUsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNzguMjUsLTQzLjIgMCwtNDMuMiAwLC03LjIgNzguMjUsLTcuMiA3OC4yNSwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzOS4xMiIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkVtcGxvecOpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjE5LjcsLTUwLjQgMTUwLjI1LC0yNS4yIDIxOS43LDAgMjg5LjE1LC0yNS4yIDIxOS43LC01MC40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIxOS43IiB5PSItMjAuNTMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+VHJhdmFpbGxlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik03OC4zMSwtMjQuMkM5OC45NSwtMjQuMiAxMjQuOSwtMjQuMiAxNDguOTIsLTI0LjIiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzguMzEsLTI2LjJDOTguOTUsLTI2LjIgMTI0LjksLTI2LjIgMTQ4LjkyLC0yNi4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzMC44IiB5PSItMjguOTgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjQ3MS42NSwtNDMuMiAzNjEuMTUsLTQzLjIgMzYxLjE1LC03LjIgNDcxLjY1LC03LjIgNDcxLjY1LC00My4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQxNi40IiB5PSItMjAuNTMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+RMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTM2MC44MiwtMjYuMkMzMzkuMDEsLTI2LjIgMzEzLjcxLC0yNi4yIDI5MC42MSwtMjYuMiIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0zNjAuODIsLTI0LjJDMzM5LjAxLC0yNC4yIDMxMy43MSwtMjQuMiAyOTAuNjEsLTI0LjIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzA4LjczIiB5PSItMTIuMDciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le 1 et le N correspondent aux cardinalités maximales du MCD Merise. Comme on voit, elles sont permutées. Merise suit la convention <em>Look Here</em> (LH) ; la notation de Chen, <em>Look Across</em> (LA). Comme cette dernière est la plus répandue dans le monde anglo-saxon, nous parlerons par commodité d'« ERD » (<em>Entity-relationship diagram</em>) pour les modèles conceptuels selon Chen, et toujours de « MCD » pour ceux de Merise.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Considérons maintenant les deux versions d'une association avec des cardinalités minimales distinctes :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [164]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nMer: mer\nRecevoir, 01 Rivière, 1N Mer\nRivière: rivière\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTAiIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCAzMTAgNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzEwIiBoZWlnaHQ9Ijc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRUNFVk9JUiAtLT4KPGc+Cgk8bGluZSB4MT0iMjU5IiB5MT0iMzkiIHgyPSIxNDAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzNiIgeTE9IjM5IiB4Mj0iMTQwIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMTc0IDEwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjM4IGgtOTYgVjI0IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0xODggMzggdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxMDYgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFYzOCBIOTYiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iOTIiIHk9IjEwIiB3aWR0aD0iOTYiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSI5MiIgeTE9IjM4IiB4Mj0iMTg4IiB5Mj0iMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSI5OSIgeT0iMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SZWNldm9pcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5NCIgeT0iNTUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsMTwvdGV4dD4KCTx0ZXh0IHg9IjY4IiB5PSI1NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBNRVIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjM5IiB3aWR0aD0iNTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iOSIgeT0iOSIgd2lkdGg9IjU0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjkiIHkxPSIzOSIgeDI9IjYzIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE4IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPk1lcjwvdGV4dD4KCTx0ZXh0IHg9IjE3IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5tZXI8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjQzIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFJJVklFUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjE3IiB5PSI5IiB3aWR0aD0iODQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjE3IiB5PSIzOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxNyIgeT0iOSIgd2lkdGg9Ijg0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIxNyIgeTE9IjM5IiB4Mj0iMzAxIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyNiIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SaXZpw6hyZTwvdGV4dD4KCTx0ZXh0IHg9IjIyNSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cml2acOocmU8L3RleHQ+Cgk8bGluZSB4MT0iMjI1IiB5MT0iNTkiIHgyPSIyNjYiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [165]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjQwMXB0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNDAwLjg3IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDM5Ni44NywtNTQuNCAzOTYuODcsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNTQsLTQzLjIgMCwtNDMuMiAwLC03LjIgNTQsLTcuMiA1NCwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyNyIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk1lcjwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjE4OS45MywtNTAuNCAxMjYsLTI1LjIgMTg5LjkzLDAgMjUzLjg3LC0yNS4yIDE4OS45MywtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODkuOTMiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5SZWNldm9pcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01NC4yNywtMjQuMkM3My41NywtMjQuMiAxMDAuMjksLTI0LjIgMTI0LjkxLC0yNC4yIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTU0LjI3LC0yNi4yQzczLjU3LC0yNi4yIDEwMC4yOSwtMjYuMiAxMjQuOTEsLTI2LjIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTA2Ljc5IiB5PSItMjguOTgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjM5Mi44NywtNDMuMiAzMjUuODcsLTQzLjIgMzI1Ljg3LC03LjIgMzkyLjg3LC03LjIgMzkyLjg3LC00My4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM1OS4zNyIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJpdmnDqHJlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTMyNS40OSwtMjUuMkMzMDUuMywtMjUuMiAyNzkuMDEsLTI1LjIgMjU0Ljk2LC0yNS4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI3My4wOCIgeT0iLTEyLjA3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPC9nPgo8L3N2Zz4K\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les cardinalités maximales sont toujours permutées ; par contre, les cardinalités minimales ne le sont pas. Dans l'ERD, elles sont figurées par un trait simple (0) ou double (1). On les appelle aussi des « participations » : une rivière peut ne participer (directement) à l'alimentation d'aucune mer (ce n'est pas un fleuve) ; toute mer participe à la réception d'une rivière (un fleuve) minimum. Les conventions sont donc les suivantes :</p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Cardinalités</th>\n<th style=\"text-align:center\">MCD Merise</th>\n<th style=\"text-align:center\">ERD Chen</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">minimale</td>\n<td style=\"text-align:center\">LH</td>\n<td style=\"text-align:center\">LH</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">maximale</td>\n<td style=\"text-align:center\">LH</td>\n<td style=\"text-align:center\">LA</td>\n</tr>\n</tbody>\n</table>\n<p>La notation Merise a l'avantage de la cohérence ; celle de Chen en a d'autres, que nous verrons un peu plus loin.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Avant cela, voyons un dernier point de détail : lorsque deux cardinalités N se trouvent de part et d'autre d'une association binaire, l'une est notée M :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [166]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nPROJET: projet\nREQUÉRIR, 1N PROJET, 0N PIÈCE\nPIÈCE: pièce\nCOMPOSER, 0N PIÈCE, 0N PIÈCE\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OTciIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCA0OTcgNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iNDk3IiBoZWlnaHQ9Ijc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBSRVFVRVJJUiAtLT4KPGc+Cgk8bGluZSB4MT0iNTMiIHkxPSIzOSIgeDI9IjE4MiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMwMyIgeTE9IjM5IiB4Mj0iMTgyIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjI0IDEwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjM4IGgtMTEyIFYyNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjM4IDM4IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTQwIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzggSDExMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxMjYiIHk9IjEwIiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTI2IiB5MT0iMzgiIHgyPSIyMzgiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjEzNCIgeT0iMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SRVFVw4lSSVI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxMDIiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDMiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQ09NUE9TRVIgLS0+CjxnPgoJPHBhdGggZD0iTTMwMyAzOSBDMzI4LjY3IDcgMzcwLjMzIDcgNDI4IDM5IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHBhdGggZD0iTTMwMyAzOSBDMzI4LjY3IDcxIDM3MC4zMyA3MSA0MjggMzkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNNDc0IDEwIGExNCAxNCA5MCAwIDEgMTQgMTQgVjM4IGgtMTIwIFYyNCBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNNDg4IDM4IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMzgyIGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMzggSDEyMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIzNjgiIHk9IjEwIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMzY4IiB5MT0iMzgiIHgyPSI0ODgiIHkyPSIzOCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjM3NSIgeT0iMzEuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DT01QT1NFUjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjM0NCIgeT0iMzIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KCTx0ZXh0IHg9IjM0NCIgeT0iNTQiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijg4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI4OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI5NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5QUk9KRVQ8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI1NiIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBQSUVDRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNjciIHk9IjkiIHdpZHRoPSI3MiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjciIHk9IjM5IiB3aWR0aD0iNzIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjY3IiB5PSI5IiB3aWR0aD0iNzIiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjY3IiB5MT0iMzkiIHgyPSIzMzkiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjc1IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlBJw4hDRTwvdGV4dD4KCTx0ZXh0IHg9IjI3NSIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cGnDqGNlPC90ZXh0PgoJPGxpbmUgeDE9IjI3NSIgeTE9IjU5IiB4Mj0iMzA4IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [167]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjY4N3B0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNjg2Ljc5IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDY4Mi43OSwtNTQuNCA2ODIuNzksNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNzIuMjUsLTQzLjIgMCwtNDMuMiAwLC03LjIgNzIuMjUsLTcuMiA3Mi4yNSwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNi4xMiIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlBST0pFVDwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIyMy41LC01MC40IDE0NC4yNSwtMjUuMiAyMjMuNSwwIDMwMi43NiwtMjUuMiAyMjMuNSwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjMuNSIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJFUVXDiVJJUjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik03Mi43LC0yNC4yQzkyLjcyLC0yNC4yIDExOC4zNywtMjQuMiAxNDIuODIsLTI0LjIiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzIuNywtMjYuMkM5Mi43MiwtMjYuMiAxMTguMzcsLTI2LjIgMTQyLjgyLC0yNi4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEyNC42OSIgeT0iLTI4Ljk4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI0MzcuMjYsLTQzLjIgMzc0Ljc2LC00My4yIDM3NC43NiwtNy4yIDQzNy4yNiwtNy4yIDQzNy4yNiwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0MDYuMDEiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5QScOIQ0U8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMzc0LjYzLC0yNS4yQzM1NS4xNywtMjUuMiAzMjkuMTksLTI1LjIgMzA0LjI3LC0yNS4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMyMi40IiB5PSItMTIuMDciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TTwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjU5NC4wMiwtNTAuNCA1MDkuMjYsLTI1LjIgNTk0LjAyLDAgNjc4Ljc5LC0yNS4yIDU5NC4wMiwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1OTQuMDIiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DT01QT1NFUjwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyYjNDU7NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmIzQ1OzQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik00MzcuNDgsLTMwLjM5QzQ2Mi40NiwtMzEuODkgNDk4LjIzLC0zMi4zMSA1MjkuMjcsLTMxLjY1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjUxMS4zIiB5PSItMzUuNzQiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TTwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MyAtLT4KPGcgaWQ9ImVkZ2U0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01MjkuMzIsLTE4Ljc1QzQ5OC4zLC0xOC4wOSA0NjIuNTUsLTE4LjUxIDQzNy41NiwtMjAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDU1LjIxIiB5PSItNS45MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Entit%C3%A9s-faibles-et-entit%C3%A9s-associatives\">Entités faibles et entités associatives<a class=\"anchor-link\" href=\"#Entit%C3%A9s-faibles-et-entit%C3%A9s-associatives\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Maintenant examinons le cas des entités faibles :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [168]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nŒuvre: œuvre\nDF, 0N Œuvre, _11 Exemplaire\nExemplaire: exemplaire\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMTQiIGhlaWdodD0iNzgiIHZpZXdCb3g9IjAgMCAzMTQgNzgiPgo8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzE0IiBoZWlnaHQ9Ijc4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjQ4IiB5MT0iMzkiIHgyPSIxMzYiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNDUiIHkxPSIzOSIgeDI9IjEzNiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPGNpcmNsZSBjeD0iMTM2IiBjeT0iMzkiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTIzIiB5PSI0My44IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkRGPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iOTIiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4wLE48L3RleHQ+Cgk8dGV4dCB4PSIxNjIiIHk9IjU1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iMTYyIiB5MT0iNTciIHgyPSIxODAiIHkyPSI1NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgT0VVVlJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSI4NyIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNyIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij7FknV2cmU8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+xZN1dnJlPC90ZXh0PgoJPGxpbmUgeDE9IjE3IiB5MT0iNTkiIHgyPSI1OCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBFWEVNUExBSVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE4NSIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxODUiIHk9IjM5IiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE4NSIgeT0iOSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxODUiIHkxPSIzOSIgeDI9IjMwNSIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxOTQiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RXhlbXBsYWlyZTwvdGV4dD4KCTx0ZXh0IHg9IjE5MyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZXhlbXBsYWlyZTwvdGV4dD4KCTxsaW5lIHgxPSIxOTMiIHkxPSI1OSIgeDI9IjI2MiIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWRhc2hhcnJheT0iNCIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [169]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjM5NXB0IiBoZWlnaHQ9IjY5cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMzk0LjcwIDY4LjgyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDY0LjgyKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtNjQuODIgMzkwLjcsLTY0LjgyIDM5MC43LDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjY0LC00OC40MSAwLC00OC40MSAwLC0xMi40MSA2NCwtMTIuNDEgNjQsLTQ4LjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMyIiB5PSItMjUuNzMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+xZJ1dnJlPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTcyLjQ4LC01NS42MSAxNDIuMjUsLTMwLjQxIDE3Mi40OCwtNS4yMSAyMDIuNzEsLTMwLjQxIDE3Mi40OCwtNTUuNjEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTcyLjQ4LC02MC44MiAxMzYsLTMwLjQxIDE3Mi40OCwwIDIwOC45NSwtMzAuNDEgMTcyLjQ4LC02MC44MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIuNDgiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5ERjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik02NC4yMywtMzAuNDFDODUuNDUsLTMwLjQxIDExMy4zLC0zMC40MSAxMzUuNDQsLTMwLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjExNy4zMSIgeT0iLTM0LjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIzODIuNywtNDguNDEgMjg0Ljk1LC00OC40MSAyODQuOTUsLTEyLjQxIDM4Mi43LC0xMi40MSAzODIuNywtNDguNDEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMzg2LjcsLTUyLjQxIDI4MC45NSwtNTIuNDEgMjgwLjk1LC04LjQxIDM4Ni43LC04LjQxIDM4Ni43LC01Mi40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMzMuODMiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5FeGVtcGxhaXJlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTI4MC41NSwtMzEuNDFDMjU3LjIzLC0zMS40MSAyMzAuNDUsLTMxLjQxIDIwOS4zOSwtMzEuNDEiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMjgwLjU1LC0yOS40MUMyNTcuMjMsLTI5LjQxIDIzMC40NSwtMjkuNDEgMjA5LjM5LC0yOS40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjcuNTEiIHk9Ii0xNy4yOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'entité faible, à l'instar de la DF « renforçante », sont entourées d'un double trait.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le vocabulaire de Chen comporte encore un élément graphique, que Merise ne distingue pas spécialement. Nous avons vu que toute association non DF pouvait être décomposée de façon équivalente par l'insertion d'entités faibles :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [ ]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span>\nProduit: produit\nDF, _11 Ligne de commande, 0N Produit\nLigne de commande: _quantité\nDF, _11 Ligne de commande, 1N Commande\nCommande: commande\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>LIGNE DE COMMANDE est quelquefois qualifiée d'« entité associative », et Chen la figure logiquement par un losange (association) inscrit dans un rectangle (entité). Graphviz ne prend actuellement <a href=\"https://stackoverflow.com/questions/48046186/is-it-possible-to-have-nested-node-shapes-on-graphviz\">pas</a> en charge cette représentation. Nous l'approximons donc ainsi :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [170]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo,mindist=2,scale=0.6 --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjM2MHB0IiBoZWlnaHQ9IjY5cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMzYwLjM3IDY4LjgyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDY0LjgyKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtNjQuODIgMzU2LjM3LC02NC44MiAzNTYuMzcsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNjQsLTQ4LjQxIDAsLTQ4LjQxIDAsLTEyLjQxIDY0LC0xMi40MSA2NCwtNDguNDEiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzIiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj7FknV2cmU8L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxNTkuNDksLTU1LjYxIDEyOS4yNiwtMzAuNDEgMTU5LjQ5LC01LjIxIDE4OS43MiwtMzAuNDEgMTU5LjQ5LC01NS42MSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxNTkuNDksLTYwLjgyIDEyMy4wMSwtMzAuNDEgMTU5LjQ5LDAgMTk1Ljk2LC0zMC40MSAxNTkuNDksLTYwLjgyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE1OS40OSIgeT0iLTI1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkRGPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjEmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTY0LjE3LC0zMC40MUM4MS44NywtMzAuNDEgMTAzLjkyLC0zMC40MSAxMjIuMzYsLTMwLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwNC4yMyIgeT0iLTM0LjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIzNDguMzcsLTQ4LjQxIDI1MC42MiwtNDguNDEgMjUwLjYyLC0xMi40MSAzNDguMzcsLTEyLjQxIDM0OC4zNywtNDguNDEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMzUyLjM3LC01Mi40MSAyNDYuNjIsLTUyLjQxIDI0Ni42MiwtOC40MSAzNTIuMzcsLTguNDEgMzUyLjM3LC01Mi40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOTkuNSIgeT0iLTI1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkV4ZW1wbGFpcmU8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMjQ2LjE3LC0zMS40MUMyMjkuNjMsLTMxLjQxIDIxMS43NywtMzEuNDEgMTk2LjU5LC0zMS40MSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0yNDYuMTcsLTI5LjQxQzIyOS42MywtMjkuNDEgMjExLjc3LC0yOS40MSAxOTYuNTksLTI5LjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIxNC43MiIgeT0iLTE3LjI4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPC9nPgo8L3N2Zz4K\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Associations-n-aires-en-Look-Across\">Associations n-aires en <em>Look Across</em><a class=\"anchor-link\" href=\"#Associations-n-aires-en-Look-Across\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Triplet-NNN\">Triplet NNN<a class=\"anchor-link\" href=\"#Triplet-NNN\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Passons maintenant aux choses sérieuses. Jusqu'ici, la différence entre les deux notations était purement cosmétique. Qu'en est-il des associations n-aires, et que signifie <em>Look Across</em> quand <em>across</em> peut désigner plusieurs endroits ?</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [171]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t\nEmployé: employé\nAppliquer, 0N Employé, 1N Projet, 1N Compétence\nProjet: projet\n\nCompétence: compétence\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTYiIGhlaWdodD0iMTYyIiB2aWV3Qm94PSIwIDAgMzU2IDE2MiI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNTYiIGhlaWdodD0iMTYyIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBBUFBMSVFVRVIgLS0+CjxnPgoJPGxpbmUgeDE9IjU2IiB5MT0iMzkiIHgyPSIxODYiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIzMDgiIHkxPSIzOSIgeDI9IjE4NiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjE4NiIgeTE9IjEyMyIgeDI9IjE4NiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIyNiAxMCBhMTQgMTQgOTAgMCAxIDE0IDE0IFYzOCBoLTEwOCBWMjQgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI0MCAzOCB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE0NiBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjM4IEgxMDgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTMyIiB5PSIxMCIgd2lkdGg9IjEwOCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjEzMiIgeTE9IjM4IiB4Mj0iMjQwIiB5Mj0iMzgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNDAiIHk9IjMxLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXBwbGlxdWVyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTA4IiB5PSI1NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0PgoJPHRleHQgeD0iMjQ1IiB5PSI1NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTkxIiB5PSI4NSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBFTVBMT1lFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIzOSIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSI5NCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI5IiB5MT0iMzkiIHgyPSIxMDMiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTgiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+RW1wbG95w6k8L3RleHQ+Cgk8dGV4dCB4PSIxNyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZW1wbG95w6k8L3RleHQ+Cgk8bGluZSB4MT0iMTciIHkxPSI1OSIgeDI9IjcxIiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyNjkiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNjkiIHk9IjM5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjY5IiB5PSI5IiB3aWR0aD0iNzgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjY5IiB5MT0iMzkiIHgyPSIzNDciIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjc3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2pldDwvdGV4dD4KCTx0ZXh0IHg9IjI3NyIgeT0iNTYuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjI3NyIgeTE9IjU5IiB4Mj0iMzE2IiB5Mj0iNTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IENPTVBFVEVOQ0UgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTIzIiB5PSI5MyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMjMiIHk9IjEyMyIgd2lkdGg9IjEyNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMjMiIHk9IjkzIiB3aWR0aD0iMTI2IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEyMyIgeTE9IjEyMyIgeDI9IjI0OSIgeTI9IjEyMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTMyIiB5PSIxMTQuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Db21ww6l0ZW5jZTwvdGV4dD4KCTx0ZXh0IHg9IjEzMSIgeT0iMTQwLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmNvbXDDqXRlbmNlPC90ZXh0PgoJPGxpbmUgeDE9IjEzMSIgeTE9IjE0MyIgeDI9IjIwOCIgeTI9IjE0MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Appliquer</strong> (<u>employé</u>, <u>projet</u>, <u>compétence</u>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans ce cas (le plus usuel), la question ne se pose pas vraiment, ou du moins n'est pas tranchée de façon évidente :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [172]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t chen:layout=circo,mindist=1,scale=0.4 --defer\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI2MHB0IiBoZWlnaHQ9IjE5OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI2MC4yNiAxOTkuNDUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTk1LjQ1KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTk1LjQ1IDI1Ni4yNiwtMTk1LjQ1IDI1Ni4yNiw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI3OC4yNSwtMTEzLjcyIDAsLTExMy43MiAwLC03Ny43MiA3OC4yNSwtNzcuNzIgNzguMjUsLTExMy43MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzOS4xMiIgeT0iLTkxLjA1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkVtcGxvecOpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTgyLjIsLTEyMC45MiAxMTIuMTQsLTk1LjcyIDE4Mi4yLC03MC41MiAyNTIuMjYsLTk1LjcyIDE4Mi4yLC0xMjAuOTIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii05MS4wNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BcHBsaXF1ZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzguNiwtOTUuNzJDODguNjEsLTk1LjcyIDk5LjY3LC05NS43MiAxMTAuNzMsLTk1LjcyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjkyLjYxIiB5PSItOTkuNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwhLS0gMyAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4zPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjExLjk1LC0zNiAxNTIuNDUsLTM2IDE1Mi40NSwwIDIxMS45NSwwIDIxMS45NSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5Qcm9qZXQ8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTgzLjIsLTM2LjQyQzE4My4yLC00Ni40OCAxODMuMiwtNTkuMDggMTgzLjIsLTcwLjA5Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE4MS4yLC0zNi40MkMxODEuMiwtNDYuNDggMTgxLjIsLTU5LjA4IDE4MS4yLC03MC4wOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzMuNzUiIHk9Ii00Ny4yOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwhLS0gNCAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT40PC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjM0LjQ1LC0xOTEuNDUgMTI5Ljk1LC0xOTEuNDUgMTI5Ljk1LC0xNTUuNDUgMjM0LjQ1LC0xNTUuNDUgMjM0LjQ1LC0xOTEuNDUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii0xNjguNzciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q29tcMOpdGVuY2U8L3RleHQ+CjwvZz4KPCEtLSA0JiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NCYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTgxLjIsLTE1NS4wM0MxODEuMiwtMTQ0Ljk3IDE4MS4yLC0xMzIuMzcgMTgxLjIsLTEyMS4zNiIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODMuMiwtMTU1LjAzQzE4My4yLC0xNDQuOTcgMTgzLjIsLTEzMi4zNyAxODMuMiwtMTIxLjM2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5MC42NSIgeT0iLTEzNC44MSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Quels sont les autres cas ? Il ne s'agit pas de ceux où l'association n-aire est entourée d'une ou plusieurs cardinalités maximale 1, puisqu'on pourrait alors la décomposer en DF binaires (cf. argument <code>split</code>). En réalité, on touche ici aux limites de la notation <em>Look Here</em>, plus intuitive, mais moins puissante que <em>Look Across</em>, et que Merise n'a pu rattraper que dans sa version 2.</p>\n<p>Pour répondre progressivement à la question, procédons désormais dans l'ordre inverse, en présentant d'abord l'ERD, et ensuite seulement le MCD équivalent.</p>\n<p>Les exemples qui suivent (ainsi d'ailleurs que le précédent), sont adaptés des pages 28 sqq. et 96 sqq. de l'ouvrage de Toby J. Teorey, Sam S. Lightstone, Tom Nadeau, H.V. Jagadish, <em>Database Modeling and Design - Logical Design</em>, 5th Edition - February 10, 2011 (Elsevier).</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Triplet-1NN\">Triplet 1NN<a class=\"anchor-link\" href=\"#Triplet-1NN\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le premier ERD apportant véritablement quelque chose de nouveau a cette structure :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [173]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t chen:layout=circo,mindist=1,scale=0.45 --defer\nIngénieur: ingénieur\nGérer, /1N Responsable, 1N Ingénieur, 1N Projet\nProjet: projet\n\nResponsable: responsable\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI1NnB0IiBoZWlnaHQ9IjE5OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI1Ni4xNyAxOTguNjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTk0LjYpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC0xOTQuNiAyNTIuMTcsLTE5NC42IDI1Mi4xNyw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI4NSwtMTEzLjMgMCwtMTEzLjMgMCwtNzcuMyA4NSwtNzcuMyA4NSwtMTEzLjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDIuNSIgeT0iLTkwLjYyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkluZ8OpbmlldXI8L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxOTUuMTcsLTEyMC41IDE0OC40LC05NS4zIDE5NS4xNywtNzAuMSAyNDEuOTUsLTk1LjMgMTk1LjE3LC0xMjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxOTUuMTciIHk9Ii05MC42MiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5Hw6lyZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNODUuNDMsLTk0LjNDMTA0Ljc1LC05NC4zIDEyNy42MiwtOTQuMyAxNDcuNDcsLTk0LjMiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNODUuNDMsLTk2LjNDMTA0Ljc1LC05Ni4zIDEyNy42MiwtOTYuMyAxNDcuNDcsLTk2LjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTI5LjM0IiB5PSItOTkuMDgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIyNC45MiwtMzYgMTY1LjQyLC0zNiAxNjUuNDIsMCAyMjQuOTIsMCAyMjQuOTIsLTM2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5NS4xNyIgeT0iLTEzLjMyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlByb2pldDwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xOTYuMTcsLTM2LjMyQzE5Ni4xNywtNDYuMzIgMTk2LjE3LC01OC44NiAxOTYuMTcsLTY5LjgiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTk0LjE3LC0zNi4zMkMxOTQuMTcsLTQ2LjMyIDE5NC4xNywtNTguODYgMTk0LjE3LC02OS44Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4Ni43MiIgeT0iLTQ3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIyNDguMTcsLTE5MC42IDE0Mi4xNywtMTkwLjYgMTQyLjE3LC0xNTQuNiAyNDguMTcsLTE1NC42IDI0OC4xNywtMTkwLjYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTk1LjE3IiB5PSItMTY3LjkyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJlc3BvbnNhYmxlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE5NC4xNywtMTU0LjI4QzE5NC4xNywtMTQ0LjI4IDE5NC4xNywtMTMxLjc0IDE5NC4xNywtMTIwLjgiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTk2LjE3LC0xNTQuMjhDMTk2LjE3LC0xNDQuMjggMTk2LjE3LC0xMzEuNzQgMTk2LjE3LC0xMjAuOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMDMuNjMiIHk9Ii0xMzQuMjUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les auteurs explicitent ainsi ses règles de gestion :</p>\n<blockquote>\n<p><em>Chaque ingénieur travaillant sur un projet particulier a exactement un responsable, mais chaque responsable d'un projet peut gérer plusieurs ingénieurs, et chaque responsable d'un ingénieur peut gérer cet ingénieur sur plusieurs projets.</em></p>\n</blockquote>\n<p>Reprenons ces trois assertions, et faisons-les correspondre au trois cardinalités dans le sens anti-horaire à partir du 1 :</p>\n<ul>\n<li>1 : pour un couple (ingénieur, projet) donné, un seul responsable possible ;</li>\n<li>N : pour un couple (responsable, projet) donné, plusieurs ingénieurs possibles ;</li>\n<li>N : pour un couple (responsable, ingénieur) donné, plusieurs projets possibles.</li>\n</ul>\n<p>Avec Merise, les assertions seraient plutôt du type : « pour un x donné, <em>tant</em> de couples (y, z) possibles ». Il y a donc bien permutation, mais permutation des références au singleton et au $n-1$-uplet.</p>\n<p>C'est la réponse à notre question initiale, et nous verrons avec plaisir qu'elle reste valable quel que soit le triplet de cardinalités de l'association ternaire.</p>\n<p>Pour l'instant, résumons les règles de gestion par cette <strong>unique</strong> dépendance fonctionnelle :</p>\n<ul>\n<li>(Ingénieur, Projet) $\\implies$ Responsable.</li>\n</ul>\n<p>Pour exprimer cela en (ou en dépit de) <em>Look Here</em>, on doit recourir à un agrégat :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [174]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --mld --colors pond\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNzAiIGhlaWdodD0iMTkwIiB2aWV3Qm94PSIwIDAgMzcwIDE5MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNzAiIGhlaWdodD0iMTkwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBHRVJFUiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIyMDAiIGN5PSIxMDYiIHI9IjYiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjYTZlZmIzNTUiLz4KCTxsaW5lIHgxPSIyMDAiIHkxPSIxNDIiIHgyPSIyMDAiIHkyPSI0OCIgc3Ryb2tlPSIjNDc2MDYyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSI3MiIgeTE9IjQ4IiB4Mj0iMjAwIiB5Mj0iNDgiIHN0cm9rZT0iIzQ3NjA2MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzEzIiB5MT0iNDgiIHgyPSIyMDAiIHkyPSI0OCIgc3Ryb2tlPSIjNDc2MDYyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yMCAxMyBMMzUwIDEzIGE3IDcgMCAwIDEgNyA3IEwzNTcgNzYgYTcgNyAwIDAgMSAtNyA3IEwyMCA4MyBhNyA3IDAgMCAxIC03IC03IEwxMyAyMCBhNyA3IDAgMCAxIDcgLTciIGZpbGw9IiNhNmVmYjMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjMiLz4KCQk8cGF0aCBkPSJNMjAgMTMgTDM1MCAxMyBhNyA3IDAgMCAxIDcgNyBMMzU3IDc2IGE3IDcgMCAwIDEgLTcgNyBMMjAgODMgYTcgNyAwIDAgMSAtNyAtNyBMMTMgMjAgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yMjEgMTkgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNDcgaC03MCBWMzMgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiM5ZWJkNmQiIHN0cm9rZT0iIzllYmQ2ZCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTIzNSA0NyB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE3OSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjQ3IEg3MCIgZmlsbD0iI2MzZGJiYiIgc3Ryb2tlPSIjYzNkYmJiIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNjUiIHk9IjE5IiB3aWR0aD0iNzAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjOGVhMjQzIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNjUiIHkxPSI0NyIgeDI9IjIzNSIgeTI9IjQ3IiBzdHJva2U9IiM4ZWEyNDMiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTcyIiB5PSI0MC4zIiBmaWxsPSIjM2Q0ODRhIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkfDqXJlcjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjIxMCIgeT0iOTkiIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjEzNiIgeT0iNjkiIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI0NSIgeT0iNjkiIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgSU5HRU5JRVVSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE4IiB5PSIxOCIgd2lkdGg9IjEwOCIgaGVpZ2h0PSIzMCIgZmlsbD0iIzdlY2I5YSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxOCIgeT0iNDgiIHdpZHRoPSIxMDgiIGhlaWdodD0iMzAiIGZpbGw9IiNhNmVmYjMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjE4IiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE4IiB5MT0iNDgiIHgyPSIxMjYiIHkyPSI0OCIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjciIHk9IjM5LjMiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5nw6luaWV1cjwvdGV4dD4KCTx0ZXh0IHg9IjI2IiB5PSI2NS4xIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pbmfDqW5pZXVyPC90ZXh0PgoJPGxpbmUgeDE9IjI2IiB5MT0iNjgiIHgyPSI4NCIgeTI9IjY4IiBzdHJva2U9IiMxYjUzNDMiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9KRVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjc0IiB5PSIxOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjN2VjYjlhIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI3NCIgeT0iNDgiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzQiIHk9IjE4IiB3aWR0aD0iNzgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjc0IiB5MT0iNDgiIHgyPSIzNTIiIHkyPSI0OCIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjgyIiB5PSIzOS4zIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2pldDwvdGV4dD4KCTx0ZXh0IHg9IjI4MiIgeT0iNjUuMSIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjI4MiIgeTE9IjY4IiB4Mj0iMzIxIiB5Mj0iNjgiIHN0cm9rZT0iIzFiNTM0MyIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFJFU1BPTlNBQkxFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjEzMyIgeT0iMTEyIiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjN2VjYjlhIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEzMyIgeT0iMTQyIiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjEzMyIgeT0iMTEyIiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjEzMyIgeTE9IjE0MiIgeDI9IjI2NyIgeTI9IjE0MiIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTQxIiB5PSIxMzMuMyIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5SZXNwb25zYWJsZTwvdGV4dD4KCTx0ZXh0IHg9IjE0MSIgeT0iMTU5LjEiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnJlc3BvbnNhYmxlPC90ZXh0PgoJPGxpbmUgeDE9IjE0MSIgeTE9IjE2MiIgeDI9IjIxNiIgeTI9IjE2MiIgc3Ryb2tlPSIjMWI1MzQzIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Gérer</strong> (<u>ingénieur</u>, <u>projet</u>, responsable)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>… ou à une CIF à unicité complète (ici en notation allégée) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [175]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --mld -t create:cifs=light arrange:balanced --seed=3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNzAiIGhlaWdodD0iMTkwIiB2aWV3Qm94PSIwIDAgMzcwIDE5MCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNzAiIGhlaWdodD0iMTkwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IENJRl9DT05TVFJBSU5UXyMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjcyIiB5Mj0iMTQyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iMTMzIDE0MiAxMjEgMTQ4IDEyNSAxNDIgMTIxIDEzNiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iMjAwIiB5MT0iMTQyIiB4Mj0iNzIiIHkyPSIxNDIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSI3MiIgY3k9IjE0MiIgcj0iMTMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iNjMuNSIgeT0iMTQ2LjIiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiIHN0eWxlPSJwb2ludGVyLWV2ZW50czogbm9uZTsiPkNJRjwvdGV4dD4KCTwvZz4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBHRVJFUiAtLT4KPGc+Cgk8bGluZSB4MT0iMjAwIiB5MT0iMTQyIiB4Mj0iMjAwIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzIiIHkxPSI0OCIgeDI9IjIwMCIgeTI9IjQ4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjMxMyIgeTE9IjQ4IiB4Mj0iMjAwIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8cGF0aCBkPSJNMjIxIDE5IGExNCAxNCA5MCAwIDEgMTQgMTQgVjQ3IGgtNzAgVjMzIGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0yMzUgNDcgdjE2IGExNCAxNCA5MCAwIDEgLTE0IDE0IEgxNzkgYTE0IDE0IDkwIDAgMSAtMTQgLTE0IFY0NyBINzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHJlY3QgeD0iMTY1IiB5PSIxOSIgd2lkdGg9IjcwIiBoZWlnaHQ9IjU4IiBmaWxsPSJub25lIiByeD0iMTQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8bGluZSB4MT0iMTY1IiB5MT0iNDciIHgyPSIyMzUiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTx0ZXh0IHg9IjE3MiIgeT0iNDAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Hw6lyZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyMTAiIHk9Ijk5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIxMzYiIHk9IjY5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyNDUiIHk9IjY5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElOR0VOSUVVUiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxOCIgeT0iMTgiIHdpZHRoPSIxMDgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTgiIHk9IjQ4IiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE4IiB5PSIxOCIgd2lkdGg9IjEwOCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxOCIgeTE9IjQ4IiB4Mj0iMTI2IiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI3IiB5PSIzOS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkluZ8OpbmlldXI8L3RleHQ+Cgk8dGV4dCB4PSIyNiIgeT0iNjUuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+aW5nw6luaWV1cjwvdGV4dD4KCTxsaW5lIHgxPSIyNiIgeTE9IjY4IiB4Mj0iODQiIHkyPSI2OCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3NCIgeT0iMTgiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyNzQiIHk9IjQ4IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjc0IiB5PSIxOCIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3NCIgeTE9IjQ4IiB4Mj0iMzUyIiB5Mj0iNDgiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI4MiIgeT0iMzkuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9qZXQ8L3RleHQ+Cgk8dGV4dCB4PSIyODIiIHk9IjY1LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByb2pldDwvdGV4dD4KCTxsaW5lIHgxPSIyODIiIHkxPSI2OCIgeDI9IjMyMSIgeTI9IjY4IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBSRVNQT05TQUJMRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxMzMiIHk9IjExMiIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzMiIHk9IjE0MiIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxMzMiIHk9IjExMiIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxMzMiIHkxPSIxNDIiIHgyPSIyNjciIHkyPSIxNDIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE0MSIgeT0iMTMzLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UmVzcG9uc2FibGU8L3RleHQ+Cgk8dGV4dCB4PSIxNDEiIHk9IjE1OS4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yZXNwb25zYWJsZTwvdGV4dD4KCTxsaW5lIHgxPSIxNDEiIHkxPSIxNjIiIHgyPSIyMTYiIHkyPSIxNjIiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KPC9zdmc+\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Gérer</strong> (<u>ingénieur</u>, <u>projet</u>, responsable)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>... Ou encore à une entité faible :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [176]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --mld -t explode:weak,arity=2 arrange:balanced --seed=14\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMjgiIGhlaWdodD0iMjI4IiB2aWV3Qm94PSIwIDAgMzI4IDIyOCI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzMjgiIGhlaWdodD0iMjI4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBERjAgLS0+CjxnPgoJPGxpbmUgeDE9IjE5MiIgeTE9IjExNCIgeDI9IjE5MiIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjI4MCIgeTE9IjM5IiB4Mj0iMTkyIiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIxOTIiIGN5PSIzOSIgcj0iMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIxNzkiIHk9IjQzLjgiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+REY8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIxOTciIHk9Ijg1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iMTk3IiB5MT0iODciIHgyPSIyMTUiIHkyPSI4NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIxNyIgeT0iNTUiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBBc3NvY2lhdGlvbiBERjEgLS0+CjxnPgoJPGxpbmUgeDE9IjE5MiIgeTE9IjExNCIgeDI9Ijc2IiB5Mj0iMTE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9Ijc2IiB5MT0iMzkiIHgyPSI3NiIgeTI9IjExNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9Ijc2IiBjeT0iMTE0IiByPSIyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjYzIiB5PSIxMTguOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjEzMyIgeT0iMTMwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8bGluZSB4MT0iMTMzIiB5MT0iMTMyIiB4Mj0iMTUxIiB5Mj0iMTMyIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iODEiIHk9Ijg1IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gREYyIC0tPgo8Zz4KCTxsaW5lIHgxPSIxOTIiIHkxPSIxMTQiIHgyPSIxOTIiIHkyPSIxODkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNzYiIHkxPSIxODkiIHgyPSIxOTIiIHkyPSIxODkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIxOTIiIGN5PSIxODkiIHI9IjIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMTc5IiB5PSIxOTMuOCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5ERjwvdGV4dD4KCTwvZz4KCTx0ZXh0IHg9IjE5NyIgeT0iMTUxIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLDE8L3RleHQ+Cgk8dGV4dCB4PSIxNDgiIHk9IjIwNSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkdFTklFVVIgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjIiIHk9IjkiIHdpZHRoPSIxMDgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjIiIHk9IjM5IiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIyIiB5PSI5IiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIyIiB5MT0iMzkiIHgyPSIxMzAiIHkyPSIzOSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzEiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+SW5nw6luaWV1cjwvdGV4dD4KCTx0ZXh0IHg9IjMwIiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5pbmfDqW5pZXVyPC90ZXh0PgoJPGxpbmUgeDE9IjMwIiB5MT0iNTkiIHgyPSI4OCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9KRVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjQxIiB5PSI5IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjQxIiB5PSIzOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI0MSIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI0MSIgeTE9IjM5IiB4Mj0iMzE5IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjI0OSIgeT0iMzAuMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9qZXQ8L3RleHQ+Cgk8dGV4dCB4PSIyNDkiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByb2pldDwvdGV4dD4KCTxsaW5lIHgxPSIyNDkiIHkxPSI1OSIgeDI9IjI4OCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBHRVJFUiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIxNTYiIHk9IjkzIiB3aWR0aD0iNzIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU2IiB5PSIxMjMiIHdpZHRoPSI3MiIgaGVpZ2h0PSIxMiIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjkzIiB3aWR0aD0iNzIiIGhlaWdodD0iNDIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTU2IiB5MT0iMTIzIiB4Mj0iMjI4IiB5Mj0iMTIzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNjQiIHk9IjExNC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkfDqXJlcjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUkVTUE9OU0FCTEUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iOSIgeT0iMTU5IiB3aWR0aD0iMTM0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjkiIHk9IjE4OSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI5IiB5PSIxNTkiIHdpZHRoPSIxMzQiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iOSIgeTE9IjE4OSIgeDI9IjE0MyIgeTI9IjE4OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTciIHk9IjE4MC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlJlc3BvbnNhYmxlPC90ZXh0PgoJPHRleHQgeD0iMTciIHk9IjIwNi4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5yZXNwb25zYWJsZTwvdGV4dD4KCTxsaW5lIHgxPSIxNyIgeTE9IjIwOSIgeDI9IjkyIiB5Mj0iMjA5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Gérer</strong> (<u>ingénieur</u>, <u>projet</u>, responsable)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les schémas relationnels produits permettent de se convaincre que ces différentes variantes respectent bien la dépendance fonctionnelle désirée : (Ingénieur, Projet) $\\implies$ Responsable.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Triplet-11N\">Triplet 11N<a class=\"anchor-link\" href=\"#Triplet-11N\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Passons à la deuxième combinaison intéressante :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [177]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t chen:layout=circo,mindist=1,scale=0.45 --defer\nProjet: projet\nAffecter, /1N Site, /1N Projet, 0N Employé\nSite: site\n\nEmployé: employé\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjIzN3B0IiBoZWlnaHQ9IjE5N3B0Igogdmlld0JveD0iMC4wMCAwLjAwIDIzNi43NCAxOTcuMTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTkzLjE0KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTkzLjE0IDIzMi43NCwtMTkzLjE0IDIzMi43NCw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI1OS41LC0xMTIuNTcgMCwtMTEyLjU3IDAsLTc2LjU3IDU5LjUsLTc2LjU3IDU5LjUsLTExMi41NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOS43NSIgeT0iLTg5LjkiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+UHJvamV0PC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTY5LjcxLC0xMTkuNzcgMTEwLjY4LC05NC41NyAxNjkuNzEsLTY5LjM3IDIyOC43NCwtOTQuNTcgMTY5LjcxLC0xMTkuNzciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTY5LjcxIiB5PSItODkuOSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BZmZlY3RlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01OS43OCwtOTMuNTdDNzQuMzEsLTkzLjU3IDkyLjMxLC05My41NyAxMDkuNTEsLTkzLjU3Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTU5Ljc4LC05NS41N0M3NC4zMSwtOTUuNTcgOTIuMzEsLTk1LjU3IDEwOS41MSwtOTUuNTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTEuMzgiIHk9Ii05OC4zNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwhLS0gMyAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4zPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTk2LjcxLC0zNiAxNDIuNzEsLTM2IDE0Mi43MSwwIDE5Ni43MSwwIDE5Ni43MSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTY5LjcxIiB5PSItMTMuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+U2l0ZTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNzAuNzEsLTM2LjE1QzE3MC43MSwtNDUuOTYgMTcwLjcxLC01OC4yNSAxNzAuNzEsLTY5LjAyIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE2OC43MSwtMzYuMTVDMTY4LjcxLC00NS45NiAxNjguNzEsLTU4LjI1IDE2OC43MSwtNjkuMDIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYxLjI2IiB5PSItNDYuMjIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIwOC44NCwtMTg5LjE0IDEzMC41OSwtMTg5LjE0IDEzMC41OSwtMTUzLjE0IDIwOC44NCwtMTUzLjE0IDIwOC44NCwtMTg5LjE0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2OS43MSIgeT0iLTE2Ni40NyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5FbXBsb3nDqTwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNjkuNzEsLTE1Mi45OUMxNjkuNzEsLTE0My4xOCAxNjkuNzEsLTEzMC44OSAxNjkuNzEsLTEyMC4xMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzguMTciIHk9Ii0xMzMuNTciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Règles de gestion :</p>\n<blockquote>\n<p><em>Chaque employé affecté à un projet travaille sur un seul site pour ce projet, mais peut se trouver sur différents sites pour différents projets. Sur un site donné, un salarié ne travaille que sur un seul projet. Sur un site donné, il peut y avoir plusieurs employés affectés à un projet donné.</em></p>\n</blockquote>\n<p>Autrement dit (en partant du bas et dans le sens anti-horaire) :</p>\n<p>1 : pour un couple (projet, employé) donné, un seul site possible ;\n1 : pour un couple (employé, site) donné, un seul projet possible ;\nN : pour un couple (projet, site) donné, plusieurs employés possibles.</p>\n<p>En résumé, <strong>deux</strong> dépendances fonctionnelles :</p>\n<ul>\n<li>(Projet, Employé) $\\implies$ Site.</li>\n<li>(Employé, Site) $\\implies$ Projet.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Voici le MCD correspondant, successivement avec des agrégats et des CIFS (plus de variante possible avec entité faible) :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [178]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --select all -t mld:c --colors pond\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODIiIGhlaWdodD0iMjE3IiB2aWV3Qm94PSIwIDAgMzgyIDIxNyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODIiIGhlaWdodD0iMjE3IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBBRkZFQ1RFUiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIyOTUiIGN5PSI1NyIgcj0iNiIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNhNmVmYjM1NSIvPgoJPGxpbmUgeDE9IjMyOCIgeTE9IjU3IiB4Mj0iMjAzIiB5Mj0iNTciIHN0cm9rZT0iIzQ3NjA2MiIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Y2lyY2xlIGN4PSIxMTEiIGN5PSI1NyIgcj0iNiIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNhNmVmYjM1NSIvPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTciIHgyPSIyMDMiIHkyPSI1NyIgc3Ryb2tlPSIjNDc2MDYyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyMDMiIHkxPSIxNjAiIHgyPSIyMDMiIHkyPSI1NyIgc3Ryb2tlPSIjNDc2MDYyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxwYXRoIGQ9Ik0yNyAyMCBMMjUzIDIwIGE3IDcgMCAwIDEgNyA3IEwyNjAgMTkxIGE3IDcgMCAwIDEgLTcgNyBMMTU0IDE5OCBhNyA3IDAgMCAxIC03IC03IEwxNDcgMTAyIGE3IDcgMCAwIDAgLTcgLTcgTDI3IDk1IGE3IDcgMCAwIDEgLTcgLTcgTDIwIDI3IGE3IDcgMCAwIDEgNyAtNyIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuMTUiLz4KCQk8cGF0aCBkPSJNMjcgMjAgTDI1MyAyMCBhNyA3IDAgMCAxIDcgNyBMMjYwIDE5MSBhNyA3IDAgMCAxIC03IDcgTDE1NCAxOTggYTcgNyAwIDAgMSAtNyAtNyBMMTQ3IDEwMiBhNyA3IDAgMCAwIC03IC03IEwyNyA5NSBhNyA3IDAgMCAxIC03IC03IEwyMCAyNyBhNyA3IDAgMCAxIDcgLTciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CgkJPHBhdGggZD0iTTE0NiAxMiBMMzYzIDEyIGE3IDcgMCAwIDEgNyA3IEwzNzAgOTUgYTcgNyAwIDAgMSAtNyA3IEwyNzQgMTAyIGE3IDcgMCAwIDAgLTcgNyBMMjY3IDE5OCBhNyA3IDAgMCAxIC03IDcgTDE0NiAyMDUgYTcgNyAwIDAgMSAtNyAtNyBMMTM5IDE5IGE3IDcgMCAwIDEgNyAtNyIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuMTUiLz4KCQk8cGF0aCBkPSJNMTQ2IDEyIEwzNjMgMTIgYTcgNyAwIDAgMSA3IDcgTDM3MCA5NSBhNyA3IDAgMCAxIC03IDcgTDI3NCAxMDIgYTcgNyAwIDAgMCAtNyA3IEwyNjcgMTk4IGE3IDcgMCAwIDEgLTcgNyBMMTQ2IDIwNSBhNyA3IDAgMCAxIC03IC03IEwxMzkgMTkgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yMzggMjggYTE0IDE0IDkwIDAgMSAxNCAxNCBWNTYgaC05OCBWNDIgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiM5ZWJkNmQiIHN0cm9rZT0iIzllYmQ2ZCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTI1MiA1NiB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDE2OCBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjU2IEg5OCIgZmlsbD0iI2MzZGJiYiIgc3Ryb2tlPSIjYzNkYmJiIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIxNTQiIHk9IjI4IiB3aWR0aD0iOTgiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjOGVhMjQzIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIxNTQiIHkxPSI1NiIgeDI9IjI1MiIgeTI9IjU2IiBzdHJva2U9IiM4ZWEyNDMiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMTYyIiB5PSI0OS4zIiBmaWxsPSIjM2Q0ODRhIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkFmZmVjdGVyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMjY3IiB5PSI4MyIgZmlsbD0iIzJmNDk0ZSIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMTIwIiB5PSI4MyIgZmlsbD0iIzJmNDk0ZSIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjE4IiB5PSIxMTIiIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjAsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgUFJPSkVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjI3IiB5PSIyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjN2VjYjlhIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI3IiB5PSI1NyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjI3IiB5PSIyNyIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjI3IiB5MT0iNTciIHgyPSIxMDUiIHkyPSI1NyIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzUiIHk9IjQ4LjMiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvamV0PC90ZXh0PgoJPHRleHQgeD0iMzUiIHk9Ijc0LjEiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByb2pldDwvdGV4dD4KCTxsaW5lIHgxPSIzNSIgeTE9Ijc3IiB4Mj0iNzQiIHkyPSI3NyIgc3Ryb2tlPSIjMWI1MzQzIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgU0lURSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzMDEiIHk9IjI3IiB3aWR0aD0iNTQiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzAxIiB5PSI1NyIgd2lkdGg9IjU0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjMwMSIgeT0iMjciIHdpZHRoPSI1NCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzMDEiIHkxPSI1NyIgeDI9IjM1NSIgeTI9IjU3IiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzMDkiIHk9IjQ4LjMiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+U2l0ZTwvdGV4dD4KCTx0ZXh0IHg9IjMwOSIgeT0iNzQuMSIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2l0ZTwvdGV4dD4KCTxsaW5lIHgxPSIzMDkiIHkxPSI3NyIgeDI9IjMzMiIgeTI9Ijc3IiBzdHJva2U9IiMxYjUzNDMiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBFTVBMT1lFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE1NiIgeT0iMTMwIiB3aWR0aD0iOTQiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTU2IiB5PSIxNjAiIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjEzMCIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE1NiIgeTE9IjE2MCIgeDI9IjI1MCIgeTI9IjE2MCIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMTY1IiB5PSIxNTEuMyIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5FbXBsb3nDqTwvdGV4dD4KCTx0ZXh0IHg9IjE2NCIgeT0iMTc3LjEiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmVtcGxvecOpPC90ZXh0PgoJPGxpbmUgeDE9IjE2NCIgeTE9IjE4MCIgeDI9IjIxOCIgeTI9IjE4MCIgc3Ryb2tlPSIjMWI1MzQzIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Affecter</strong> (<u>projet</u>, <u>employé</u> <sup>u1</sup>, site! <sup>u1</sup>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [179]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced --seed=3\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzODIiIGhlaWdodD0iMjE3IiB2aWV3Qm94PSIwIDAgMzgyIDIxNyI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzODIiIGhlaWdodD0iMjE3IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IENJRl9DT05TVFJBSU5UXyMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyMDMiIHkxPSI1NyIgeDI9IjY2IiB5Mj0iMTYwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iNjYgODcgNzIgOTkgNjYgOTUgNjAgOTkiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgoJPGxpbmUgeDE9IjY2IiB5MT0iNTciIHgyPSI2NiIgeTI9IjE2MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjY2IiBjeT0iMTYwIiByPSIxMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI1Ny41IiB5PSIxNjQuMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgc3R5bGU9InBvaW50ZXItZXZlbnRzOiBub25lOyI+Q0lGPC90ZXh0PgoJPC9nPgo8L2c+Cgo8IS0tIENvbnN0cmFpbnQgQ0lGX0NPTlNUUkFJTlRfIzIgLS0+CjxnPgoJPGxpbmUgeDE9IjIwMyIgeTE9IjU3IiB4Mj0iMzI4IiB5Mj0iMTYwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iMzI4IDg3IDMzNCA5OSAzMjggOTUgMzIyIDk5IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIzMjgiIHkxPSI1NyIgeDI9IjMyOCIgeTI9IjE2MCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjMyOCIgY3k9IjE2MCIgcj0iMTMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjRkZGRkZGIi8+CgkJPHRleHQgeD0iMzE5LjUiIHk9IjE2NC4yIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIiBzdHlsZT0icG9pbnRlci1ldmVudHM6IG5vbmU7Ij5DSUY8L3RleHQ+Cgk8L2c+CjwvZz4KCjwhLS0gQXNzb2NpYXRpb24gQUZGRUNURVIgLS0+CjxnPgoJPGxpbmUgeDE9IjMyOCIgeTE9IjU3IiB4Mj0iMjAzIiB5Mj0iNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iNjYiIHkxPSI1NyIgeDI9IjIwMyIgeTI9IjU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGxpbmUgeDE9IjIwMyIgeTE9IjE2MCIgeDI9IjIwMyIgeTI9IjU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIzOCAyOCBhMTQgMTQgOTAgMCAxIDE0IDE0IFY1NiBoLTk4IFY0MiBhMTQgMTQgOTAgMCAxIDE0IC0xNCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cGF0aCBkPSJNMjUyIDU2IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMTY4IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWNTYgSDk4IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxyZWN0IHg9IjE1NCIgeT0iMjgiIHdpZHRoPSI5OCIgaGVpZ2h0PSI1OCIgZmlsbD0ibm9uZSIgcng9IjE0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPGxpbmUgeDE9IjE1NCIgeTE9IjU2IiB4Mj0iMjUyIiB5Mj0iNTYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIxNjIiIHk9IjQ5LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QWZmZWN0ZXI8L3RleHQ+Cgk8L2c+Cgk8dGV4dCB4PSIyNjciIHk9IjgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIxMjAiIHk9IjgzIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIyMTgiIHk9IjExMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MCxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9KRVQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMjciIHk9IjI3IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjciIHk9IjU3IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjciIHk9IjI3IiB3aWR0aD0iNzgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMjciIHkxPSI1NyIgeDI9IjEwNSIgeTI9IjU3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNSIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9qZXQ8L3RleHQ+Cgk8dGV4dCB4PSIzNSIgeT0iNzQuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cHJvamV0PC90ZXh0PgoJPGxpbmUgeDE9IjM1IiB5MT0iNzciIHgyPSI3NCIgeTI9Ijc3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cgo8IS0tIEVudGl0eSBTSVRFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjMwMSIgeT0iMjciIHdpZHRoPSI1NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzMDEiIHk9IjU3IiB3aWR0aD0iNTQiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzAxIiB5PSIyNyIgd2lkdGg9IjU0IiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjMwMSIgeTE9IjU3IiB4Mj0iMzU1IiB5Mj0iNTciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjMwOSIgeT0iNDguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5TaXRlPC90ZXh0PgoJPHRleHQgeD0iMzA5IiB5PSI3NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5zaXRlPC90ZXh0PgoJPGxpbmUgeDE9IjMwOSIgeTE9Ijc3IiB4Mj0iMzMyIiB5Mj0iNzciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IEVNUExPWUUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTU2IiB5PSIxMzAiIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNTYiIHk9IjE2MCIgd2lkdGg9Ijk0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE1NiIgeT0iMTMwIiB3aWR0aD0iOTQiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMTU2IiB5MT0iMTYwIiB4Mj0iMjUwIiB5Mj0iMTYwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNjUiIHk9IjE1MS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkVtcGxvecOpPC90ZXh0PgoJPHRleHQgeD0iMTY0IiB5PSIxNzcuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZW1wbG95w6k8L3RleHQ+Cgk8bGluZSB4MT0iMTY0IiB5MT0iMTgwIiB4Mj0iMjE4IiB5Mj0iMTgwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Affecter</strong> (<u>projet</u>, <u>employé</u> <sup>u1</sup>, site! <sup>u1</sup>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>On voit apparaître dans le schéma relationnel un « u1 » en exposant qui signifie : contrainte d'unicité n°1. Il y a en effet deux clés candidates : (projet, employé) et (employé, site). Seule l'une des deux est devenue clé primaire, mais cela ne veut pas dire qu'on a perdu la contrainte de dépendance fonctionnelle induite par l'autre. En SQL :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [180]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t sql\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Affecter</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">projet</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">employe</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">projet</span><span class=\"w\">  </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">employe</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">site</span><span class=\"w\">    </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">employe</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">site</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Triplet-111\">Triplet 111<a class=\"anchor-link\" href=\"#Triplet-111\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La dernière combinaison obéit à la même logique :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [181]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t chen:layout=circo,mindist=1,scale=0.45 --defer\nTechnicien: technicien\nUtiliser, /1N Technicien, /1N Carnet, /1N Projet\nProjet: projet\n\nCarnet: carnet\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_erd_chen.svg\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" max-width=\"100%\" src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI1MXB0IiBoZWlnaHQ9IjE4OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI1MS4zOSAxODkuNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTg1LjQxKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTg1LjQxIDI0Ny4zOSwtMTg1LjQxIDI0Ny4zOSw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI5MS43NSwtMTA4LjcxIDAsLTEwOC43MSAwLC03Mi43MSA5MS43NSwtNzIuNzEgOTEuNzUsLTEwOC43MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NS44OCIgeT0iLTg2LjAzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlRlY2huaWNpZW48L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxODYuMTksLTExNS45MSAxMjksLTkwLjcxIDE4Ni4xOSwtNjUuNTEgMjQzLjM5LC05MC43MSAxODYuMTksLTExNS45MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODYuMTkiIHk9Ii04Ni4wMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5VdGlsaXNlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik05Mi4yMSwtODkuNzFDMTAzLjcsLTg5LjcxIDExNi4xNywtODkuNzEgMTI4LjE1LC04OS43MSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik05Mi4yMSwtOTEuNzFDMTAzLjcsLTkxLjcxIDExNi4xNywtOTEuNzEgMTI4LjE1LC05MS43MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTAuMDIiIHk9Ii05NC40OCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwhLS0gNCAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT40PC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjE1Ljk0LC0zNiAxNTYuNDQsLTM2IDE1Ni40NCwwIDIxNS45NCwwIDIxNS45NCwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTg2LjE5IiB5PSItMTMuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+UHJvamV0PC90ZXh0Pgo8L2c+CjwhLS0gNCYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjQmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE4Ny4xOSwtMzYuMzVDMTg3LjE5LC00NS4xIDE4Ny4xOSwtNTUuNzEgMTg3LjE5LC02NS4yMyIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODUuMTksLTM2LjM1QzE4NS4xOSwtNDUuMSAxODUuMTksLTU1LjcxIDE4NS4xOSwtNjUuMjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTc3Ljc0IiB5PSItNDIuNDIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIxOC41NywtMTgxLjQxIDE1My44MiwtMTgxLjQxIDE1My44MiwtMTQ1LjQxIDIxOC41NywtMTQ1LjQxIDIxOC41NywtMTgxLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4Ni4xOSIgeT0iLTE1OC43NCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DYXJuZXQ8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTg1LjE5LC0xNDUuMDZDMTg1LjE5LC0xMzYuMzEgMTg1LjE5LC0xMjUuNyAxODUuMTksLTExNi4xOSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODcuMTksLTE0NS4wNkMxODcuMTksLTEzNi4zMSAxODcuMTksLTEyNS43IDE4Ny4xOSwtMTE2LjE5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5NC42NSIgeT0iLTEyOS42NCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Règles de gestion :</p>\n<blockquote>\n<p><em>Un technicien utilise exactement un carnet pour chaque projet. Chaque carnet appartient à un technicien pour chaque projet. Notez qu'un technicien peut toujours travailler sur plusieurs projets et gérer différents carnets pour différents projets.</em></p>\n</blockquote>\n<p>Autrement dit (en partant du haut et dans le sens horaire) :</p>\n<ul>\n<li>1 : pour un couple (technicien, projet) donné, un seul carnet possible ;</li>\n<li>1 : pour un couple (carnet, projet) donné, un seul technicien possible ;</li>\n<li>1 : pour un couple (carnet, technicien) donné, un seul projet possible.</li>\n</ul>\n<p>En résumé, <strong>trois</strong> dépendances fonctionnelles :</p>\n<ul>\n<li>(Technicien, Projet) $\\implies$ Carnet.</li>\n<li>(Carnet, Technicien) $\\implies$ Projet.</li>\n<li>(Carnet, Projet) $\\implies$ Technicien.</li>\n</ul>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [182]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --select all -t mld:c --colors pond\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NzQiIGhlaWdodD0iMjQ1IiB2aWV3Qm94PSIwIDAgNDc0IDI0NSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NzQiIGhlaWdodD0iMjQ1IiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBBc3NvY2lhdGlvbiBVVElMSVNFUiAtLT4KPGc+Cgk8Y2lyY2xlIGN4PSIxNTgiIGN5PSI2NiIgcj0iNiIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNhNmVmYjM1NSIvPgoJPGxpbmUgeDE9Ijk0IiB5MT0iNjYiIHgyPSIyNTYiIHkyPSI2NiIgc3Ryb2tlPSIjNDc2MDYyIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxjaXJjbGUgY3g9IjI1NiIgY3k9IjE0MyIgcj0iNiIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNhNmVmYjM1NSIvPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjE3OSIgeDI9IjI1NiIgeTI9IjY2IiBzdHJva2U9IiM0NzYwNjIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGNpcmNsZSBjeD0iMzU0IiBjeT0iNjYiIHI9IjYiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSIjYTZlZmIzNTUiLz4KCTxsaW5lIHgxPSIzOTkiIHkxPSI2NiIgeDI9IjI1NiIgeTI9IjY2IiBzdHJva2U9IiM0NzYwNjIiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTIwOCAyNiBMNDQxIDI2IGE3IDcgMCAwIDEgNyA3IEw0NDggOTkgYTcgNyAwIDAgMSAtNyA3IEwzMTggMTA2IGE3IDcgMCAwIDAgLTcgNyBMMzExIDIxMiBhNyA3IDAgMCAxIC03IDcgTDIwOCAyMTkgYTcgNyAwIDAgMSAtNyAtNyBMMjAxIDMzIGE3IDcgMCAwIDEgNyAtNyIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjAuMSIvPgoJCTxwYXRoIGQ9Ik0yMDggMjYgTDQ0MSAyNiBhNyA3IDAgMCAxIDcgNyBMNDQ4IDk5IGE3IDcgMCAwIDEgLTcgNyBMMzE4IDEwNiBhNyA3IDAgMCAwIC03IDcgTDMxMSAyMTIgYTcgNyAwIDAgMSAtNyA3IEwyMDggMjE5IGE3IDcgMCAwIDEgLTcgLTcgTDIwMSAzMyBhNyA3IDAgMCAxIDcgLTciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjAsNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CgkJPHBhdGggZD0iTTIzIDE2IEw0NTEgMTYgYTcgNyAwIDAgMSA3IDcgTDQ1OCAxMDkgYTcgNyAwIDAgMSAtNyA3IEwyMyAxMTYgYTcgNyAwIDAgMSAtNyAtNyBMMTYgMjMgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMC4xIi8+CgkJPHBhdGggZD0iTTIzIDE2IEw0NTEgMTYgYTcgNyAwIDAgMSA3IDcgTDQ1OCAxMDkgYTcgNyAwIDAgMSAtNyA3IEwyMyAxMTYgYTcgNyAwIDAgMSAtNyAtNyBMMTYgMjMgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0xMyA2IEwzMjQgNiBhNyA3IDAgMCAxIDcgNyBMMzMxIDIzMiBhNyA3IDAgMCAxIC03IDcgTDE4OCAyMzkgYTcgNyAwIDAgMSAtNyAtNyBMMTgxIDEzMyBhNyA3IDAgMCAwIC03IC03IEwxMyAxMjYgYTcgNyAwIDAgMSAtNyAtNyBMNiAxMyBhNyA3IDAgMCAxIDcgLTciIGZpbGw9IiNhNmVmYjMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIwLjEiLz4KCQk8cGF0aCBkPSJNMTMgNiBMMzI0IDYgYTcgNyAwIDAgMSA3IDcgTDMzMSAyMzIgYTcgNyAwIDAgMSAtNyA3IEwxODggMjM5IGE3IDcgMCAwIDEgLTcgLTcgTDE4MSAxMzMgYTcgNyAwIDAgMCAtNyAtNyBMMTMgMTI2IGE3IDcgMCAwIDEgLTcgLTcgTDYgMTMgYTcgNyAwIDAgMSA3IC03IiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSIwLDQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJCTxwYXRoIGQ9Ik0yODcgMzcgYTE0IDE0IDkwIDAgMSAxNCAxNCBWNjUgaC05MCBWNTEgYTE0IDE0IDkwIDAgMSAxNCAtMTQiIGZpbGw9IiM5ZWJkNmQiIHN0cm9rZT0iIzllYmQ2ZCIgc3Ryb2tlLXdpZHRoPSIwIi8+CgkJPHBhdGggZD0iTTMwMSA2NSB2MTYgYTE0IDE0IDkwIDAgMSAtMTQgMTQgSDIyNSBhMTQgMTQgOTAgMCAxIC0xNCAtMTQgVjY1IEg5MCIgZmlsbD0iI2MzZGJiYiIgc3Ryb2tlPSIjYzNkYmJiIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyMTEiIHk9IjM3IiB3aWR0aD0iOTAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjOGVhMjQzIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyMTEiIHkxPSI2NSIgeDI9IjMwMSIgeTI9IjY1IiBzdHJva2U9IiM4ZWEyNDMiIHN0cm9rZS13aWR0aD0iMS41Ii8+CgkJPHRleHQgeD0iMjE4IiB5PSI1OC4zIiBmaWxsPSIjM2Q0ODRhIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlV0aWxpc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTcyIiB5PSI5NyIgZmlsbD0iIzJmNDk0ZSIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0PgoJPHRleHQgeD0iMjc2IiB5PSIxMjYiIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjMyMSIgeT0iOTciIGZpbGw9IiMyZjQ5NGUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgVEVDSE5JQ0lFTiAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzNiIgeT0iMzYiIHdpZHRoPSIxMTYiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzYiIHk9IjY2IiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM2IiB5PSIzNiIgd2lkdGg9IjExNiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzNiIgeTE9IjY2IiB4Mj0iMTUyIiB5Mj0iNjYiIHN0cm9rZT0iIzM4NzI1MiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ0IiB5PSI1Ny4zIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRlY2huaWNpZW48L3RleHQ+Cgk8dGV4dCB4PSI0NCIgeT0iODMuMSIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+dGVjaG5pY2llbjwvdGV4dD4KCTxsaW5lIHgxPSI0NCIgeTE9Ijg2IiB4Mj0iMTA4IiB5Mj0iODYiIHN0cm9rZT0iIzFiNTM0MyIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzNjAiIHk9IjM2IiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzYwIiB5PSI2NiIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYTZlZmIzIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM2MCIgeT0iMzYiIHdpZHRoPSI3OCIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzNjAiIHkxPSI2NiIgeDI9IjQzOCIgeTI9IjY2IiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNjgiIHk9IjU3LjMiIGZpbGw9IiMxYjUzNDMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UHJvamV0PC90ZXh0PgoJPHRleHQgeD0iMzY4IiB5PSI4My4xIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wcm9qZXQ8L3RleHQ+Cgk8bGluZSB4MT0iMzY4IiB5MT0iODYiIHgyPSI0MDciIHkyPSI4NiIgc3Ryb2tlPSIjMWI1MzQzIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgoKPCEtLSBFbnRpdHkgQ0FSTkVUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIxNSIgeT0iMTQ5IiB3aWR0aD0iODIiIGhlaWdodD0iMzAiIGZpbGw9IiM3ZWNiOWEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjE1IiB5PSIxNzkiIHdpZHRoPSI4MiIgaGVpZ2h0PSIzMCIgZmlsbD0iI2E2ZWZiMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMTUiIHk9IjE0OSIgd2lkdGg9IjgyIiBoZWlnaHQ9IjYwIiBmaWxsPSJub25lIiBzdHJva2U9IiMzODcyNTIiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjIxNSIgeTE9IjE3OSIgeDI9IjI5NyIgeTI9IjE3OSIgc3Ryb2tlPSIjMzg3MjUyIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMjIzIiB5PSIxNzAuMyIgZmlsbD0iIzFiNTM0MyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5DYXJuZXQ8L3RleHQ+Cgk8dGV4dCB4PSIyMjMiIHk9IjE5Ni4xIiBmaWxsPSIjMWI1MzQzIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jYXJuZXQ8L3RleHQ+Cgk8bGluZSB4MT0iMjIzIiB5MT0iMTk5IiB4Mj0iMjYzIiB5Mj0iMTk5IiBzdHJva2U9IiMxYjUzNDMiIHN0cm9rZS13aWR0aD0iMSIvPgo8L2c+Cjwvc3ZnPg==\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Utiliser</strong> (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien! <sup>u1 u2</sup>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [183]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced flip:d,v --seed=12\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NzQiIGhlaWdodD0iMjk5IiB2aWV3Qm94PSIwIDAgNDc0IDI5OSI+CjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSI0NzQiIGhlaWdodD0iMjk5IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIvPgoKPCEtLSBDb25zdHJhaW50IENJRl9DT05TVFJBSU5UXyMxIC0tPgo8Zz4KCTxsaW5lIHgxPSIyNTYiIHkxPSIxMjAiIHgyPSIzOTkiIHkyPSIyMzMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtZGFzaGFycmF5PSIwLDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgoJPHBvbHlnb24gcG9pbnRzPSIyOTcgMjMzIDMwOSAyMjcgMzA1IDIzMyAzMDkgMjM5IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIyNTYiIHkxPSIyMzMiIHgyPSIzOTkiIHkyPSIyMzMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8Zz4KCQk8Y2lyY2xlIGN4PSIzOTkiIGN5PSIyMzMiIHI9IjEzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0iI0ZGRkZGRiIvPgoJCTx0ZXh0IHg9IjM5MC41IiB5PSIyMzcuMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgc3R5bGU9InBvaW50ZXItZXZlbnRzOiBub25lOyI+Q0lGPC90ZXh0PgoJPC9nPgo8L2c+Cgo8IS0tIENvbnN0cmFpbnQgQ0lGX0NPTlNUUkFJTlRfIzIgLS0+CjxnPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjEyMCIgeDI9IjM5OSIgeTI9IjM2IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iMzk5IDkwIDM5MyA3OCAzOTkgODIgNDA1IDc4IiBmaWxsPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz4KCTxsaW5lIHgxPSIzOTkiIHkxPSIxMjAiIHgyPSIzOTkiIHkyPSIzNiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9IjM5OSIgY3k9IjM2IiByPSIxMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSIzOTAuNSIgeT0iNDAuMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgc3R5bGU9InBvaW50ZXItZXZlbnRzOiBub25lOyI+Q0lGPC90ZXh0PgoJPC9nPgo8L2c+Cgo8IS0tIENvbnN0cmFpbnQgQ0lGX0NPTlNUUkFJTlRfIzMgLS0+CjxnPgoJPGxpbmUgeDE9IjI1NiIgeTE9IjEyMCIgeDI9Ijk0IiB5Mj0iMjMzIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWRhc2hhcnJheT0iMCw1IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KCTxwb2x5Z29uIHBvaW50cz0iOTQgMTUwIDEwMCAxNjIgOTQgMTU4IDg4IDE2MiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgk8bGluZSB4MT0iOTQiIHkxPSIxMjAiIHgyPSI5NCIgeTI9IjIzMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxnPgoJCTxjaXJjbGUgY3g9Ijk0IiBjeT0iMjMzIiByPSIxMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9IiNGRkZGRkYiLz4KCQk8dGV4dCB4PSI4NS41IiB5PSIyMzcuMiIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSIgc3R5bGU9InBvaW50ZXItZXZlbnRzOiBub25lOyI+Q0lGPC90ZXh0PgoJPC9nPgo8L2c+Cgo8IS0tIEFzc29jaWF0aW9uIFVUSUxJU0VSIC0tPgo8Zz4KCTxsaW5lIHgxPSI5NCIgeTE9IjEyMCIgeDI9IjI1NiIgeTI9IjEyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTxsaW5lIHgxPSIyNTYiIHkxPSIyMzMiIHgyPSIyNTYiIHkyPSIxMjAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8bGluZSB4MT0iMzk5IiB5MT0iMTIwIiB4Mj0iMjU2IiB5Mj0iMTIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPGc+CgkJPHBhdGggZD0iTTI4NyA5MSBhMTQgMTQgOTAgMCAxIDE0IDE0IFYxMTkgaC05MCBWMTA1IGExNCAxNCA5MCAwIDEgMTQgLTE0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMCIvPgoJCTxwYXRoIGQ9Ik0zMDEgMTE5IHYxNiBhMTQgMTQgOTAgMCAxIC0xNCAxNCBIMjI1IGExNCAxNCA5MCAwIDEgLTE0IC0xNCBWMTE5IEg5MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAiLz4KCQk8cmVjdCB4PSIyMTEiIHk9IjkxIiB3aWR0aD0iOTAiIGhlaWdodD0iNTgiIGZpbGw9Im5vbmUiIHJ4PSIxNCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJCTxsaW5lIHgxPSIyMTEiIHkxPSIxMTkiIHgyPSIzMDEiIHkyPSIxMTkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCQk8dGV4dCB4PSIyMTgiIHk9IjExMi4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlV0aWxpc2VyPC90ZXh0PgoJPC9nPgoJPHRleHQgeD0iMTcyIiB5PSIxNTEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEiPjEsTjwvdGV4dD4KCTx0ZXh0IHg9IjI3NiIgeT0iMTgwIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExIj4xLE48L3RleHQ+Cgk8dGV4dCB4PSIzMjEiIHk9IjE1MSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkZ1dHVyYSIgZm9udC1zaXplPSIxMSI+MSxOPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBURUNITklDSUVOIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM2IiB5PSI5MCIgd2lkdGg9IjExNiIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNiIgeT0iMTIwIiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM2IiB5PSI5MCIgd2lkdGg9IjExNiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzNiIgeTE9IjEyMCIgeDI9IjE1MiIgeTI9IjEyMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDQiIHk9IjExMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlRlY2huaWNpZW48L3RleHQ+Cgk8dGV4dCB4PSI0NCIgeT0iMTM3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnRlY2huaWNpZW48L3RleHQ+Cgk8bGluZSB4MT0iNDQiIHkxPSIxNDAiIHgyPSIxMDgiIHkyPSIxNDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IFBST0pFVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzNjAiIHk9IjkwIiB3aWR0aD0iNzgiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzYwIiB5PSIxMjAiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNjAiIHk9IjkwIiB3aWR0aD0iNzgiIGhlaWdodD0iNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzYwIiB5MT0iMTIwIiB4Mj0iNDM4IiB5Mj0iMTIwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIzNjgiIHk9IjExMS4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPlByb2pldDwvdGV4dD4KCTx0ZXh0IHg9IjM2OCIgeT0iMTM3LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnByb2pldDwvdGV4dD4KCTxsaW5lIHgxPSIzNjgiIHkxPSIxNDAiIHgyPSI0MDciIHkyPSIxNDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CjwvZz4KCjwhLS0gRW50aXR5IENBUk5FVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIyMTUiIHk9IjIwMyIgd2lkdGg9IjgyIiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjIxNSIgeT0iMjMzIiB3aWR0aD0iODIiIGhlaWdodD0iMzAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjE1IiB5PSIyMDMiIHdpZHRoPSI4MiIgaGVpZ2h0PSI2MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMTUiIHkxPSIyMzMiIHgyPSIyOTciIHkyPSIyMzMiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjIyMyIgeT0iMjI0LjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q2FybmV0PC90ZXh0PgoJPHRleHQgeD0iMjIzIiB5PSIyNTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+Y2FybmV0PC90ZXh0PgoJPGxpbmUgeDE9IjIyMyIgeTE9IjI1MyIgeDI9IjI2MyIgeTI9IjI1MyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_mld.md\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<ul>\n<li><strong>Utiliser</strong> (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien! <sup>u1 u2</sup>)</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il y a maintenant trois clés candidates, correspondant à deux contraintes d'unicité. En SQL :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [184]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t sql\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">Utiliser</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">carnet</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">projet</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">carnet</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">projet</span><span class=\"w\">     </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">technicien</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">42</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">carnet</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">technicien</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"k\">UNIQUE</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">projet</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">technicien</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h4 id=\"Conclusion-sur-les-agr%C3%A9gats-multiples\">Conclusion sur les agrégats multiples<a class=\"anchor-link\" href=\"#Conclusion-sur-les-agr%C3%A9gats-multiples\">¶</a></h4>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Notre syntaxe <code>/1N</code> pour les agrégats permet d'exprimer simplement toutes les combinaisons possibles de cardinalités d'une association n-aire dans la notation de Chen : il suffit de mettre un <code>/1N</code> partout où Chen met un <code>1</code>. Chaque <code>/1N</code> créera une nouvelle dépendance fonctionnelle, autrement dit, une nouvelle clé candidate.</p>\n<p>Plus rigoureusement : supposons une association $n$-aire $A$ exclusivement entourée de 1N (ou 0N). Soient $E_1$, $E_2$, ..., $E_n$ les entités mises en jeu, et $k_1, k_2$, ..., $k_n$ leurs identifiants respectifs. Alors, noter <code>/1N</code> (ou <code>/0N</code>) la cardinalité de la patte de $E_i$ dénote l'existence de la dépendance fonctionnelle suivante : $(k_1, ..., k_{i-1}, k_{i+1}, ..., k_n) \\implies k_i$, autrement dit : que $(k_1, ..., k_{i-1}, k_{i+1}, ..., k_n)$ est une clé candidate de la table $A$.</p>\n<p>Notez pour finir que Mocodo permet de spécifier à coût zéro quelle clé candidate sera élue clé primaire. Il suffit pour cela de placer en tête de la liste des entités mises en jeu par $A$ celle dont l'identifiant ne doit <strong>pas</strong> entrer dans la clé primaire. Si c'est $E_1$, la clé primaire sera automatiquement $(k_2, ..., k_n)$.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Annexe-B%C2%A0:-La-commande-mocodo\">Annexe B : La commande <code>mocodo</code><a class=\"anchor-link\" href=\"#Annexe-B%C2%A0:-La-commande-mocodo\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Param%C3%A9trage\">Paramétrage<a class=\"anchor-link\" href=\"#Param%C3%A9trage\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"mocodo---help\"><code>mocodo --help</code><a class=\"anchor-link\" href=\"#mocodo---help\">¶</a></h3>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [185]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> --help\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>usage: mocodo [--language CODE] [--params_path PATH] [--input PATH] [--help]\n              [--version] [--restore] [--lib [URL]] [--output_dir PATH]\n              [--encodings [STR ...]] [--svg_to {png,pdf} [{png,pdf} ...]]\n              [--print_params] [--reuse_geo] [--uid_suffix INT]\n              [--select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]]\n              [--defer [STR ...]] [--mld] [--transform [STR ...]]\n              [--seed [FLOAT]] [--title STR] [--df STR] [--card_format [STR]]\n              [--fk_format [STR]] [--strengthen_card [STR]] [--flex FLOAT]\n              [--colors STEM_OR_PATH] [--shapes STEM_OR_PATH] [--scale RATE]\n              [--adjust_width RATE] [--detect_overlaps] [--no_assoc_ids]\n              [--gutters STR [STR ...]]\n\nNOM :\nMocodo - Un générateur de diagrammes entité-association.\n\nDESCRIPTION :\nMocodo est un outil libre destiné à l'enseignement des bases de données relationnelles.\nIl prend en entrée une description textuelle des entités et associations d'un diagramme\nentité-association (MCD). Il produit en sortie un dessin vectoriel en SVG et un schéma\nrelationnel dans divers formats (SQL, LaTeX, Markdown, etc.).\n\nNOTE :\nChacune des valeurs suivantes est :\n- spécifiée explicitement par l'utilisateur comme option de ligne de commande ;\n- sinon, récupérée depuis un fichier de chemin --params_path ;\n- sinon, récupérée depuis un fichier nommé « params.json » dans le répertoire d'entrée ;\n- sinon, calculée à partir d'une valeur par défaut, éventuellement dépendante de votre système.\n    \n\nOPTIONS SUR MOCODO LUI-MÊME :\n  --language CODE       force la localisation des messages avec le code de\n                        langue donné (par exemple, « fr », « en », ...)\n                        (default: fr)\n  --help                affiche ce message d'aide, puis termine\n  --version             affiche le numéro de version, puis termine\n  --restore             recrée une version vierge des fichiers « sandbox.mcd »\n                        et « params.json » dans le répertoire d'entrée, puis\n                        termine (default: False)\n\nENTRÉE/SORTIE :\n  --params_path PATH    le chemin du fichier de paramètres. S'il est omis,\n                        utilise « params.json » dans le répertoire d'entrée.\n                        S'il n'existe pas, utilise les paramètres par défaut.\n                        (default: params.json)\n  --input PATH, -i PATH\n                        le chemin du fichier d'entrée. Par défaut, les\n                        fichiers de sortie seront générés dans le même\n                        répertoire (default: /Users/aristide/Dropbox/Sites/moc\n                        odo/doc/mocodo_notebook/sandbox.mcd)\n  --lib [URL]           remote directory to use as fallback when the input\n                        file is not found locally (default:\n                        https://mocodo.net/web/lib)\n  --output_dir PATH     le répertoire des fichiers de sortie (default: .)\n  --encodings [STR ...]\n                        un ou plusieurs encodages à essayer successivement\n                        lors de la lecture du fichier d'entrée (default:\n                        ['utf8', 'macroman'])\n  --svg_to {png,pdf} [{png,pdf} ...]\n                        génère une version PNG ou PDF de la sortie SVG\n                        (requiert CairoSVG) (default: [])\n  --print_params        affiche le contenu du fichier de paramètres, puis\n                        termine (default: False)\n  --reuse_geo           réutilise le fichier de géométrie de l'exécution\n                        précédente (default: False)\n  --uid_suffix INT      ajoute un discriminateur à un SVG interactif (default:\n                        0)\n  --select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]\n                        sous Jupyter Notebook, spécifie explicitement les\n                        catégories de résultats à afficher\n  --defer [STR ...]     utilise un service web externe pour convertir les\n                        résultats de la conversion dans les formats graphiques\n                        donnés\n  --mld                 alias de compatibilité ascendante pour « -t » (sans\n                        arguments). Équivalent à « -t markdown » mais, sous\n                        Jupyter Notebook, n'empêche pas le rendu du diagramme\n                        conceptuel dans la sortie de la cellule (default:\n                        False)\n  --transform [STR ...], -t [STR ...]\n                        crée une nouvelle version du MCD en appliquant\n                        séquentiellement les opérations de réécriture données,\n                        et/ou le convertit dans les formats ou langages\n                        donnés. Sous Jupyter Notebook, « -T » remplace\n                        respectivement la cellule courante par le résultat\n                        textuel, ou le copie dans le presse-papier (pip3\n                        install pyperclip)\n  --seed [FLOAT]        valeur initiale pour le générateur de nombres\n                        aléatoires (default: None)\n  --title STR           nom du modèle, utilisé à divers endroits (système de\n                        fichiers, base de données, etc.) (default: MCD)\n\nASPECT DE LA SORTIE GRAPHIQUE :\n  --df STR              l'acronyme à entourer dans une dépendance\n                        fonctionnelle (default: DF)\n  --card_format [STR]   chaîne de formatage pour les cardinalités minimales et\n                        maximales (default: {min_card},{max_card})\n  --fk_format [STR]     chaîne de formatage pour les clés étrangères dans le\n                        diagramme relationnel (default: #{label})\n  --strengthen_card [STR]\n                        chaîne pour les cardinalités relatives (default:\n                        _1,1_)\n  --flex FLOAT          incurve les pattes rectilignes dont les cardinalités\n                        peuvent se chevaucher (default: 0.75)\n  --colors STEM_OR_PATH\n                        la palette de couleurs à utiliser lors de la\n                        génération du dessin. Nom (sans extension) d'un\n                        fichier situé dans le répertoire « colors », ou chemin\n                        vers un fichier personnel (default: bw)\n  --shapes STEM_OR_PATH\n                        spécification des polices, dimensions, etc. Nom (sans\n                        extension) d'un fichier situé dans le répertoire\n                        « shapes », ou chemin vers un fichier personnel\n                        (default: copperplate)\n  --scale RATE          applique au diagramme le facteur de mise à l'échelle\n                        donné (default: 1)\n  --adjust_width RATE   applique à tous les textes calculés le facteur de mise\n                        à l'échelle donné (default: 1)\n  --detect_overlaps     lève une erreur quand des pattes horizontales ou\n                        verticales se chevauchent (default: False)\n  --no_assoc_ids        interdit l'utilisation d'identifiants dans les\n                        associations (conformément au standard Merise)\n                        (default: False)\n  --gutters STR [STR ...]\n                        définit la visibilité et le contenu des gouttières\n                        latérales\n\nVOIR AUSSI :\n  Version en ligne      https://mocodo.net\n  Code source           https://github.com/laowantong/mocodo\n  Documentation         https://laowantong.github.io/mocodo/doc/fr_refman.html\n  Aide-mémoire pour -t  https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md\n\nLICENCE :               MIT\n\nCONTACT :\n  Auteur                Aristide Grange\n  Adresse               Université de Lorraine\n                        Laboratoire LCOMS - UFR MIM\n                        3 rue Augustin Fresnel\n                        57070 METZ Technopôle\n                        France\n  Courriel              &lt;prénom.nom&gt;@univ-lorraine.fr\n    \n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Param%C3%A9trage-%C3%A0-long-terme\">Paramétrage à long terme<a class=\"anchor-link\" href=\"#Param%C3%A9trage-%C3%A0-long-terme\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour éviter d'avoir à invoquer Mocodo répétitivement avec une longue kyrielle d'options, vous pouvez mettre celles-ci dans un fichier <code>params.json</code> situé dans le répertoire de lancement de Mocodo. La commande:</p>\n<pre><code>mocodo --restore</code></pre>\n<p>... le fait pour vous avec un fichier de paramètres vide, <em>i.e.</em>, un fichier-texte réduit aux deux caractères <code>{}</code>  (attention, elle rétablit aussi le fichier <code>sandbox.mcd</code> à son contenu par défaut).</p>\n<p>Pour que le style de vos MCD soit maintenu à moindre frais à travers tous vos documents, vous êtes encouragés à modifier ce fichier de paramètres selon vos goûts et vos besoins. Mocodo peut même vous aider à le faire en exécutant la cellule suivante:</p>\n<pre><code>%mocodo --print_params\n</code></pre>\n<p>Son évaluation remplace son propre contenu par des lignes de code similaires à :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [186]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"c1\"># You may edit and run the following lines</span>\n<span class=\"kn\">import</span> <span class=\"nn\">json</span><span class=\"o\">,</span> <span class=\"nn\">pathlib</span>\n<span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"s2\">\"\"\"</span><span class=\"se\">\\</span>\n<span class=\"s2\">{</span>\n<span class=\"s2\">  \"adjust_width\": 1,</span>\n<span class=\"s2\">  \"card_format\": \"</span><span class=\"si\">{min_card}</span><span class=\"s2\">,</span><span class=\"si\">{max_card}</span><span class=\"s2\">\",</span>\n<span class=\"s2\">  \"colors\": \"bw\",</span>\n<span class=\"s2\">  \"detect_overlaps\": false,</span>\n<span class=\"s2\">  \"df\": \"DF\",</span>\n<span class=\"s2\">  \"encodings\": [ \"utf8\", \"macroman\" ],</span>\n<span class=\"s2\">  \"fk_format\": \"#</span><span class=\"si\">{label}</span><span class=\"s2\">\",</span>\n<span class=\"s2\">  \"flex\": 0.75,</span>\n<span class=\"s2\">  \"language\": \"fr\",</span>\n<span class=\"s2\">  \"lib\": \"https://mocodo.net/web/lib\",</span>\n<span class=\"s2\">  \"mld\": false,</span>\n<span class=\"s2\">  \"no_assoc_ids\": false,</span>\n<span class=\"s2\">  \"output_dir\": \".\",</span>\n<span class=\"s2\">  \"restore\": false,</span>\n<span class=\"s2\">  \"scale\": 1,</span>\n<span class=\"s2\">  \"seed\": null,</span>\n<span class=\"s2\">  \"shapes\": \"copperplate\",</span>\n<span class=\"s2\">  \"strengthen_card\": \"_1,1_\",</span>\n<span class=\"s2\">  \"svg_to\": [],</span>\n<span class=\"s2\">  \"title\": \"MCD\",</span>\n<span class=\"s2\">  \"uid_suffix\": 0</span>\n<span class=\"s2\">}\"\"\"</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">json</span><span class=\"o\">.</span><span class=\"n\">loads</span><span class=\"p\">(</span><span class=\"n\">params</span><span class=\"p\">)</span>\n<span class=\"k\">except</span><span class=\"p\">:</span>\n    <span class=\"k\">raise</span> <span class=\"ne\">RuntimeError</span><span class=\"p\">(</span><span class=\"s2\">\"Invalid JSON. Check your syntax on https://jsonlint.com.\"</span><span class=\"p\">)</span>\n<span class=\"n\">pathlib</span><span class=\"o\">.</span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s2\">\"./params.json\"</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">write_text</span><span class=\"p\">(</span><span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"n\">encoding</span><span class=\"o\">=</span><span class=\"s2\">\"utf8\"</span><span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ensuite :</p>\n<ol>\n<li>Modifiez la variable <code>params</code> à votre gré en respectant la syntaxe <a href=\"http://json.org\">JSON</a>.</li>\n<li>Exécutez la cellule pour créer un fichier de nom et emplacement adéquats.</li>\n</ol>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>En cas de besoin, vous pourrez toujours ponctuellement passer outre ces réglages en en précisant d'autres en ligne de commande. Plus précisément, chaque paramètre est déterminé:</p>\n<ol>\n<li>par sa valuation en ligne de commande;</li>\n<li>à défaut, par sa valuation dans le fichier de paramètres indiqué par <code>--params_path</code>;</li>\n<li>à défaut d'une telle indication, par sa valuation dans le fichier <code>params.json</code> du répertoire courant;</li>\n<li>à défaut, par une valeur défaut éventuellement dépendante de votre système.</li>\n</ol>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Dissection-de-la-commande\">Dissection de la commande<a class=\"anchor-link\" href=\"#Dissection-de-la-commande\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'API de Mocodo a été revue de façon radicale pour la version 4.0. Le nombre d'options de premier niveau a été réduit ; en contrepartie, certaines sont devenues de véritables mini-commandes, avec leur propre liste d'arguments, et une syntaxe et un comportement uniformes. Voici leur définition en ABNF :</p>\n<p><img alt=\"\" src=\"examples/option_syntax_2.png\"/></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Introduisons, sur un exemple fictif, un vocabulaire que nous avons essayé d'employer le plus rigoureusement possible tout au long de cette documentation (et dans le code lui-même) :</p>\n<pre><code>mocodo    --select all    --transform  drain  arrange:wide  explode:weak,arity=2.5\n</code></pre>\n<ul>\n<li>La <strong>commande</strong> <code>mocodo</code> est invoquée avec les <strong>options</strong> <code>--select</code> et <code>--transform</code>.</li>\n<li>On passe à la seconde trois <strong>arguments</strong> de complexité croissante, <code>drain</code>, <code>arrange:wide</code> et <code>explode:weak,arity=2.5</code>. Notez que le séparateur des arguments est l'espace. Par conséquent, un argument ne peut contenir d'espaces qu'entre guillemets.</li>\n<li>Chacun des arguments consiste en un nom de <strong>sous-option</strong> (<code>drain</code>, <code>arrange</code> ou <code>explode</code>), suivi éventuellement d'un deux-points (<code>:</code>), suivi d'une liste de <strong>sous-arguments</strong> séparés par des virgules (<code>,</code>).</li>\n<li>Chacun des sous-arguments consiste en un nom de <strong>sous-sous-option</strong>, suivi éventuellement d'un signe égal (<code>=</code>), suivi d'un <strong>sous-sous-argument</strong> (éventuellement entre guillemets).</li>\n</ul>\n<p>On n'ira pas plus loin et, heureusement, la plupart des commandes réelles n'atteignent pas ce degré d'imbrication. La décomposition suivante fixera peut-être les idées, ou pourra du moins servir de référence en cas de doute :</p>\n<p>$$\n\\underbrace{\\texttt{mocodo}}_{\\text{command}}\n\\qquad\n\\texttt{-}\\,\\texttt{-}\n\\underbrace{\\texttt{select}}_{\\text{option}}\n\\underbrace{\n    \\texttt{all}\n}_{\\text{argument}}\n\\qquad\n\\texttt{-}\\,\\texttt{-}\n\\underbrace{\\texttt{transform}}_{\\text{option}}\n\\qquad\n\\underbrace{\n    \\underbrace{\n        \\texttt{drain}\n    }_{\\text{sub-option}}\n}_{\\text{argument}}\n\\qquad\n\\underbrace{\n    \\underbrace{\n        \\texttt{arrange}\n    }_{\\text{sub-option}}\n    \\texttt{:}\n    \\underbrace{\n        \\underbrace{\n            \\texttt{wide}\n        }_{\\text{sub-sub-opt}}\n    }_{\\text{sub-arg}}\n}_{\\text{argument}}\n\\qquad\n\\underbrace{\n    \\underbrace{\n        \\texttt{explode}\n    }_{\\text{sub-option}}\n    \\texttt{:}\n    \\underbrace{\n        \\underbrace{\n            \\texttt{weak}\n        }_{\\text{sub-sub-opt}}\n    }_{\\text{sub-arg}}\n    \\texttt{,}\n    \\underbrace{\n        \\underbrace{\n            \\texttt{arity}\n        }_{\\text{sub-sub-opt}}\n        \\texttt{=}\n        \\underbrace{\n            \\texttt{2.5}\n        }_{\\text{sub-sub-arg}}\n    }_{\\text{sub-argument}}\n}_{\\text{argument}}\n$$</p>\n<p>L'intérêt de cette structuration en arborescence est double. Elle permet :</p>\n<ul>\n<li>de créer des pipelines d'opérations : le résultat de l'application du premier argument est fourni en entrée au second, etc ;</li>\n<li>de regrouper les opérations interdépendantes. Par exemple, avant la version 4.0, l'argument <code>explode:weak,arity=2.5</code> aurait dû être mis à plat : <code>--explode --weak_explosion --explosion_arity=2.5</code>. Cela donne le même statut à toutes, masquant le fait que certaines n'ont de sens qu'en présence d'une autre.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"L'option---transform-et-ses-arguments\">L'option <code>--transform</code> et ses arguments<a class=\"anchor-link\" href=\"#L'option---transform-et-ses-arguments\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Triage-et-ex%C3%A9cution-des-transformations\">Triage et exécution des transformations<a class=\"anchor-link\" href=\"#Triage-et-ex%C3%A9cution-des-transformations\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'option à tout faire est <code>--transform</code>, que vous pouvez abréger <code>-t</code>. Avant de traiter ses arguments, Mocodo commence par les répartir en deux catégories :</p>\n<ul>\n<li>les <strong>réécritures</strong>, qui transforment le MCD original en un nouveau MCD avec, par exemple, les libellés mis en majuscules, ou les associations n-aires décomposées en DF, ou les boîtes réarrangées ;</li>\n<li>les <strong>conversions</strong>, qui produisent quelque chose qui n'est pas un MCD : ce peut être un dictionnaire des données, un diagramme de classes UML, un ERD dans la notation <em>crow's foot</em>, etc.</li>\n</ul>\n<p>L'exécution se déroule alors en deux étapes :</p>\n<ol>\n<li>les réécritures sont opérées en pipeline, c'est-à-dire que le MCD produit par la première réécriture est passé en entrée de la seconde, etc. Leur ordre a donc de l'importance ;</li>\n<li>les conversions sont alors appliquées au résultat de la dernière réécriture. Leur ordre n'a pas d'importance.</li>\n</ol>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Aide-m%C3%A9moire-des-transformations\">Aide-mémoire des transformations<a class=\"anchor-link\" href=\"#Aide-m%C3%A9moire-des-transformations\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'option <code>-t</code> (ou <code>--transform</code>) permet d'accéder à un grand nombre d'opérations de conversion ou de réécriture.</p>\n<p>Toutes les opérations de conversion ont déjà été décrites dans ce document :</p>\n<ul>\n<li>produits dérivés : <code>data_dict</code>, <code>share</code> ;</li>\n<li>schémas relationnels textuels : <code>html</code>, <code>latex</code>, <code>markdown</code>, <code>text</code> ;</li>\n<li>DDL : <code>sql</code> (et ses dialectes) ;</li>\n<li>autres sorties relationnelles : <code>diagram</code>, <code>dbml</code>, <code>d2</code>, <code>dependencies</code> ;</li>\n<li>conversions dans d'autres notations : <code>uml</code>, <code>crow</code>, <code>chen</code>.</li>\n</ul>\n<p>Certaines opérations de réécriture ont été présentées, d'autres passées sous silence :</p>\n<ul>\n<li>réorganisation du MCD : <code>arrange</code>, <code>flip</code> ;</li>\n<li>obfuscation et randomisation d'éléments donnés : <code>randomize</code>, <code>drown</code> ;</li>\n<li>génération de MCD aléatoires : <code>grow</code> ;</li>\n<li>décomposition d'associations : <code>split</code>, <code>drain</code>, <code>explode</code> ;</li>\n<li>inférence d'informations manquantes : <code>create</code> ;</li>\n<li>suppression d'éléments donnés : <code>delete</code> ;</li>\n<li>traitement de chaînes de caractères : <code>truncate</code>, <code>slice</code>, <code>prefix</code>, <code>suffix</code>, <code>replace</code> ;</li>\n<li>homogénéisation de la mise en forme : <code>ascii</code>, <code>camel</code>, <code>snake</code>, <code>pascal</code>, <code>lower</code>, <code>upper</code>, etc.</li>\n</ul>\n<p>L'aide-mémoire suivant devrait vous permettre de prendre en main les sous-options de <code>--transform</code> qui vous intéressent. Survolez une sous-option pour afficher ses alias éventuels.</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [187]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Markdown</span><span class=\"p\">(</span><span class=\"s2\">\"../fr_cheat_sheet.md\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[187]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<h3 id=\"Op%C3%A9rations-de-conversion\">Opérations de conversion<a class=\"anchor-link\" href=\"#Op%C3%A9rations-de-conversion\">¶</a></h3><table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Sous-option</th>\n<th style=\"text-align:left\">Description</th>\n<th style=\"text-align:left\">Exemples</th>\n<th style=\"text-align:left\">Explications</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">ast</span></td>\n<td style=\"text-align:left\">crée l'arbre de syntaxe abstraite du texte source (pour le débogage)</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">chen</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel dans la notation de Chen</td>\n<td style=\"text-align:left\"><code>chen</code></td>\n<td style=\"text-align:left\">sans attributs</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>chen:attrs</code></td>\n<td style=\"text-align:left\">avec attributs</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>chen:attrs --defer</code></td>\n<td style=\"text-align:left\">calcule le rendu graphique via un service web</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>chen:layout=circo,mindist=2,scale=0.6</code></td>\n<td style=\"text-align:left\">ajoute des options arbitraires pour Graphviz</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : crowfoot, crowsfoot.\">crow</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel dans la notation crow's foot</td>\n<td style=\"text-align:left\"><code>crow</code></td>\n<td style=\"text-align:left\">format Graphviz</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>crow --defer</code></td>\n<td style=\"text-align:left\">calcule le rendu graphique via un service web</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>crow:mmd</code></td>\n<td style=\"text-align:left\">format Mermaid</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>crow:mermaid</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">d2</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format D2</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : data_dictionary.\">data_dict</span></td>\n<td style=\"text-align:left\">extrait tous les attributs du MCD dans une table</td>\n<td style=\"text-align:left\"><code>data_dict</code></td>\n<td style=\"text-align:left\">tableau Markdown, trois colonnes</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:label</code></td>\n<td style=\"text-align:left\">liste Markdown, une colonne</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:label,type='Description'</code></td>\n<td style=\"text-align:left\">deux colonnes, un libellé personnalisé</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:label='Attribut',type='Description'</code></td>\n<td style=\"text-align:left\">deux colonnes, deux libellés personnalisés</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:**box**='Entité ou&lt;br&gt;association',label,`type`=`'Type de données'`</code></td>\n<td style=\"text-align:left\">mise en forme de certains libellés</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:tsv</code></td>\n<td style=\"text-align:left\">tableau TSV, trois colonnes</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>data_dict:tsv,label</code></td>\n<td style=\"text-align:left\">liste des attributs séparés par des retours à la ligne</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">dbml</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format DBML</td>\n<td style=\"text-align:left\"><code>dbml</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>dbml:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">debug</span></td>\n<td style=\"text-align:left\">liste des informations internes relatives à la conversion en schéma relationnel</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">dependencies</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un graphe de dépendances</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">diagram</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un diagramme relationnel au format Mocodo</td>\n<td style=\"text-align:left\"><code>diagram</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>diagram:c</code></td>\n<td style=\"text-align:left\">avec contraintes d'unicité et d'optionalité</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">html</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format HTML</td>\n<td style=\"text-align:left\"><code>html</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:c</code></td>\n<td style=\"text-align:left\">avec contraintes d'unicité et d'optionalité</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:e</code></td>\n<td style=\"text-align:left\">avec explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:bce</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em>, contraintes et explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : tex.\">latex</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format LaTeX</td>\n<td style=\"text-align:left\"><code>latex</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>latex:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>latex:c</code></td>\n<td style=\"text-align:left\">avec contraintes d'unicité et d'optionalité</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>latex:e</code></td>\n<td style=\"text-align:left\">avec explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>latex:bce</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em>, contraintes et explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : md, mld.\">markdown</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format Markdown</td>\n<td style=\"text-align:left\"><code>markdown</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>markdown:c</code></td>\n<td style=\"text-align:left\">avec contraintes d'unicité et d'optionalité</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>markdown:e</code></td>\n<td style=\"text-align:left\">avec explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>markdown:ce</code></td>\n<td style=\"text-align:left\">avec contraintes et explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : ms_sql, sql_server, sqlserver.\">mssql</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server</td>\n<td style=\"text-align:left\"><code>mssql</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>mssql:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">mysql</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour MySQL</td>\n<td style=\"text-align:left\"><code>mysql</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>mysql:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : oracle_db.\">oracle</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour Oracle DB</td>\n<td style=\"text-align:left\"><code>oracle</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>oracle:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : postgres.\">postgresql</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour PostgreSQL</td>\n<td style=\"text-align:left\"><code>postgresql</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>postgresql:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : chat, chatbot, ia, ai.\">prompt</span></td>\n<td style=\"text-align:left\">génère un prompt pour demander à une IA de compléter le MCD</td>\n<td style=\"text-align:left\"><code>prompt:cards</code></td>\n<td style=\"text-align:left\">avec les explications des cardinalités</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>prompt:types</code></td>\n<td style=\"text-align:left\">avec les types des attributs</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : template, relation_template.\">relation</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en schéma relationnel avec le gabarit donné</td>\n<td style=\"text-align:left\"><code>relation:path/to/my_template.yaml</code></td>\n<td style=\"text-align:left\">chemin relatif, extension obligatoire</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : url, link, qr, qr_code.\">share</span></td>\n<td style=\"text-align:left\">encode le MCD dans une URL pour Mocodo online</td>\n<td style=\"text-align:left\"><code>qr --defer</code></td>\n<td style=\"text-align:left\">génère un QR code via un service web</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : ddl.\">sql</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour SQL</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">sqlite</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un modèle physique pour SQLite</td>\n<td style=\"text-align:left\"><code>sqlite</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>sqlite:b</code></td>\n<td style=\"text-align:left\">avec <em>boilerplate</em></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : txt.\">text</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en un schéma relationnel au format texte</td>\n<td style=\"text-align:left\"><code>text</code></td>\n<td style=\"text-align:left\">version de base</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>text:c</code></td>\n<td style=\"text-align:left\">avec contraintes d'unicité et d'optionalité</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:e</code></td>\n<td style=\"text-align:left\">avec explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>html:ce</code></td>\n<td style=\"text-align:left\">avec contraintes et explications</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : uml, class_diagram.\">uml</span></td>\n<td style=\"text-align:left\">convertit le modèle conceptuel en diagramme de classes UML</td>\n<td style=\"text-align:left\"><code>uml</code></td>\n<td style=\"text-align:left\">format PlantUML</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>uml:plantuml</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>uml --defer</code></td>\n<td style=\"text-align:left\">calcule le rendu graphique via un service web</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>uml:plantuml=-</code></td>\n<td style=\"text-align:left\">supprime les styles par défaut</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>uml:plantuml='skinparam backgroundColor yellow\\nskinparam classAttributeFontName Arial\\n'</code></td>\n<td style=\"text-align:left\">ajoute des styles personnalisés</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"Op%C3%A9rations-de-r%C3%A9%C3%A9criture\">Opérations de réécriture<a class=\"anchor-link\" href=\"#Op%C3%A9rations-de-r%C3%A9%C3%A9criture\">¶</a></h3><table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Sous-option</th>\n<th style=\"text-align:left\">Description</th>\n<th style=\"text-align:left\">Exemples</th>\n<th style=\"text-align:left\">Explications</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">arrange</span></td>\n<td style=\"text-align:left\">réarrange la disposition, soit par Branch &amp; Bound, soit avec un algorithme génétique</td>\n<td style=\"text-align:left\"><code>arrange</code></td>\n<td style=\"text-align:left\">B&amp;B sans contraintes</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:timeout=60</code></td>\n<td style=\"text-align:left\">B&amp;B limité à une minute</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:wide</code></td>\n<td style=\"text-align:left\">B&amp;B privilégiant la largeur</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:current</code></td>\n<td style=\"text-align:left\">B&amp;B sur la grille courante</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:balanced=0</code></td>\n<td style=\"text-align:left\">B&amp;B sur la plus petite grille équilibrée</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:balanced=1</code></td>\n<td style=\"text-align:left\">B&amp;B sur la seconde plus petite grille équilibrée</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>arrange:algo=ga</code></td>\n<td style=\"text-align:left\">algorithme génétique</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">ascii</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en ASCII</td>\n<td style=\"text-align:left\"><code>ascii:roles,labels</code></td>\n<td style=\"text-align:left\">rôles, libellés des boîtes et des attributs en ASCII</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : camelcase, camel_case.\">camel</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en camelCase</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">capitalize</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en capitalisant la première lettre de chaque mot</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : case_fold.\">casefold</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en minuscules, mais plus agressivement que « lower »</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : add, insert, make, guess, infer, complete, new.\">create</span></td>\n<td style=\"text-align:left\">essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants</td>\n<td style=\"text-align:left\"><code>guess:types</code></td>\n<td style=\"text-align:left\">deviner les types manquants</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>create:types=</code></td>\n<td style=\"text-align:left\">remplacer les types manquants par <code>[]</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>create:types=TODO</code></td>\n<td style=\"text-align:left\">remplacer les types manquants par <code>[TODO]</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>make:entities</code></td>\n<td style=\"text-align:left\">réparer l'oubli d'entités référencées dans des associations</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>create:dfs</code></td>\n<td style=\"text-align:left\">mettre des DF partout où c'est possible</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>add:df_arrows</code></td>\n<td style=\"text-align:left\">ajouter des flèches aux DF 11</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>add:cifs</code></td>\n<td style=\"text-align:left\">ajouter les CIF correspondant aux agrégats</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>add:cifs=light</code></td>\n<td style=\"text-align:left\">même chose en visualisation allégée</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>add:roles</code></td>\n<td style=\"text-align:left\">mettre comme rôles le nom des associations partout où c'est utile</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : del, suppress, erase, remove, hide, empty.\">delete</span></td>\n<td style=\"text-align:left\">supprime les éléments donnés quand c'est possible</td>\n<td style=\"text-align:left\"><code>empty</code></td>\n<td style=\"text-align:left\">ne garde que la structure et le nom des boîtes</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>delete:types,notes,attrs,cards</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>delete:cards</code></td>\n<td style=\"text-align:left\">remplace les cardinalités par <code>XX</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>delete:card_prefixes</code></td>\n<td style=\"text-align:left\">supprime les marqueurs d'entités faibles et d'agrégats</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>delete:dfs</code></td>\n<td style=\"text-align:left\">supprime les entités indépendantes dont tous les attributs sont identifiants (et les DF qui les relient)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">drain</span></td>\n<td style=\"text-align:left\">déplace tout attribut d'association (1,1) vers l'entité appropriée</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : drown_by_numbers, anonymize, anonymise.\">drown</span></td>\n<td style=\"text-align:left\">remplace tous les noms d'éléments par un libellé générique numéroté</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">echo</span></td>\n<td style=\"text-align:left\">réécrit le texte source tel quel</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">explode</span></td>\n<td style=\"text-align:left\">décompose toute association n-aire (*,N) en n associations binaires</td>\n<td style=\"text-align:left\"><code>explode arrange</code></td>\n<td style=\"text-align:left\">décomposer les non-DF ternaires et plus, puis réarranger</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>explode:arity=3 arrange</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>explode:weak arrange</code></td>\n<td style=\"text-align:left\">idem, avec création d'entités faibles</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>explode:arity=2.5 arrange</code></td>\n<td style=\"text-align:left\">étendre aux non-DF binaires porteuses d'attributs</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>explode:arity=2 arrange</code></td>\n<td style=\"text-align:left\">étendre à toutes les non-DF binaires</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">fix</span></td>\n<td style=\"text-align:left\">essaie de corriger les erreurs courantes dans les éléments donnés</td>\n<td style=\"text-align:left\"><code>fix:cards</code></td>\n<td style=\"text-align:left\">normaliser les cardinalités en 01, 11, 0N et 1N</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : mirror, reflect.\">flip</span></td>\n<td style=\"text-align:left\">applique au diagramme une symétrie verticale, horizontale ou diagonale</td>\n<td style=\"text-align:left\"><code>flip:v</code></td>\n<td style=\"text-align:left\">symétrie verticale</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>flip:h</code></td>\n<td style=\"text-align:left\">symétrie horizontale</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>flip:d</code></td>\n<td style=\"text-align:left\">symétrie selon la seconde diagonale</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>flip:vhd</code></td>\n<td style=\"text-align:left\">symétrie selon la première diagonale</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>flip:dhv</code></td>\n<td style=\"text-align:left\">idem (ordre indifférent)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">grow</span></td>\n<td style=\"text-align:left\">ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations)</td>\n<td style=\"text-align:left\"><code>grow arrange</code></td>\n<td style=\"text-align:left\">ajouter des éléments avec les paramètres par défaut, puis réarranger</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:n=10</code></td>\n<td style=\"text-align:left\">nombre total d'associations à ajouter (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:arity_1=2</code></td>\n<td style=\"text-align:left\">nombre d'associations réflexives (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:arity_3=2</code></td>\n<td style=\"text-align:left\">nombre d'associations ternaires (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:arity_4=0</code></td>\n<td style=\"text-align:left\">nombre d'associations quaternaires (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:doubles=1</code></td>\n<td style=\"text-align:left\">nombre d'associations liant deux mêmes entités (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:composite_ids=1</code></td>\n<td style=\"text-align:left\">nombre d'identifiants composites (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:ent_attrs=4</code></td>\n<td style=\"text-align:left\">nombre maximal d'attributs par entité (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:assoc_attrs=2</code></td>\n<td style=\"text-align:left\">nombre maximal d'attributs par association (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:'*1-*N'=3</code></td>\n<td style=\"text-align:left\">nombre d'associations <code>*1-*N</code> (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:'01-11'=1</code></td>\n<td style=\"text-align:left\">nombre d'associations <code>01-11</code> (défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:'_11-*N'=1</code></td>\n<td style=\"text-align:left\">une entité faible (zéro par défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:'/1N-*N'=1</code></td>\n<td style=\"text-align:left\">un agrégat (zéro par défaut)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:from_scratch arrange</code></td>\n<td style=\"text-align:left\">à partir d'un MCD vide</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>grow:grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange</code></td>\n<td style=\"text-align:left\">créer un MCD d'entraînement à la conversion en relationnel</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : lowercase, lower_case.\">lower</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en minuscules</td>\n<td style=\"text-align:left\"><code>lower:attrs,roles</code></td>\n<td style=\"text-align:left\">attributs et rôles en minuscules</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : pascalcase, pascal_case.\">pascal</span></td>\n<td style=\"text-align:left\">réécrit les élements donnés en PascalCase</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : prepend.\">prefix</span></td>\n<td style=\"text-align:left\">préfixe les éléments donnés avec la chaîne donnée</td>\n<td style=\"text-align:left\"><code>prefix:roles='-'</code></td>\n<td style=\"text-align:left\">force les rôles à remplacer le nom des clés étrangères lors du passage au relationnel</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : rand, random, randomise, obfuscate, obscure.\">randomize</span></td>\n<td style=\"text-align:left\">garde la structure, mais randomise les éléments donnés quand c'est possible</td>\n<td style=\"text-align:left\"><code>obfuscate</code></td>\n<td style=\"text-align:left\">libellés remplacés par du Lorem Ipsum</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>obfuscate:labels=lorem</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>obfuscate:labels=disparition</code></td>\n<td style=\"text-align:left\">idem, lexique du roman de Perec</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>obfuscate:labels=en4</code></td>\n<td style=\"text-align:left\">idem, mots anglais de 4 lettres (SFW)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>obfuscate:attrs=fr,boxes=fr5</code></td>\n<td style=\"text-align:left\">idem, mots français de longueur quelconque pour les attributs, de 5 lettres pour les boîtes</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>randomize:types</code></td>\n<td style=\"text-align:left\">types randomisés avec les fréquences de <code>default_datatypes_fr.tsv</code>.</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : substitute, sub, repl.\">replace</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné</td>\n<td style=\"text-align:left\"><code>replace:boxes='DIRIGER/RÉPONDRE DE'</code></td>\n<td style=\"text-align:left\">renomme une boîte</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:texts='personel/personnel'</code></td>\n<td style=\"text-align:left\">corrige une faute d'orthographe</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:replace:texts='_/ '</code></td>\n<td style=\"text-align:left\">remplace les tirets bas par des espaces</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:types='VARCHAR/VARCHAR2'</code></td>\n<td style=\"text-align:left\">modifie un nom de type</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:cards=0N/1N</code></td>\n<td style=\"text-align:left\">remplace toutes les cardinalités 0N par 1N</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:cards=1N//1N</code></td>\n<td style=\"text-align:left\">crée des agrégats un peu partout</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>replace:cards='0/X' replace:cards='11/X1' replace:cards='1N/XN'</code></td>\n<td style=\"text-align:left\">masque les cardinalités minimales</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>delete:card_prefixes replace:cards=11/_11</code></td>\n<td style=\"text-align:left\">ajoute des marqueurs d'entités faibles</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : cut, interval.\">slice</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en n'en gardant qu'une tranche donnée</td>\n<td style=\"text-align:left\"><code>slice:boxes=5:10</code></td>\n<td style=\"text-align:left\">de l'indice 5 (inclus) à l'indice 10 (exclu)</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes=5:</code></td>\n<td style=\"text-align:left\">supprime les 5 premiers caractères</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes=:5</code></td>\n<td style=\"text-align:left\">ne garde que les 5 premiers caractères</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes=:-5</code></td>\n<td style=\"text-align:left\">supprime les 5 derniers caractères</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes=:</code></td>\n<td style=\"text-align:left\">équivalent de <code>echo</code></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes=</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"><code>slice:boxes</code></td>\n<td style=\"text-align:left\">idem</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : snakecase, snake_case.\">snake</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en snake_case</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\">split</span></td>\n<td style=\"text-align:left\">décompose toute association n-aire (*,1) en n-1 associations binaires</td>\n<td style=\"text-align:left\"><code>split arrange</code></td>\n<td style=\"text-align:left\">décomposer, puis réarranger</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : append.\">suffix</span></td>\n<td style=\"text-align:left\">suffixe les éléments donnés avec la chaîne donnée</td>\n<td style=\"text-align:left\"><code>suffix:boxes=1</code></td>\n<td style=\"text-align:left\">Ajoute un suffixe numérique au nom des boîtes en vue de mettre un MCD et sa copie sur le même diagramme.</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : swap_case.\">swapcase</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en inversant la casse de chaque lettre</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : titlecase, title_case.\">title</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule</td>\n<td style=\"text-align:left\"></td>\n<td style=\"text-align:left\"></td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : trunc, shorten.\">truncate</span></td>\n<td style=\"text-align:left\">tronque les éléments donnés à la longueur donnée (par défaut : 64)</td>\n<td style=\"text-align:left\"><code>truncate:boxes=10</code></td>\n<td style=\"text-align:left\">tronque les noms des boîtes à 10 caractères</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><span style=\"font-family:monospace; font-weight:600\" title=\"Alias : uppercase, upper_case.\">upper</span></td>\n<td style=\"text-align:left\">réécrit les éléments donnés en majuscules</td>\n<td style=\"text-align:left\"><code>upper:boxes</code></td>\n<td style=\"text-align:left\">noms des boîtes en majuscules</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"R%C3%A9%C3%A9criture-d'%C3%A9l%C3%A9ments-donn%C3%A9s\">Réécriture d'éléments donnés<a class=\"anchor-link\" href=\"#R%C3%A9%C3%A9criture-d'%C3%A9l%C3%A9ments-donn%C3%A9s\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Dans l'aide-mémoire, de nombreuses opérations de réécriture sont décrites comme s'appliquant à des « éléments donnés ». Il s'agit de certains ensembles de <em>tokens</em> produits par l'analyse syntaxique. Plus précisément :</p>\n<ul>\n<li><code>arrows</code> : flèches de pattes (suffixes <code>&lt;</code> ou <code>&gt;</code> des cardinalités).</li>\n<li><code>attrs</code> : libellés des attributs d'entités ou d'associations.</li>\n<li><code>boxes</code> : libellés des entités et associations.</li>\n<li><code>cards</code> : cardinalités (<code>11</code>, <code>1N</code>, etc., sans préfixe ni suffixe).</li>\n<li><code>card_prefixes</code> : préfixes de cardinalités (<code>_</code> pour les entités faibles, <code>/</code> pour les agrégats).</li>\n<li><code>constraint_notes</code> : messages affichés au survol d'une contrainte.</li>\n<li><code>labels</code> : libellés des entités, des associations et des attributs.</li>\n<li><code>leg_notes</code> : notes de pattes (rôles ou messages affichés au survol).</li>\n<li><code>notes</code> : équivalent de <code>roles</code> + <code>constraint_notes</code>.</li>\n<li><code>roles</code> : alias de <code>leg_notes</code>.</li>\n<li><code>texts</code> : équivalent de <code>labels</code> + <code>notes</code>.</li>\n<li><code>types</code> : types de données.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Fonctionnement-de-la-commande-magique\">Fonctionnement de la commande magique<a class=\"anchor-link\" href=\"#Fonctionnement-de-la-commande-magique\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il peut être utile de comprendre ce qui se passe en coulisses lorsque l'on invoque la commande magique sur une cellule d'un notebook Jupyter :</p>\n<ul>\n<li>dans le répertoire courant est créé au besoin un sous-répertoire <code>mocodo_notebook</code> ;</li>\n<li>le texte d'entrée y est sauvegardé sous le nom de <code>sandbox.mcd</code> ;</li>\n<li>la commande est lancée sur ce fichier avec tous les paramètres donnés par l'utilisateur. Cela signifie que tous les fichiers générés le seront au même endroit sous les noms de <code>sandbox.svg</code>, <code>sandbox.html</code>, etc. (relisez-les avec la commande magique <code>%load</code>) ;</li>\n<li>certains des fichiers générés sont affichés dans la sortie de la cellule, d'autres pas, selon les règles suivantes (<code>rw</code> et <code>cv</code> dénotent respectivement une opération de réécriture et de conversion) :</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">commande</th>\n<th style=\"text-align:center\">tracé<br/>du MCD</th>\n<th style=\"text-align:center\">résultat des<br/>réécritures</th>\n<th style=\"text-align:center\">résultats des<br/>conversions</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>mocodo</code></td>\n<td style=\"text-align:center\">initial</td>\n<td style=\"text-align:center\">-</td>\n<td style=\"text-align:center\">-</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><code>mocodo -t</code> ou <code>mocodo --mld</code></td>\n<td style=\"text-align:center\">initial</td>\n<td style=\"text-align:center\">-</td>\n<td style=\"text-align:center\">MLD en<br/>Markdown</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><code>mocodo -t rw1 rw2 ...</code></td>\n<td style=\"text-align:center\">final</td>\n<td style=\"text-align:center\">final</td>\n<td style=\"text-align:center\">-</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><code>mocodo -t             cv1 cv2 ...</code></td>\n<td style=\"text-align:center\">-</td>\n<td style=\"text-align:center\">-</td>\n<td style=\"text-align:center\">tous</td>\n</tr>\n<tr>\n<td style=\"text-align:left\"><code>mocodo -t rw1 rw2 ... cv1 cv2 ...</code></td>\n<td style=\"text-align:center\">final</td>\n<td style=\"text-align:center\">-</td>\n<td style=\"text-align:center\">tous</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Ces règles d'affichage par défaut devraient répondre aux besoins les plus courants, mais l'option <code>--select</code> peut prendre le pas :</p>\n<ul>\n<li>sans arguments, rien n'est affiché ;</li>\n<li>l'argument <code>mcd</code> affiche le diagramme conceptuel ;</li>\n<li>l'argument <code>rw</code> (ou un alias de commodité parmi <code>source</code>, <code>text</code>, <code>code</code>, <code>mocodo</code>) affiche le résultat de la <em>dernière</em> réécriture ;</li>\n<li>l'argument <code>cv</code> (ou un alias de commodité parmi <code>mld</code>, <code>ddl</code>, <code>sql</code>) affiche les résultats des conversions ;</li>\n<li>ces arguments peuvent être librement combinés et ordonnés ;</li>\n<li>l'argument <code>all</code> affiche tout ce qui est disponible, dans l'ordre <code>mcd</code>, <code>rw</code> et <code>cv</code> ;</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les conversions génèrent par défaut un fichier-texte. Un dessin s'affichera à la place :</p>\n<ul>\n<li>pour l'argument <code>diagram</code> ;</li>\n<li>avec l'option <code>--defer</code>, pour autant qu'un web-service de rendu soit défini pour le fichier en question.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Il est possible de mettre <code>-t</code> en majuscule. Dans ce cas :</p>\n<ul>\n<li>s'il y a une ou plusieurs opérations de réécriture, le résultat de la dernière réécriture remplace le contenu de la cellule et la sortie est effacée ;</li>\n<li>sinon, s'il y a une ou plusieurs opérations de conversion et que <a href=\"https://github.com/asweigart/pyperclip\">Pyperclip</a> est installé, le résultat de la dernière conversion est copié dans le presse-papier.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h2 id=\"Gabarits-de-passage-au-relationnel\">Gabarits de passage au relationnel<a class=\"anchor-link\" href=\"#Gabarits-de-passage-au-relationnel\">¶</a></h2>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>L'algorithme convertissant la représentation interne d'un schéma relationnel en une représentation externe dans tel ou tel format est totalement découplé dudit format. Cela signifie que vous pouvez modifier ou créer un format sans écrire une seule ligne de code, mais en remplissant une espèce de formulaire, ou gabarit (<em>template</em> en anglais).</p>\n<p>Si vous n'avez aucune velléité de le faire ou que vous n'êtes pas ami avec les expressions régulières, vous pouvez sauter cette section. Sinon, accrochez-vous, ça va devenir un peu technique.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Format-des-gabarits\">Format des gabarits<a class=\"anchor-link\" href=\"#Format-des-gabarits\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les gabarits de Mocodo étaient à l'origine écrits en JSON. Par conséquent, un grand nombre des caractères utilisés dans les expressions régulières devaient être échappés, ce qui rendait celles-ci (encore) plus difficiles à écrire, à relire et à tester. La version 4 passe à YAML, qui n'a pas cet inconvénient. Voici par exemple un extrait de gabarit dans l'ancienne syntaxe :</p>\n<div class=\"highlight\"><pre><span></span><span class=\"w\">    </span><span class=\"p\">{</span>\n<span class=\"w\">      </span><span class=\"nt\">\"order\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"mi\">400</span><span class=\"p\">,</span>\n<span class=\"w\">      </span><span class=\"nt\">\"comment\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s2\">\"Move all foreign keys constraints at the end of the document\"</span><span class=\"p\">,</span>\n<span class=\"w\">      </span><span class=\"nt\">\"search\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s2\">\"(?sm)(CREATE TABLE ([^\\n]+) \\\\(\\n(?:[^\\n]+\\n)*)  (FOREIGN KEY[^\\n]+),\\n(.*)\"</span><span class=\"p\">,</span>\n<span class=\"w\">      </span><span class=\"nt\">\"replace\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s2\">\"\\\\1\\\\4\\nALTER TABLE \\\\2 ADD \\\\3;\"</span><span class=\"p\">,</span>\n<span class=\"w\">      </span><span class=\"nt\">\"iterated\"</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"kc\">true</span>\n<span class=\"w\">    </span><span class=\"p\">},</span>\n</pre></div>\n<p>... et le même dans la nouvelle :</p>\n<div class=\"highlight\"><pre><span></span><span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">400</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Move</span><span class=\"nv\"> </span><span class=\"s\">all</span><span class=\"nv\"> </span><span class=\"s\">foreign</span><span class=\"nv\"> </span><span class=\"s\">keys</span><span class=\"nv\"> </span><span class=\"s\">constraints</span><span class=\"nv\"> </span><span class=\"s\">at</span><span class=\"nv\"> </span><span class=\"s\">the</span><span class=\"nv\"> </span><span class=\"s\">end</span><span class=\"nv\"> </span><span class=\"s\">of</span><span class=\"nv\"> </span><span class=\"s\">the</span><span class=\"nv\"> </span><span class=\"s\">document'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'(?sm)(CREATE</span><span class=\"nv\"> </span><span class=\"s\">TABLE</span><span class=\"nv\"> </span><span class=\"s\">([^\\n]+)</span><span class=\"nv\"> </span><span class=\"s\">\\(\\n(?:[^\\n]+\\n)*)</span><span class=\"nv\">  </span><span class=\"s\">(FOREIGN</span><span class=\"nv\"> </span><span class=\"s\">KEY[^\\n]+),\\n(.*)'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\1\\4\\nALTER</span><span class=\"nv\"> </span><span class=\"s\">TABLE</span><span class=\"nv\"> </span><span class=\"s\">\\2</span><span class=\"nv\"> </span><span class=\"s\">ADD</span><span class=\"nv\"> </span><span class=\"s\">\\3;'</span>\n<span class=\"w\">    </span><span class=\"nt\">iterated</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">true</span>\n</pre></div>\n<p>Si vous avez écrit vos propres gabarits JSON, vous pouvez les convertir automatiquement en YAML à l'aide du script <code>json_to_yaml_templates.py</code> fourni dans le répertoire <code>dev</code>.</p>\n<p><strong>Remarque.</strong> Si les gabarits de Mocodo constituent des fichiers YAML valides, l'inverse n'est pas forcément vrai. Mocodo utilise un sous-ensemble sain de YAML adapté à ses besoins. Il a son propre <em>parser</em> avec les particularités suivantes :</p>\n<ul>\n<li>Un gabarit est un dictionnaire dont les valeurs sont :<ul>\n<li>soit des types scalaires (chaînes, nombres, booléens, <code>null</code>) ;</li>\n<li>soit des listes de dictionnaires à valeurs scalaires.</li>\n</ul>\n</li>\n<li>Toute <em>valeur</em> chaîne doit être délimitée par des simples quotes (<code>'</code>). Les quotes internes sont échappées en les doublant (<code>''</code>).</li>\n<li>Les expressions régulières de recherche et de remplacement suivent les mêmes règles d'échappement que les r-strings de Python.</li>\n<li>Les autres chaînes (notamment les chaînes de composition) ne demandent pas à échapper les anti-slashes, mais à doubler les accolades (règles des fr-strings). Exception : pour les distinguer du retour-chariot et de la tabulation, il faudra échapper les <code>\\n</code> et les <code>\\t</code> si on veut les laisser littéralement. Vous en avez un exemple pour <code>\\newcommand</code> et <code>\\title</code> dans le <a href=\"https://github.com/laowantong/mocodo/blob/53ba0fce41aaf7b8156821a50dd3d3f1051f8af0/mocodo/resources/relation_templates/latex-bce.yaml#L2\"><em>boilerplate</em> du gabarit pour $\\LaTeX$</a>.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"D%C3%A9rivation-de-gabarits\">Dérivation de gabarits<a class=\"anchor-link\" href=\"#D%C3%A9rivation-de-gabarits\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Depuis la version 3.1, il est possible de définir un gabarit dérivé d'un autre (qui lui-même peut dériver d'un autre, etc.). Dans le but de réduire les redondances et de faciliter les tests et la maintenance, la version 4.0 fait un usage intensif de cette fonctionnalité :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [188]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">SVG</span><span class=\"p\">(</span><span class=\"s2\">\"../../mocodo/resources/relation_templates/_graph.svg\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[188]:</div>\n<div class=\"jp-RenderedSVG jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"image/svg+xml\" tabindex=\"0\">\n<img alt=\"No description has been provided for this image\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iNzM4cHQiIGhlaWdodD0iMTg1M3B0IiB2aWV3Qm94PSIwLjAwIDAuMDAgNzM3Ljc1IDE4NTMuMDAiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTg0OSkiPgo8dGl0bGU+RzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTg0OSA3MzMuNzUsLTE4NDkgNzMzLjc1LDQgLTQsNCIvPgo8IS0tIGQyIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPmQyPC90aXRsZT4KPHBhdGggZmlsbD0iIzY3MDAwZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjUsLTM2QzY1LC0zNiAzNSwtMzYgMzUsLTM2IDI5LC0zNiAyMywtMzAgMjMsLTI0IDIzLC0yNCAyMywtMTIgMjMsLTEyIDIzLC02IDI5LDAgMzUsMCAzNSwwIDY1LDAgNjUsMCA3MSwwIDc3LC02IDc3LC0xMiA3NywtMTIgNzcsLTI0IDc3LC0yNCA3NywtMzAgNzEsLTM2IDY1LC0zNiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1MCIgeT0iLTEyLjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5kMjwvdGV4dD4KPC9nPgo8IS0tIGRibWwgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+ZGJtbDwvdGl0bGU+CjxwYXRoIGZpbGw9IiM2NzAwMGQiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTY1LC05MEM2NSwtOTAgMzUsLTkwIDM1LC05MCAyOSwtOTAgMjMsLTg0IDIzLC03OCAyMywtNzggMjMsLTY2IDIzLC02NiAyMywtNjAgMjksLTU0IDM1LC01NCAzNSwtNTQgNjUsLTU0IDY1LC01NCA3MSwtNTQgNzcsLTYwIDc3LC02NiA3NywtNjYgNzcsLTc4IDc3LC03OCA3NywtODQgNzEsLTkwIDY1LC05MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1MCIgeT0iLTY2LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5kYm1sPC90ZXh0Pgo8L2c+CjwhLS0gZGJtbCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5kYm1sLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmVlMGQyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0xOTguMTIsLTkwQzE5OC4xMiwtOTAgMTY0LjEyLC05MCAxNjQuMTIsLTkwIDE1OC4xMiwtOTAgMTUyLjEyLC04NCAxNTIuMTIsLTc4IDE1Mi4xMiwtNzggMTUyLjEyLC02NiAxNTIuMTIsLTY2IDE1Mi4xMiwtNjAgMTU4LjEyLC01NCAxNjQuMTIsLTU0IDE2NC4xMiwtNTQgMTk4LjEyLC01NCAxOTguMTIsLTU0IDIwNC4xMiwtNTQgMjEwLjEyLC02MCAyMTAuMTIsLTY2IDIxMC4xMiwtNjYgMjEwLjEyLC03OCAyMTAuMTIsLTc4IDIxMC4xMiwtODQgMjA0LjEyLC05MCAxOTguMTIsLTkwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4MS4xMiIgeT0iLTY2LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmRibWwtYjwvdGV4dD4KPC9nPgo8IS0tIGRibWwmIzQ1OyZndDtkYm1sJiM0NTtiIC0tPgo8ZyBpZD0iZWRnZTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPmRibWwtJmd0O2RibWwtYjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik04OC4zLC03MkMxMDguODEsLTcyIDEzMy44MywtNzIgMTUyLjU2LC03MiIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4OC4zMywtNjguNSA3OC4zMywtNzIgODguMzMsLTc1LjUgODguMzMsLTY4LjUiLz4KPC9nPgo8IS0tIHNxbCAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5zcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSIjNjcwMDBkIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02NSwtMzYwQzY1LC0zNjAgMzUsLTM2MCAzNSwtMzYwIDI5LC0zNjAgMjMsLTM1NCAyMywtMzQ4IDIzLC0zNDggMjMsLTMzNiAyMywtMzM2IDIzLC0zMzAgMjksLTMyNCAzNSwtMzI0IDM1LC0zMjQgNjUsLTMyNCA2NSwtMzI0IDcxLC0zMjQgNzcsLTMzMCA3NywtMzM2IDc3LC0zMzYgNzcsLTM0OCA3NywtMzQ4IDc3LC0zNTQgNzEsLTM2MCA2NSwtMzYwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjUwIiB5PSItMzM2LjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5zcWw8L3RleHQ+CjwvZz4KPCEtLSBkZGwgLS0+CjxnIGlkPSJub2RlNSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+ZGRsPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMTk2LjEyLC01MjJDMTk2LjEyLC01MjIgMTY2LjEyLC01MjIgMTY2LjEyLC01MjIgMTYwLjEyLC01MjIgMTU0LjEyLC01MTYgMTU0LjEyLC01MTAgMTU0LjEyLC01MTAgMTU0LjEyLC00OTggMTU0LjEyLC00OTggMTU0LjEyLC00OTIgMTYwLjEyLC00ODYgMTY2LjEyLC00ODYgMTY2LjEyLC00ODYgMTk2LjEyLC00ODYgMTk2LjEyLC00ODYgMjAyLjEyLC00ODYgMjA4LjEyLC00OTIgMjA4LjEyLC00OTggMjA4LjEyLC00OTggMjA4LjEyLC01MTAgMjA4LjEyLC01MTAgMjA4LjEyLC01MTYgMjAyLjEyLC01MjIgMTk2LjEyLC01MjIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItNDk4LjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmRkbDwvdGV4dD4KPC9nPgo8IS0tIHNxbCYjNDU7Jmd0O2RkbCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5zcWwtJmd0O2RkbDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik02OC45NywtMzY4Ljk2Qzc4LjM1LC0zODMuMTcgODkuOTQsLTQwMC45NCAxMDAsLTQxNyAxMTYuNTEsLTQ0My4zNiAxMTQuMTEsLTQ1NC45MSAxMzYsLTQ3NyAxNDEuMzEsLTQ4Mi4zNiAxNDcuODksLTQ4Ny4xMSAxNTQuMzMsLTQ5MS4wNyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI3Mi4xNSwtMzY3LjQyIDYzLjcxLC0zNjEuMDIgNjYuMzIsLTM3MS4yOSA3Mi4xNSwtMzY3LjQyIi8+CjwvZz4KPCEtLSBtc3NxbCAtLT4KPGcgaWQ9Im5vZGU1MiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bXNzcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZWYzYjJjIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0xOTYuMTIsLTQ2OEMxOTYuMTIsLTQ2OCAxNjYuMTIsLTQ2OCAxNjYuMTIsLTQ2OCAxNjAuMTIsLTQ2OCAxNTQuMTIsLTQ2MiAxNTQuMTIsLTQ1NiAxNTQuMTIsLTQ1NiAxNTQuMTIsLTQ0NCAxNTQuMTIsLTQ0NCAxNTQuMTIsLTQzOCAxNjAuMTIsLTQzMiAxNjYuMTIsLTQzMiAxNjYuMTIsLTQzMiAxOTYuMTIsLTQzMiAxOTYuMTIsLTQzMiAyMDIuMTIsLTQzMiAyMDguMTIsLTQzOCAyMDguMTIsLTQ0NCAyMDguMTIsLTQ0NCAyMDguMTIsLTQ1NiAyMDguMTIsLTQ1NiAyMDguMTIsLTQ2MiAyMDIuMTIsLTQ2OCAxOTYuMTIsLTQ2OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii00NDQuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0id2hpdGUiPm1zc3FsPC90ZXh0Pgo8L2c+CjwhLS0gc3FsJiM0NTsmZ3Q7bXNzcWwgLS0+CjxnIGlkPSJlZGdlNDYiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnNxbC0mZ3Q7bXNzcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNODAuOTcsLTM2Ny4wN0MxMDQuOCwtMzg3IDEzNy41NCwtNDE0LjM5IDE1OC43NywtNDMyLjE0Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjgzLjQsLTM2NC41NCA3My40OCwtMzYwLjgxIDc4LjkxLC0zNjkuOTEgODMuNCwtMzY0LjU0Ii8+CjwvZz4KPCEtLSBteXNxbCAtLT4KPGcgaWQ9Im5vZGU1NCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bXlzcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZWYzYjJjIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0xOTYuMTIsLTM4N0MxOTYuMTIsLTM4NyAxNjYuMTIsLTM4NyAxNjYuMTIsLTM4NyAxNjAuMTIsLTM4NyAxNTQuMTIsLTM4MSAxNTQuMTIsLTM3NSAxNTQuMTIsLTM3NSAxNTQuMTIsLTM2MyAxNTQuMTIsLTM2MyAxNTQuMTIsLTM1NyAxNjAuMTIsLTM1MSAxNjYuMTIsLTM1MSAxNjYuMTIsLTM1MSAxOTYuMTIsLTM1MSAxOTYuMTIsLTM1MSAyMDIuMTIsLTM1MSAyMDguMTIsLTM1NyAyMDguMTIsLTM2MyAyMDguMTIsLTM2MyAyMDguMTIsLTM3NSAyMDguMTIsLTM3NSAyMDguMTIsLTM4MSAyMDIuMTIsLTM4NyAxOTYuMTIsLTM4NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii0zNjMuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0id2hpdGUiPm15c3FsPC90ZXh0Pgo8L2c+CjwhLS0gc3FsJiM0NTsmZ3Q7bXlzcWwgLS0+CjxnIGlkPSJlZGdlNDgiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnNxbC0mZ3Q7bXlzcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNODguMDMsLTM0OS43NEMxMDkuMjUsLTM1NC4xOCAxMzUuMzYsLTM1OS42NCAxNTQuMzUsLTM2My42MSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4OC44MSwtMzQ2LjMzIDc4LjMsLTM0Ny43MSA4Ny4zNywtMzUzLjE4IDg4LjgxLC0zNDYuMzMiLz4KPC9nPgo8IS0tIG9yYWNsZSAtLT4KPGcgaWQ9Im5vZGU1NiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+b3JhY2xlPC90aXRsZT4KPHBhdGggZmlsbD0iI2VmM2IyYyIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMTk2LjEyLC0zMzNDMTk2LjEyLC0zMzMgMTY2LjEyLC0zMzMgMTY2LjEyLC0zMzMgMTYwLjEyLC0zMzMgMTU0LjEyLC0zMjcgMTU0LjEyLC0zMjEgMTU0LjEyLC0zMjEgMTU0LjEyLC0zMDkgMTU0LjEyLC0zMDkgMTU0LjEyLC0zMDMgMTYwLjEyLC0yOTcgMTY2LjEyLC0yOTcgMTY2LjEyLC0yOTcgMTk2LjEyLC0yOTcgMTk2LjEyLC0yOTcgMjAyLjEyLC0yOTcgMjA4LjEyLC0zMDMgMjA4LjEyLC0zMDkgMjA4LjEyLC0zMDkgMjA4LjEyLC0zMjEgMjA4LjEyLC0zMjEgMjA4LjEyLC0zMjcgMjAyLjEyLC0zMzMgMTk2LjEyLC0zMzMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItMzA5LjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5vcmFjbGU8L3RleHQ+CjwvZz4KPCEtLSBzcWwmIzQ1OyZndDtvcmFjbGUgLS0+CjxnIGlkPSJlZGdlNTAiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnNxbC0mZ3Q7b3JhY2xlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTg4LjAzLC0zMzQuMjZDMTA5LjI1LC0zMjkuODIgMTM1LjM2LC0zMjQuMzYgMTU0LjM1LC0zMjAuMzkiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iODcuMzcsLTMzMC44MiA3OC4zLC0zMzYuMjkgODguODEsLTMzNy42NyA4Ny4zNywtMzMwLjgyIi8+CjwvZz4KPCEtLSBwb3N0Z3Jlc3FsIC0tPgo8ZyBpZD0ibm9kZTYyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5wb3N0Z3Jlc3FsPC90aXRsZT4KPHBhdGggZmlsbD0iI2VmM2IyYyIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMjA4LjI1LC0yMjVDMjA4LjI1LC0yMjUgMTU0LC0yMjUgMTU0LC0yMjUgMTQ4LC0yMjUgMTQyLC0yMTkgMTQyLC0yMTMgMTQyLC0yMTMgMTQyLC0yMDEgMTQyLC0yMDEgMTQyLC0xOTUgMTQ4LC0xODkgMTU0LC0xODkgMTU0LC0xODkgMjA4LjI1LC0xODkgMjA4LjI1LC0xODkgMjE0LjI1LC0xODkgMjIwLjI1LC0xOTUgMjIwLjI1LC0yMDEgMjIwLjI1LC0yMDEgMjIwLjI1LC0yMTMgMjIwLjI1LC0yMTMgMjIwLjI1LC0yMTkgMjE0LjI1LC0yMjUgMjA4LjI1LC0yMjUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItMjAxLjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5wb3N0Z3Jlc3FsPC90ZXh0Pgo8L2c+CjwhLS0gc3FsJiM0NTsmZ3Q7cG9zdGdyZXNxbCAtLT4KPGcgaWQ9ImVkZ2U1NiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+c3FsLSZndDtwb3N0Z3Jlc3FsPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTc1Ljk4LC0zMTUuODhDMTAxLjcsLTI4OC45OSAxNDEuMDgsLTI0Ny44MiAxNjMuMzIsLTIyNC41NyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI3My41OCwtMzEzLjMzIDY5LjE5LC0zMjIuOTggNzguNjMsLTMxOC4xNyA3My41OCwtMzEzLjMzIi8+CjwvZz4KPCEtLSBzcWxpdGUgLS0+CjxnIGlkPSJub2RlNjYiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnNxbGl0ZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNjYjE4MWQiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTE5Ni4xMiwtMTQ0QzE5Ni4xMiwtMTQ0IDE2Ni4xMiwtMTQ0IDE2Ni4xMiwtMTQ0IDE2MC4xMiwtMTQ0IDE1NC4xMiwtMTM4IDE1NC4xMiwtMTMyIDE1NC4xMiwtMTMyIDE1NC4xMiwtMTIwIDE1NC4xMiwtMTIwIDE1NC4xMiwtMTE0IDE2MC4xMiwtMTA4IDE2Ni4xMiwtMTA4IDE2Ni4xMiwtMTA4IDE5Ni4xMiwtMTA4IDE5Ni4xMiwtMTA4IDIwMi4xMiwtMTA4IDIwOC4xMiwtMTE0IDIwOC4xMiwtMTIwIDIwOC4xMiwtMTIwIDIwOC4xMiwtMTMyIDIwOC4xMiwtMTMyIDIwOC4xMiwtMTM4IDIwMi4xMiwtMTQ0IDE5Ni4xMiwtMTQ0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4MS4xMiIgeT0iLTEyMC41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSJ3aGl0ZSI+c3FsaXRlPC90ZXh0Pgo8L2c+CjwhLS0gc3FsJiM0NTsmZ3Q7c3FsaXRlIC0tPgo8ZyBpZD0iZWRnZTYwIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5zcWwtJmd0O3NxbGl0ZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik02My41NSwtMzE0LjA1Qzc4Ljg3LC0yODAuOTcgMTA2LjQxLC0yMjQuNzUgMTM2LC0xODAgMTQ0LjQxLC0xNjcuMjcgMTU1LjIzLC0xNTMuOTkgMTY0LjA1LC0xNDMuNzkiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNjAuNDUsLTMxMi40IDU5LjQ3LC0zMjIuOTUgNjYuODEsLTMxNS4zMiA2MC40NSwtMzEyLjQiLz4KPC9nPgo8IS0tIGRlYnVnIC0tPgo8ZyBpZD0ibm9kZTYiIGNsYXNzPSJub2RlIj4KPHRpdGxlPmRlYnVnPC90aXRsZT4KPHBhdGggZmlsbD0iIzY3MDAwZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjUsLTQ2MkM2NSwtNDYyIDM1LC00NjIgMzUsLTQ2MiAyOSwtNDYyIDIzLC00NTYgMjMsLTQ1MCAyMywtNDUwIDIzLC00MzggMjMsLTQzOCAyMywtNDMyIDI5LC00MjYgMzUsLTQyNiAzNSwtNDI2IDY1LC00MjYgNjUsLTQyNiA3MSwtNDI2IDc3LC00MzIgNzcsLTQzOCA3NywtNDM4IDc3LC00NTAgNzcsLTQ1MCA3NywtNDU2IDcxLC00NjIgNjUsLTQ2MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1MCIgeT0iLTQzOC41NyIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSJ3aGl0ZSI+ZGVidWc8L3RleHQ+CjwvZz4KPCEtLSBkZXBlbmRlbmNpZXMgLS0+CjxnIGlkPSJub2RlNyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+ZGVwZW5kZW5jaWVzPC90aXRsZT4KPHBhdGggZmlsbD0iIzY3MDAwZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNODgsLTU1NkM4OCwtNTU2IDEyLC01NTYgMTIsLTU1NiA2LC01NTYgMCwtNTUwIDAsLTU0NCAwLC01NDQgMCwtNTMyIDAsLTUzMiAwLC01MjYgNiwtNTIwIDEyLC01MjAgMTIsLTUyMCA4OCwtNTIwIDg4LC01MjAgOTQsLTUyMCAxMDAsLTUyNiAxMDAsLTUzMiAxMDAsLTUzMiAxMDAsLTU0NCAxMDAsLTU0NCAxMDAsLTU1MCA5NCwtNTU2IDg4LC01NTYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTAiIHk9Ii01MzIuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0id2hpdGUiPmRlcGVuZGVuY2llczwvdGV4dD4KPC9nPgo8IS0tIGRpYWdyYW0mIzQ1O2MgLS0+CjxnIGlkPSJub2RlOCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+ZGlhZ3JhbS1jPC90aXRsZT4KPHBhdGggZmlsbD0iIzY3MDAwZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNzYuMzgsLTYzMEM3Ni4zOCwtNjMwIDIzLjYyLC02MzAgMjMuNjIsLTYzMCAxNy42MywtNjMwIDExLjYyLC02MjQgMTEuNjIsLTYxOCAxMS42MiwtNjE4IDExLjYyLC02MDYgMTEuNjIsLTYwNiAxMS42MiwtNjAwIDE3LjYyLC01OTQgMjMuNjIsLTU5NCAyMy42MiwtNTk0IDc2LjM4LC01OTQgNzYuMzgsLTU5NCA4Mi4zOCwtNTk0IDg4LjM4LC02MDAgODguMzgsLTYwNiA4OC4zOCwtNjA2IDg4LjM4LC02MTggODguMzgsLTYxOCA4OC4zOCwtNjI0IDgyLjM4LC02MzAgNzYuMzgsLTYzMCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1MCIgeT0iLTYwNi41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSJ3aGl0ZSI+ZGlhZ3JhbS1jPC90ZXh0Pgo8L2c+CjwhLS0gZGlhZ3JhbSAtLT4KPGcgaWQ9Im5vZGU5IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5kaWFncmFtPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjYmJhMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMjAxLjg4LC02MzBDMjAxLjg4LC02MzAgMTYwLjM4LC02MzAgMTYwLjM4LC02MzAgMTU0LjM4LC02MzAgMTQ4LjM4LC02MjQgMTQ4LjM4LC02MTggMTQ4LjM4LC02MTggMTQ4LjM4LC02MDYgMTQ4LjM4LC02MDYgMTQ4LjM4LC02MDAgMTU0LjM4LC01OTQgMTYwLjM4LC01OTQgMTYwLjM4LC01OTQgMjAxLjg4LC01OTQgMjAxLjg4LC01OTQgMjA3Ljg4LC01OTQgMjEzLjg4LC02MDAgMjEzLjg4LC02MDYgMjEzLjg4LC02MDYgMjEzLjg4LC02MTggMjEzLjg4LC02MTggMjEzLjg4LC02MjQgMjA3Ljg4LC02MzAgMjAxLjg4LC02MzAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItNjA2LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmRpYWdyYW08L3RleHQ+CjwvZz4KPCEtLSBkaWFncmFtJiM0NTtjJiM0NTsmZ3Q7ZGlhZ3JhbSAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5kaWFncmFtLWMtJmd0O2RpYWdyYW08L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNOTkuNDMsLTYxMkMxMTUuODUsLTYxMiAxMzMuNzcsLTYxMiAxNDguNTQsLTYxMiIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI5OS44NiwtNjA4LjUgODkuODYsLTYxMiA5OS44NiwtNjE1LjUgOTkuODYsLTYwOC41Ii8+CjwvZz4KPCEtLSBodG1sJiM0NTtiYyAtLT4KPGcgaWQ9Im5vZGUxMCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+aHRtbC1iYzwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZWUwZDIiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTE5OS42MiwtMTc2NEMxOTkuNjIsLTE3NjQgMTYyLjYyLC0xNzY0IDE2Mi42MiwtMTc2NCAxNTYuNjIsLTE3NjQgMTUwLjYyLC0xNzU4IDE1MC42MiwtMTc1MiAxNTAuNjIsLTE3NTIgMTUwLjYyLC0xNzQwIDE1MC42MiwtMTc0MCAxNTAuNjIsLTE3MzQgMTU2LjYyLC0xNzI4IDE2Mi42MiwtMTcyOCAxNjIuNjIsLTE3MjggMTk5LjYyLC0xNzI4IDE5OS42MiwtMTcyOCAyMDUuNjIsLTE3MjggMjExLjYyLC0xNzM0IDIxMS42MiwtMTc0MCAyMTEuNjIsLTE3NDAgMjExLjYyLC0xNzUyIDIxMS42MiwtMTc1MiAyMTEuNjIsLTE3NTggMjA1LjYyLC0xNzY0IDE5OS42MiwtMTc2NCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii0xNzQwLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmh0bWwtYmM8L3RleHQ+CjwvZz4KPCEtLSBodG1sJiM0NTtiIC0tPgo8ZyBpZD0ibm9kZTExIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5odG1sLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMjUsLTE4MThDMzI2LjI1LC0xODE4IDI5NiwtMTgxOCAyOTYsLTE4MTggMjkwLC0xODE4IDI4NCwtMTgxMiAyODQsLTE4MDYgMjg0LC0xODA2IDI4NCwtMTc5NCAyODQsLTE3OTQgMjg0LC0xNzg4IDI5MCwtMTc4MiAyOTYsLTE3ODIgMjk2LC0xNzgyIDMyNi4yNSwtMTc4MiAzMjYuMjUsLTE3ODIgMzMyLjI1LC0xNzgyIDMzOC4yNSwtMTc4OCAzMzguMjUsLTE3OTQgMzM4LjI1LC0xNzk0IDMzOC4yNSwtMTgwNiAzMzguMjUsLTE4MDYgMzM4LjI1LC0xODEyIDMzMi4yNSwtMTgxOCAzMjYuMjUsLTE4MTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMTc5NC41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5odG1sLWI8L3RleHQ+CjwvZz4KPCEtLSBodG1sJiM0NTtiYyYjNDU7Jmd0O2h0bWwmIzQ1O2IgLS0+CjxnIGlkPSJlZGdlNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+aHRtbC1iYy0mZ3Q7aHRtbC1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIyMi4wMywtMTc2Mi44M0MyNDIuMzYsLTE3NzEuNDEgMjY2LjUsLTE3ODEuNiAyODQuMzYsLTE3ODkuMTMiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjIzLjQ2LC0xNzU5LjY0IDIxMi44OSwtMTc1OC45OCAyMjAuNzQsLTE3NjYuMDkgMjIzLjQ2LC0xNzU5LjY0Ii8+CjwvZz4KPCEtLSBodG1sJiM0NTtjIC0tPgo8ZyBpZD0ibm9kZTEyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5odG1sLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjNjcwMDBkIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02NSwtMTE3MEM2NSwtMTE3MCAzNSwtMTE3MCAzNSwtMTE3MCAyOSwtMTE3MCAyMywtMTE2NCAyMywtMTE1OCAyMywtMTE1OCAyMywtMTE0NiAyMywtMTE0NiAyMywtMTE0MCAyOSwtMTEzNCAzNSwtMTEzNCAzNSwtMTEzNCA2NSwtMTEzNCA2NSwtMTEzNCA3MSwtMTEzNCA3NywtMTE0MCA3NywtMTE0NiA3NywtMTE0NiA3NywtMTE1OCA3NywtMTE1OCA3NywtMTE2NCA3MSwtMTE3MCA2NSwtMTE3MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1MCIgeT0iLTExNDYuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0id2hpdGUiPmh0bWwtYzwvdGV4dD4KPC9nPgo8IS0tIGh0bWwmIzQ1O2MmIzQ1OyZndDtodG1sJiM0NTtiYyAtLT4KPGcgaWQ9ImVkZ2U1IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWMtJmd0O2h0bWwtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNTMuODcsLTExODAuOTlDNjEuODgsLTEyNTcuMTEgODcuMTYsLTE0NjguNDYgMTM2LC0xNjM4IDE0NS40MiwtMTY3MC43IDE2MS40OCwtMTcwNi45OSAxNzEuNDEsLTE3MjguMDgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTcuNCwtMTE4MS4wNiA1Mi44OSwtMTE3MS40NyA1MC40NCwtMTE4MS43OCA1Ny40LC0xMTgxLjA2Ii8+CjwvZz4KPCEtLSBodG1sJiM0NTtjZSAtLT4KPGcgaWQ9Im5vZGUxMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+aHRtbC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiM2NzAwMGQiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTE5OS42MiwtMTYyOUMxOTkuNjIsLTE2MjkgMTYyLjYyLC0xNjI5IDE2Mi42MiwtMTYyOSAxNTYuNjIsLTE2MjkgMTUwLjYyLC0xNjIzIDE1MC42MiwtMTYxNyAxNTAuNjIsLTE2MTcgMTUwLjYyLC0xNjA1IDE1MC42MiwtMTYwNSAxNTAuNjIsLTE1OTkgMTU2LjYyLC0xNTkzIDE2Mi42MiwtMTU5MyAxNjIuNjIsLTE1OTMgMTk5LjYyLC0xNTkzIDE5OS42MiwtMTU5MyAyMDUuNjIsLTE1OTMgMjExLjYyLC0xNTk5IDIxMS42MiwtMTYwNSAyMTEuNjIsLTE2MDUgMjExLjYyLC0xNjE3IDIxMS42MiwtMTYxNyAyMTEuNjIsLTE2MjMgMjA1LjYyLC0xNjI5IDE5OS42MiwtMTYyOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii0xNjA1LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5odG1sLWNlPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7YyYjNDU7Jmd0O2h0bWwmIzQ1O2NlIC0tPgo8ZyBpZD0iZWRnZTgiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPmh0bWwtYy0mZ3Q7aHRtbC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01OS4xMSwtMTE4MC44MkM4My40NCwtMTI2Ny4zMyAxNTUuNDEsLTE1MjMuMTUgMTc1LjEsLTE1OTMuMTMiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNjIuNTUsLTExODAuMTMgNTYuNDcsLTExNzEuNDUgNTUuODEsLTExODIuMDIgNjIuNTUsLTExODAuMTMiLz4KPC9nPgo8IS0tIGh0bWwgLS0+CjxnIGlkPSJub2RlMTciIGNsYXNzPSJub2RlIj4KPHRpdGxlPmh0bWw8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmM5MjcyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0xOTYuMTIsLTExOTdDMTk2LjEyLC0xMTk3IDE2Ni4xMiwtMTE5NyAxNjYuMTIsLTExOTcgMTYwLjEyLC0xMTk3IDE1NC4xMiwtMTE5MSAxNTQuMTIsLTExODUgMTU0LjEyLC0xMTg1IDE1NC4xMiwtMTE3MyAxNTQuMTIsLTExNzMgMTU0LjEyLC0xMTY3IDE2MC4xMiwtMTE2MSAxNjYuMTIsLTExNjEgMTY2LjEyLC0xMTYxIDE5Ni4xMiwtMTE2MSAxOTYuMTIsLTExNjEgMjAyLjEyLC0xMTYxIDIwOC4xMiwtMTE2NyAyMDguMTIsLTExNzMgMjA4LjEyLC0xMTczIDIwOC4xMiwtMTE4NSAyMDguMTIsLTExODUgMjA4LjEyLC0xMTkxIDIwMi4xMiwtMTE5NyAxOTYuMTIsLTExOTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItMTE3My41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5odG1sPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7YyYjNDU7Jmd0O2h0bWwgLS0+CjxnIGlkPSJlZGdlMTAiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPmh0bWwtYy0mZ3Q7aHRtbDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik04OC4wMywtMTE1OS43NEMxMDkuMjUsLTExNjQuMTggMTM1LjM2LC0xMTY5LjY0IDE1NC4zNSwtMTE3My42MSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4OC44MSwtMTE1Ni4zMyA3OC4zLC0xMTU3LjcxIDg3LjM3LC0xMTYzLjE4IDg4LjgxLC0xMTU2LjMzIi8+CjwvZz4KPCEtLSBsYXRleCYjNDU7YyAtLT4KPGcgaWQ9Im5vZGUyMCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bGF0ZXgtYzwvdGl0bGU+CjxwYXRoIGZpbGw9IiNjYjE4MWQiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTE5NywtMTE0M0MxOTcsLTExNDMgMTY1LjI1LC0xMTQzIDE2NS4yNSwtMTE0MyAxNTkuMjUsLTExNDMgMTUzLjI1LC0xMTM3IDE1My4yNSwtMTEzMSAxNTMuMjUsLTExMzEgMTUzLjI1LC0xMTE5IDE1My4yNSwtMTExOSAxNTMuMjUsLTExMTMgMTU5LjI1LC0xMTA3IDE2NS4yNSwtMTEwNyAxNjUuMjUsLTExMDcgMTk3LC0xMTA3IDE5NywtMTEwNyAyMDMsLTExMDcgMjA5LC0xMTEzIDIwOSwtMTExOSAyMDksLTExMTkgMjA5LC0xMTMxIDIwOSwtMTEzMSAyMDksLTExMzcgMjAzLC0xMTQzIDE5NywtMTE0MyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii0xMTE5LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5sYXRleC1jPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7YyYjNDU7Jmd0O2xhdGV4JiM0NTtjIC0tPgo8ZyBpZD0iZWRnZTE1IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWMtJmd0O2xhdGV4LWM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNODcuODgsLTExNDQuMjlDMTA4LjgsLTExMzkuOTEgMTM0LjUsLTExMzQuNTQgMTUzLjQ2LC0xMTMwLjU4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9Ijg3LjM3LC0xMTQwLjgyIDc4LjMsLTExNDYuMjkgODguODEsLTExNDcuNjcgODcuMzcsLTExNDAuODIiLz4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtjIC0tPgo8ZyBpZD0ibm9kZTI4IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tYXJrZG93bi1jPC90aXRsZT4KPHBhdGggZmlsbD0iI2NiMTgxZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMjE0LjI1LC05ODFDMjE0LjI1LC05ODEgMTQ4LC05ODEgMTQ4LC05ODEgMTQyLC05ODEgMTM2LC05NzUgMTM2LC05NjkgMTM2LC05NjkgMTM2LC05NTcgMTM2LC05NTcgMTM2LC05NTEgMTQyLC05NDUgMTQ4LC05NDUgMTQ4LC05NDUgMjE0LjI1LC05NDUgMjE0LjI1LC05NDUgMjIwLjI1LC05NDUgMjI2LjI1LC05NTEgMjI2LjI1LC05NTcgMjI2LjI1LC05NTcgMjI2LjI1LC05NjkgMjI2LjI1LC05NjkgMjI2LjI1LC05NzUgMjIwLjI1LC05ODEgMjE0LjI1LC05ODEiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgxLjEyIiB5PSItOTU3LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5tYXJrZG93bi1jPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7YyYjNDU7Jmd0O21hcmtkb3duJiM0NTtjIC0tPgo8ZyBpZD0iZWRnZTIzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWMtJmd0O21hcmtkb3duLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNjkuNjIsLTExMjQuNzRDOTYuNDUsLTEwODUuNDggMTQ1LjIzLC0xMDE0LjA4IDE2Ny45MiwtOTgwLjg3Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjY2Ljc1LC0xMTIyLjc0IDY0LC0xMTMyLjk3IDcyLjUzLC0xMTI2LjY5IDY2Ljc1LC0xMTIyLjc0Ii8+CjwvZz4KPCEtLSB0ZXh0JiM0NTtjIC0tPgo8ZyBpZD0ibm9kZTc4IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXh0LWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjNjcwMDBkIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0xOTYuMTIsLTc2NUMxOTYuMTIsLTc2NSAxNjYuMTIsLTc2NSAxNjYuMTIsLTc2NSAxNjAuMTIsLTc2NSAxNTQuMTIsLTc1OSAxNTQuMTIsLTc1MyAxNTQuMTIsLTc1MyAxNTQuMTIsLTc0MSAxNTQuMTIsLTc0MSAxNTQuMTIsLTczNSAxNjAuMTIsLTcyOSAxNjYuMTIsLTcyOSAxNjYuMTIsLTcyOSAxOTYuMTIsLTcyOSAxOTYuMTIsLTcyOSAyMDIuMTIsLTcyOSAyMDguMTIsLTczNSAyMDguMTIsLTc0MSAyMDguMTIsLTc0MSAyMDguMTIsLTc1MyAyMDguMTIsLTc1MyAyMDguMTIsLTc1OSAyMDIuMTIsLTc2NSAxOTYuMTIsLTc2NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODEuMTIiIHk9Ii03NDEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0id2hpdGUiPnRleHQtYzwvdGV4dD4KPC9nPgo8IS0tIGh0bWwmIzQ1O2MmIzQ1OyZndDt0ZXh0JiM0NTtjIC0tPgo8ZyBpZD0iZWRnZTc1IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWMtJmd0O3RleHQtYzwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik02MC4wNiwtMTEyMy41N0M4NS4wMiwtMTA0NS4zMSAxNTQuMjEsLTgyOC4yOSAxNzQuNDgsLTc2NC43MiIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI1Ni44OCwtMTEyMi4wNCA1Ny4xNywtMTEzMi42MyA2My41NSwtMTEyNC4xNyA1Ni44OCwtMTEyMi4wNCIvPgo8L2c+CjwhLS0gaHRtbCYjNDU7YmNlIC0tPgo8ZyBpZD0ibm9kZTE0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5odG1sLWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZWUwZDIiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMzMy4zOCwtMTc2NEMzMzMuMzgsLTE3NjQgMjg4Ljg4LC0xNzY0IDI4OC44OCwtMTc2NCAyODIuODgsLTE3NjQgMjc2Ljg4LC0xNzU4IDI3Ni44OCwtMTc1MiAyNzYuODgsLTE3NTIgMjc2Ljg4LC0xNzQwIDI3Ni44OCwtMTc0MCAyNzYuODgsLTE3MzQgMjgyLjg4LC0xNzI4IDI4OC44OCwtMTcyOCAyODguODgsLTE3MjggMzMzLjM4LC0xNzI4IDMzMy4zOCwtMTcyOCAzMzkuMzgsLTE3MjggMzQ1LjM4LC0xNzM0IDM0NS4zOCwtMTc0MCAzNDUuMzgsLTE3NDAgMzQ1LjM4LC0xNzUyIDM0NS4zOCwtMTc1MiAzNDUuMzgsLTE3NTggMzM5LjM4LC0xNzY0IDMzMy4zOCwtMTc2NCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii0xNzQwLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmh0bWwtYmNlPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7Y2UmIzQ1OyZndDtodG1sJiM0NTtiY2UgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+aHRtbC1jZS0mZ3Q7aHRtbC1iY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMTk4LC0xNjM4LjU2QzIxMi41MSwtMTY2Mi4wNCAyMzUuNzIsLTE2OTUuNTkgMjYyLjI1LC0xNzE5IDI2Ni42OSwtMTcyMi45MSAyNzEuNzgsLTE3MjYuNTIgMjc2Ljk2LC0xNzI5LjczIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwMS4wOSwtMTYzNi45MiAxOTIuOTMsLTE2MzAuMTcgMTk1LjEsLTE2NDAuNTQgMjAxLjA5LC0xNjM2LjkyIi8+CjwvZz4KPCEtLSBodG1sJiM0NTtlIC0tPgo8ZyBpZD0ibm9kZTE2IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5odG1sLWU8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMjUsLTE3MTBDMzI2LjI1LC0xNzEwIDI5NiwtMTcxMCAyOTYsLTE3MTAgMjkwLC0xNzEwIDI4NCwtMTcwNCAyODQsLTE2OTggMjg0LC0xNjk4IDI4NCwtMTY4NiAyODQsLTE2ODYgMjg0LC0xNjgwIDI5MCwtMTY3NCAyOTYsLTE2NzQgMjk2LC0xNjc0IDMyNi4yNSwtMTY3NCAzMjYuMjUsLTE2NzQgMzMyLjI1LC0xNjc0IDMzOC4yNSwtMTY4MCAzMzguMjUsLTE2ODYgMzM4LjI1LC0xNjg2IDMzOC4yNSwtMTY5OCAzMzguMjUsLTE2OTggMzM4LjI1LC0xNzA0IDMzMi4yNSwtMTcxMCAzMjYuMjUsLTE3MTAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMTY4Ni41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5odG1sLWU8L3RleHQ+CjwvZz4KPCEtLSBodG1sJiM0NTtjZSYjNDU7Jmd0O2h0bWwmIzQ1O2UgLS0+CjxnIGlkPSJlZGdlOSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+aHRtbC1jZS0mZ3Q7aHRtbC1lPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIxNi42NiwtMTYzNS4xNUMyMzAuNjUsLTE2NDQuNyAyNDcuMDYsLTE2NTUuNjIgMjYyLjI1LC0xNjY1IDI2OS4yMywtMTY2OS4zMSAyNzYuOTMsLTE2NzMuNzcgMjg0LjA3LC0xNjc3LjgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjE4Ljg4LC0xNjMyLjQzIDIwOC42NSwtMTYyOS42NSAyMTQuOTEsLTE2MzguMiAyMTguODgsLTE2MzIuNDMiLz4KPC9nPgo8IS0tIGxhdGV4JiM0NTtjZSAtLT4KPGcgaWQ9Im5vZGUyMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bGF0ZXgtY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSIjYTUwZjE1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMzAuNzUsLTE2NTZDMzMwLjc1LC0xNjU2IDI5MS41LC0xNjU2IDI5MS41LC0xNjU2IDI4NS41LC0xNjU2IDI3OS41LC0xNjUwIDI3OS41LC0xNjQ0IDI3OS41LC0xNjQ0IDI3OS41LC0xNjMyIDI3OS41LC0xNjMyIDI3OS41LC0xNjI2IDI4NS41LC0xNjIwIDI5MS41LC0xNjIwIDI5MS41LC0xNjIwIDMzMC43NSwtMTYyMCAzMzAuNzUsLTE2MjAgMzM2Ljc1LC0xNjIwIDM0Mi43NSwtMTYyNiAzNDIuNzUsLTE2MzIgMzQyLjc1LC0xNjMyIDM0Mi43NSwtMTY0NCAzNDIuNzUsLTE2NDQgMzQyLjc1LC0xNjUwIDMzNi43NSwtMTY1NiAzMzAuNzUsLTE2NTYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMTYzMi41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSJ3aGl0ZSI+bGF0ZXgtY2U8L3RleHQ+CjwvZz4KPCEtLSBodG1sJiM0NTtjZSYjNDU7Jmd0O2xhdGV4JiM0NTtjZSAtLT4KPGcgaWQ9ImVkZ2UxNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+aHRtbC1jZS0mZ3Q7bGF0ZXgtY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjIyLjUyLC0xNjE5LjUyQzI0MC45OCwtMTYyMy40MSAyNjIuNDgsLTE2MjcuOTUgMjc5LjU2LC0xNjMxLjU1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIyMy40OCwtMTYxNi4xNSAyMTIuOTcsLTE2MTcuNTEgMjIyLjAzLC0xNjIzIDIyMy40OCwtMTYxNi4xNSIvPgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2NlIC0tPgo8ZyBpZD0ibm9kZTI5IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tYXJrZG93bi1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNhNTBmMTUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTM0OCwtMTU3NUMzNDgsLTE1NzUgMjc0LjI1LC0xNTc1IDI3NC4yNSwtMTU3NSAyNjguMjUsLTE1NzUgMjYyLjI1LC0xNTY5IDI2Mi4yNSwtMTU2MyAyNjIuMjUsLTE1NjMgMjYyLjI1LC0xNTUxIDI2Mi4yNSwtMTU1MSAyNjIuMjUsLTE1NDUgMjY4LjI1LC0xNTM5IDI3NC4yNSwtMTUzOSAyNzQuMjUsLTE1MzkgMzQ4LC0xNTM5IDM0OCwtMTUzOSAzNTQsLTE1MzkgMzYwLC0xNTQ1IDM2MCwtMTU1MSAzNjAsLTE1NTEgMzYwLC0xNTYzIDM2MCwtMTU2MyAzNjAsLTE1NjkgMzU0LC0xNTc1IDM0OCwtMTU3NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii0xNTUxLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj5tYXJrZG93bi1jZTwvdGV4dD4KPC9nPgo8IS0tIGh0bWwmIzQ1O2NlJiM0NTsmZ3Q7bWFya2Rvd24mIzQ1O2NlIC0tPgo8ZyBpZD0iZWRnZTI0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWNlLSZndDttYXJrZG93bi1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMjEuNzIsLTE1OTQuMjlDMjM2LjM0LC0xNTg4LjEzIDI1Mi45NSwtMTU4MS4xMiAyNjcuNzksLTE1NzQuODYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjIwLjc0LC0xNTkwLjkxIDIxMi44OSwtMTU5OC4wMiAyMjMuNDYsLTE1OTcuMzYgMjIwLjc0LC0xNTkwLjkxIi8+CjwvZz4KPCEtLSB0ZXh0JiM0NTtjZSAtLT4KPGcgaWQ9Im5vZGU4MSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4dC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNhNTBmMTUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMyNy4zOCwtMTM4NkMzMjcuMzgsLTEzODYgMjk0Ljg4LC0xMzg2IDI5NC44OCwtMTM4NiAyODguODgsLTEzODYgMjgyLjg4LC0xMzgwIDI4Mi44OCwtMTM3NCAyODIuODgsLTEzNzQgMjgyLjg4LC0xMzYyIDI4Mi44OCwtMTM2MiAyODIuODgsLTEzNTYgMjg4Ljg4LC0xMzUwIDI5NC44OCwtMTM1MCAyOTQuODgsLTEzNTAgMzI3LjM4LC0xMzUwIDMyNy4zOCwtMTM1MCAzMzMuMzgsLTEzNTAgMzM5LjM4LC0xMzU2IDMzOS4zOCwtMTM2MiAzMzkuMzgsLTEzNjIgMzM5LjM4LC0xMzc0IDMzOS4zOCwtMTM3NCAzMzkuMzgsLTEzODAgMzMzLjM4LC0xMzg2IDMyNy4zOCwtMTM4NiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii0xMzYyLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IndoaXRlIj50ZXh0LWNlPC90ZXh0Pgo8L2c+CjwhLS0gaHRtbCYjNDU7Y2UmIzQ1OyZndDt0ZXh0JiM0NTtjZSAtLT4KPGcgaWQ9ImVkZ2U3NiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+aHRtbC1jZS0mZ3Q7dGV4dC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xOTYuOSwtMTU4Mi45NUMyMjMuNDgsLTE1MzIuNDkgMjc4LjYzLC0xNDI3Ljc5IDMwMC43LC0xMzg1Ljg5Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE5My44MSwtMTU4MS4zMSAxOTIuMjQsLTE1OTEuNzkgMjAwLC0xNTg0LjU4IDE5My44MSwtMTU4MS4zMSIvPgo8L2c+CjwhLS0gaHRtbCYjNDU7YmUgLS0+CjxnIGlkPSJub2RlMTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPmh0bWwtYmU8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjcuNSwtMTg0NUM0NjcuNSwtMTg0NSA0MjkuNzUsLTE4NDUgNDI5Ljc1LC0xODQ1IDQyMy43NSwtMTg0NSA0MTcuNzUsLTE4MzkgNDE3Ljc1LC0xODMzIDQxNy43NSwtMTgzMyA0MTcuNzUsLTE4MjEgNDE3Ljc1LC0xODIxIDQxNy43NSwtMTgxNSA0MjMuNzUsLTE4MDkgNDI5Ljc1LC0xODA5IDQyOS43NSwtMTgwOSA0NjcuNSwtMTgwOSA0NjcuNSwtMTgwOSA0NzMuNSwtMTgwOSA0NzkuNSwtMTgxNSA0NzkuNSwtMTgyMSA0NzkuNSwtMTgyMSA0NzkuNSwtMTgzMyA0NzkuNSwtMTgzMyA0NzkuNSwtMTgzOSA0NzMuNSwtMTg0NSA0NjcuNSwtMTg0NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xODIxLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmh0bWwtYmU8L3RleHQ+CjwvZz4KPCEtLSBodG1sJiM0NTtiY2UmIzQ1OyZndDtodG1sJiM0NTtiZSAtLT4KPGcgaWQ9ImVkZ2U3IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5odG1sLWJjZS0mZ3Q7aHRtbC1iZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTUuMDIsLTE3NjkuODNDMzU2LjcyLC0xNzcwLjg4IDM1OC4zOCwtMTc3MS45NCAzNjAsLTE3NzMgMzc2Ljc1LC0xNzgzLjk0IDM3OS4wOCwtMTc4OS4zMyAzOTYsLTE4MDAgNDAyLjkzLC0xODA0LjM3IDQxMC42NCwtMTgwOC42OCA0MTcuOTUsLTE4MTIuNTMiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMzU2Ljg0LC0xNzY2LjgzIDM0Ni40NywtMTc2NC42NyAzNTMuMjMsLTE3NzIuODMgMzU2Ljg0LC0xNzY2LjgzIi8+CjwvZz4KPCEtLSBsYXRleCYjNDU7YmMgLS0+CjxnIGlkPSJub2RlMTgiIGNsYXNzPSJub2RlIj4KPHRpdGxlPmxhdGV4LWJjPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZlZTBkMiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMzMwLjc1LC0xMTk3QzMzMC43NSwtMTE5NyAyOTEuNSwtMTE5NyAyOTEuNSwtMTE5NyAyODUuNSwtMTE5NyAyNzkuNSwtMTE5MSAyNzkuNSwtMTE4NSAyNzkuNSwtMTE4NSAyNzkuNSwtMTE3MyAyNzkuNSwtMTE3MyAyNzkuNSwtMTE2NyAyODUuNSwtMTE2MSAyOTEuNSwtMTE2MSAyOTEuNSwtMTE2MSAzMzAuNzUsLTExNjEgMzMwLjc1LC0xMTYxIDMzNi43NSwtMTE2MSAzNDIuNzUsLTExNjcgMzQyLjc1LC0xMTczIDM0Mi43NSwtMTE3MyAzNDIuNzUsLTExODUgMzQyLjc1LC0xMTg1IDM0Mi43NSwtMTE5MSAzMzYuNzUsLTExOTcgMzMwLjc1LC0xMTk3Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTExNzMuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bGF0ZXgtYmM8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGUxOSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bGF0ZXgtYjwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2NC44OCwtMTI1MUM0NjQuODgsLTEyNTEgNDMyLjM4LC0xMjUxIDQzMi4zOCwtMTI1MSA0MjYuMzgsLTEyNTEgNDIwLjM4LC0xMjQ1IDQyMC4zOCwtMTIzOSA0MjAuMzgsLTEyMzkgNDIwLjM4LC0xMjI3IDQyMC4zOCwtMTIyNyA0MjAuMzgsLTEyMjEgNDI2LjM4LC0xMjE1IDQzMi4zOCwtMTIxNSA0MzIuMzgsLTEyMTUgNDY0Ljg4LC0xMjE1IDQ2NC44OCwtMTIxNSA0NzAuODgsLTEyMTUgNDc2Ljg4LC0xMjIxIDQ3Ni44OCwtMTIyNyA0NzYuODgsLTEyMjcgNDc2Ljg4LC0xMjM5IDQ3Ni44OCwtMTIzOSA0NzYuODgsLTEyNDUgNDcwLjg4LC0xMjUxIDQ2NC44OCwtMTI1MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xMjI3LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPmxhdGV4LWI8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YmMmIzQ1OyZndDtsYXRleCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2UxMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtYmMtJmd0O2xhdGV4LWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzUzLjE3LC0xMTk1LjM2QzM3NS4wMSwtMTIwNC4wNiA0MDEuMjYsLTEyMTQuNTIgNDIwLjUzLC0xMjIyLjIiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMzU0LjUzLC0xMTkyLjEzIDM0My45NCwtMTE5MS42OCAzNTEuOTMsLTExOTguNjMgMzU0LjUzLC0xMTkyLjEzIi8+CjwvZz4KPCEtLSB0ZXgmIzQ1O2JjIC0tPgo8ZyBpZD0ibm9kZTcxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXgtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNjIsLTExOTdDNDYzLjYyLC0xMTk3IDQzMy42MiwtMTE5NyA0MzMuNjIsLTExOTcgNDI3LjYyLC0xMTk3IDQyMS42MiwtMTE5MSA0MjEuNjIsLTExODUgNDIxLjYyLC0xMTg1IDQyMS42MiwtMTE3MyA0MjEuNjIsLTExNzMgNDIxLjYyLC0xMTY3IDQyNy42MiwtMTE2MSA0MzMuNjIsLTExNjEgNDMzLjYyLC0xMTYxIDQ2My42MiwtMTE2MSA0NjMuNjIsLTExNjEgNDY5LjYyLC0xMTYxIDQ3NS42MiwtMTE2NyA0NzUuNjIsLTExNzMgNDc1LjYyLC0xMTczIDQ3NS42MiwtMTE4NSA0NzUuNjIsLTExODUgNDc1LjYyLC0xMTkxIDQ2OS42MiwtMTE5NyA0NjMuNjIsLTExOTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItMTE3My41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50ZXgtYmM8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YmMmIzQ1OyZndDt0ZXgmIzQ1O2JjIC0tPgo8ZyBpZD0iZWRnZTY0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5sYXRleC1iYy0mZ3Q7dGV4LWJjPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM1NCwtMTE3OUMzNzYuMTksLTExNzkgNDAyLjczLC0xMTc5IDQyMS44NywtMTE3OSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTQuMDUsLTExNzUuNSAzNDQuMDUsLTExNzkgMzU0LjA1LC0xMTgyLjUgMzU0LjA1LC0xMTc1LjUiLz4KPC9nPgo8IS0tIHRleCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU3MCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4LWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02MDEuNSwtMTI1MUM2MDEuNSwtMTI1MSA1NzEuNSwtMTI1MSA1NzEuNSwtMTI1MSA1NjUuNSwtMTI1MSA1NTkuNSwtMTI0NSA1NTkuNSwtMTIzOSA1NTkuNSwtMTIzOSA1NTkuNSwtMTIyNyA1NTkuNSwtMTIyNyA1NTkuNSwtMTIyMSA1NjUuNSwtMTIxNSA1NzEuNSwtMTIxNSA1NzEuNSwtMTIxNSA2MDEuNSwtMTIxNSA2MDEuNSwtMTIxNSA2MDcuNSwtMTIxNSA2MTMuNSwtMTIyMSA2MTMuNSwtMTIyNyA2MTMuNSwtMTIyNyA2MTMuNSwtMTIzOSA2MTMuNSwtMTIzOSA2MTMuNSwtMTI0NSA2MDcuNSwtMTI1MSA2MDEuNSwtMTI1MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTEyMjcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4LWI8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YiYjNDU7Jmd0O3RleCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U2MyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtYi0mZ3Q7dGV4LWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNDg4LjIsLTEyMzNDNTExLjEyLC0xMjMzIDUzOS41NiwtMTIzMyA1NTkuNzYsLTEyMzMiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNDg4LjMxLC0xMjI5LjUgNDc4LjMxLC0xMjMzIDQ4OC4zMSwtMTIzNi41IDQ4OC4zMSwtMTIyOS41Ii8+CjwvZz4KPCEtLSBsYXRleCYjNDU7YyYjNDU7Jmd0O2xhdGV4JiM0NTtiYyAtLT4KPGcgaWQ9ImVkZ2UxMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtYy0mZ3Q7bGF0ZXgtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE5LjQ0LC0xMTQwLjc0QzIzOC42MSwtMTE0OC44MyAyNjEuNjcsLTExNTguNTYgMjc5Ljc0LC0xMTY2LjE4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIyMC45MywtMTEzNy41NyAyMTAuMzUsLTExMzYuOTEgMjE4LjIxLC0xMTQ0LjAyIDIyMC45MywtMTEzNy41NyIvPgo8L2c+CjwhLS0gbGF0ZXggLS0+CjxnIGlkPSJub2RlMjUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPmxhdGV4PC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjOTI3MiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMzI2LjEyLC0xMTQzQzMyNi4xMiwtMTE0MyAyOTYuMTIsLTExNDMgMjk2LjEyLC0xMTQzIDI5MC4xMiwtMTE0MyAyODQuMTIsLTExMzcgMjg0LjEyLC0xMTMxIDI4NC4xMiwtMTEzMSAyODQuMTIsLTExMTkgMjg0LjEyLC0xMTE5IDI4NC4xMiwtMTExMyAyOTAuMTIsLTExMDcgMjk2LjEyLC0xMTA3IDI5Ni4xMiwtMTEwNyAzMjYuMTIsLTExMDcgMzI2LjEyLC0xMTA3IDMzMi4xMiwtMTEwNyAzMzguMTIsLTExMTMgMzM4LjEyLC0xMTE5IDMzOC4xMiwtMTExOSAzMzguMTIsLTExMzEgMzM4LjEyLC0xMTMxIDMzOC4xMiwtMTEzNyAzMzIuMTIsLTExNDMgMzI2LjEyLC0xMTQzIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTExMTkuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bGF0ZXg8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YyYjNDU7Jmd0O2xhdGV4IC0tPgo8ZyBpZD0iZWRnZTE4IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5sYXRleC1jLSZndDtsYXRleDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMjAuMjIsLTExMjVDMjQwLjg2LC0xMTI1IDI2NS44MiwtMTEyNSAyODQuMiwtMTEyNSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIyMjAuNDcsLTExMjEuNSAyMTAuNDcsLTExMjUgMjIwLjQ3LC0xMTI4LjUgMjIwLjQ3LC0xMTIxLjUiLz4KPC9nPgo8IS0tIHRleCYjNDU7YyAtLT4KPGcgaWQ9Im5vZGU3NCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4LWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTEwODlDMzI2LjEyLC0xMDg5IDI5Ni4xMiwtMTA4OSAyOTYuMTIsLTEwODkgMjkwLjEyLC0xMDg5IDI4NC4xMiwtMTA4MyAyODQuMTIsLTEwNzcgMjg0LjEyLC0xMDc3IDI4NC4xMiwtMTA2NSAyODQuMTIsLTEwNjUgMjg0LjEyLC0xMDU5IDI5MC4xMiwtMTA1MyAyOTYuMTIsLTEwNTMgMjk2LjEyLC0xMDUzIDMyNi4xMiwtMTA1MyAzMjYuMTIsLTEwNTMgMzMyLjEyLC0xMDUzIDMzOC4xMiwtMTA1OSAzMzguMTIsLTEwNjUgMzM4LjEyLC0xMDY1IDMzOC4xMiwtMTA3NyAzMzguMTIsLTEwNzcgMzM4LjEyLC0xMDgzIDMzMi4xMiwtMTA4OSAzMjYuMTIsLTEwODkiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMTA2NS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50ZXgtYzwvdGV4dD4KPC9nPgo8IS0tIGxhdGV4JiM0NTtjJiM0NTsmZ3Q7dGV4JiM0NTtjIC0tPgo8ZyBpZD0iZWRnZTY3IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5sYXRleC1jLSZndDt0ZXgtYzwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMTkuMzYsLTExMDkuMjlDMjQwLjE2LC0xMTAwLjUyIDI2NS41NywtMTA4OS44IDI4NC4yLC0xMDgxLjk0Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxOC4yMSwtMTEwNS45OCAyMTAuMzUsLTExMTMuMDkgMjIwLjkzLC0xMTEyLjQzIDIxOC4yMSwtMTEwNS45OCIvPgo8L2c+CjwhLS0gbGF0ZXgmIzQ1O2JjZSAtLT4KPGcgaWQ9Im5vZGUyMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bGF0ZXgtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZlZTBkMiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDcyLC0xNzkxQzQ3MiwtMTc5MSA0MjUuMjUsLTE3OTEgNDI1LjI1LC0xNzkxIDQxOS4yNSwtMTc5MSA0MTMuMjUsLTE3ODUgNDEzLjI1LC0xNzc5IDQxMy4yNSwtMTc3OSA0MTMuMjUsLTE3NjcgNDEzLjI1LC0xNzY3IDQxMy4yNSwtMTc2MSA0MTkuMjUsLTE3NTUgNDI1LjI1LC0xNzU1IDQyNS4yNSwtMTc1NSA0NzIsLTE3NTUgNDcyLC0xNzU1IDQ3OCwtMTc1NSA0ODQsLTE3NjEgNDg0LC0xNzY3IDQ4NCwtMTc2NyA0ODQsLTE3NzkgNDg0LC0xNzc5IDQ4NCwtMTc4NSA0NzgsLTE3OTEgNDcyLC0xNzkxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTE3NjcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bGF0ZXgtYmNlPC90ZXh0Pgo8L2c+CjwhLS0gbGF0ZXgmIzQ1O2NlJiM0NTsmZ3Q7bGF0ZXgmIzQ1O2JjZSAtLT4KPGcgaWQ9ImVkZ2UxMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtY2UtJmd0O2xhdGV4LWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTIuMTIsLTE2NTcuNzdDMzU0Ljk2LC0xNjU5Ljk5IDM1Ny42NCwtMTY2Mi40IDM2MCwtMTY2NSAzODYuNSwtMTY5NC4xNSAzNjkuMDQsLTE3MTcuMjcgMzk2LC0xNzQ2IDQwMC45MSwtMTc1MS4yNCA0MDcuMDcsLTE3NTUuNjUgNDEzLjQxLC0xNzU5LjI4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1NC4xLC0xNjU0Ljg5IDM0My44NiwtMTY1Mi4xNiAzNTAuMTcsLTE2NjAuNjggMzU0LjEsLTE2NTQuODkiLz4KPC9nPgo8IS0tIGxhdGV4JiM0NTtlIC0tPgo8ZyBpZD0ibm9kZTI0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5sYXRleC1lPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjYmJhMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDY0Ljg4LC0xNzM3QzQ2NC44OCwtMTczNyA0MzIuMzgsLTE3MzcgNDMyLjM4LC0xNzM3IDQyNi4zOCwtMTczNyA0MjAuMzgsLTE3MzEgNDIwLjM4LC0xNzI1IDQyMC4zOCwtMTcyNSA0MjAuMzgsLTE3MTMgNDIwLjM4LC0xNzEzIDQyMC4zOCwtMTcwNyA0MjYuMzgsLTE3MDEgNDMyLjM4LC0xNzAxIDQzMi4zOCwtMTcwMSA0NjQuODgsLTE3MDEgNDY0Ljg4LC0xNzAxIDQ3MC44OCwtMTcwMSA0NzYuODgsLTE3MDcgNDc2Ljg4LC0xNzEzIDQ3Ni44OCwtMTcxMyA0NzYuODgsLTE3MjUgNDc2Ljg4LC0xNzI1IDQ3Ni44OCwtMTczMSA0NzAuODgsLTE3MzcgNDY0Ljg4LC0xNzM3Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTE3MTMuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bGF0ZXgtZTwvdGV4dD4KPC9nPgo8IS0tIGxhdGV4JiM0NTtjZSYjNDU7Jmd0O2xhdGV4JiM0NTtlIC0tPgo8ZyBpZD0iZWRnZTE3IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5sYXRleC1jZS0mZ3Q7bGF0ZXgtZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTIuMjYsLTE2NjAuMTJDMzU0LjksLTE2NjEuNzMgMzU3LjUsLTE2NjMuMzcgMzYwLC0xNjY1IDM3Ni43NSwtMTY3NS45NCAzNzkuMDgsLTE2ODEuMzMgMzk2LC0xNjkyIDQwMy43OSwtMTY5Ni45MSA0MTIuNTYsLTE3MDEuNzQgNDIwLjYzLC0xNzA1LjkzIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1NC4zMSwtMTY1Ny4yNiAzNDMuOTIsLTE2NTUuMTggMzUwLjc0LC0xNjYzLjI5IDM1NC4zMSwtMTY1Ny4yNiIvPgo8L2c+CjwhLS0gdGV4JiM0NTtjZSAtLT4KPGcgaWQ9Im5vZGU3NSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4LWNlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDYzLjYyLC0xNjgzQzQ2My42MiwtMTY4MyA0MzMuNjIsLTE2ODMgNDMzLjYyLC0xNjgzIDQyNy42MiwtMTY4MyA0MjEuNjIsLTE2NzcgNDIxLjYyLC0xNjcxIDQyMS42MiwtMTY3MSA0MjEuNjIsLTE2NTkgNDIxLjYyLC0xNjU5IDQyMS42MiwtMTY1MyA0MjcuNjIsLTE2NDcgNDMzLjYyLC0xNjQ3IDQzMy42MiwtMTY0NyA0NjMuNjIsLTE2NDcgNDYzLjYyLC0xNjQ3IDQ2OS42MiwtMTY0NyA0NzUuNjIsLTE2NTMgNDc1LjYyLC0xNjU5IDQ3NS42MiwtMTY1OSA0NzUuNjIsLTE2NzEgNDc1LjYyLC0xNjcxIDQ3NS42MiwtMTY3NyA0NjkuNjIsLTE2ODMgNDYzLjYyLC0xNjgzIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTE2NTkuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4LWNlPC90ZXh0Pgo8L2c+CjwhLS0gbGF0ZXgmIzQ1O2NlJiM0NTsmZ3Q7dGV4JiM0NTtjZSAtLT4KPGcgaWQ9ImVkZ2U2OCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtY2UtJmd0O3RleC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTMuNywtMTY0Ni4yOEMzNzUuOTQsLTE2NTAuNzIgNDAyLjY0LC0xNjU2LjA0IDQyMS44NywtMTY1OS44NyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTQuNTEsLTE2NDIuODggMzQ0LjAyLC0xNjQ0LjM2IDM1My4xNCwtMTY0OS43NCAzNTQuNTEsLTE2NDIuODgiLz4KPC9nPgo8IS0tIGxhdGV4JiM0NTtiZSAtLT4KPGcgaWQ9Im5vZGUyMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bGF0ZXgtYmU8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02MDYuNSwtMTg0NUM2MDYuNSwtMTg0NSA1NjYuNSwtMTg0NSA1NjYuNSwtMTg0NSA1NjAuNSwtMTg0NSA1NTQuNSwtMTgzOSA1NTQuNSwtMTgzMyA1NTQuNSwtMTgzMyA1NTQuNSwtMTgyMSA1NTQuNSwtMTgyMSA1NTQuNSwtMTgxNSA1NjAuNSwtMTgwOSA1NjYuNSwtMTgwOSA1NjYuNSwtMTgwOSA2MDYuNSwtMTgwOSA2MDYuNSwtMTgwOSA2MTIuNSwtMTgwOSA2MTguNSwtMTgxNSA2MTguNSwtMTgyMSA2MTguNSwtMTgyMSA2MTguNSwtMTgzMyA2MTguNSwtMTgzMyA2MTguNSwtMTgzOSA2MTIuNSwtMTg0NSA2MDYuNSwtMTg0NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTE4MjEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bGF0ZXgtYmU8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7YmNlJiM0NTsmZ3Q7bGF0ZXgmIzQ1O2JlIC0tPgo8ZyBpZD0iZWRnZTE0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5sYXRleC1iY2UtJmd0O2xhdGV4LWJlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ5NC41NiwtMTc5MC44NkM1MTQuMzcsLTE3OTguNzMgNTM3LjEzLC0xODA3Ljc4IDU1NC45MywtMTgxNC44NSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0OTUuOSwtMTc4Ny42MyA0ODUuMzIsLTE3ODcuMTkgNDkzLjMyLC0xNzk0LjEzIDQ5NS45LC0xNzg3LjYzIi8+CjwvZz4KPCEtLSB0ZXgmIzQ1O2JjZSAtLT4KPGcgaWQ9Im5vZGU3MiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4LWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTYwNC42MiwtMTc5MUM2MDQuNjIsLTE3OTEgNTY4LjM4LC0xNzkxIDU2OC4zOCwtMTc5MSA1NjIuMzgsLTE3OTEgNTU2LjM4LC0xNzg1IDU1Ni4zOCwtMTc3OSA1NTYuMzgsLTE3NzkgNTU2LjM4LC0xNzY3IDU1Ni4zOCwtMTc2NyA1NTYuMzgsLTE3NjEgNTYyLjM4LC0xNzU1IDU2OC4zOCwtMTc1NSA1NjguMzgsLTE3NTUgNjA0LjYyLC0xNzU1IDYwNC42MiwtMTc1NSA2MTAuNjIsLTE3NTUgNjE2LjYyLC0xNzYxIDYxNi42MiwtMTc2NyA2MTYuNjIsLTE3NjcgNjE2LjYyLC0xNzc5IDYxNi42MiwtMTc3OSA2MTYuNjIsLTE3ODUgNjEwLjYyLC0xNzkxIDYwNC42MiwtMTc5MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTE3NjcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4LWJjZTwvdGV4dD4KPC9nPgo8IS0tIGxhdGV4JiM0NTtiY2UmIzQ1OyZndDt0ZXgmIzQ1O2JjZSAtLT4KPGcgaWQ9ImVkZ2U2NSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtYmNlLSZndDt0ZXgtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ5NS4xNiwtMTc3M0M1MTUuNTEsLTE3NzMgNTM4Ljg3LC0xNzczIDU1Ni43NCwtMTc3MyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0OTUuNDMsLTE3NjkuNSA0ODUuNDMsLTE3NzMgNDk1LjQzLC0xNzc2LjUgNDk1LjQzLC0xNzY5LjUiLz4KPC9nPgo8IS0tIHRleCYjNDU7YmUgLS0+CjxnIGlkPSJub2RlNzMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRleC1iZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTcxNS43NSwtMTg0NUM3MTUuNzUsLTE4NDUgNjg1Ljc1LC0xODQ1IDY4NS43NSwtMTg0NSA2NzkuNzUsLTE4NDUgNjczLjc1LC0xODM5IDY3My43NSwtMTgzMyA2NzMuNzUsLTE4MzMgNjczLjc1LC0xODIxIDY3My43NSwtMTgyMSA2NzMuNzUsLTE4MTUgNjc5Ljc1LC0xODA5IDY4NS43NSwtMTgwOSA2ODUuNzUsLTE4MDkgNzE1Ljc1LC0xODA5IDcxNS43NSwtMTgwOSA3MjEuNzUsLTE4MDkgNzI3Ljc1LC0xODE1IDcyNy43NSwtMTgyMSA3MjcuNzUsLTE4MjEgNzI3Ljc1LC0xODMzIDcyNy43NSwtMTgzMyA3MjcuNzUsLTE4MzkgNzIxLjc1LC0xODQ1IDcxNS43NSwtMTg0NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI3MDAuNzUiIHk9Ii0xODIxLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnRleC1iZTwvdGV4dD4KPC9nPgo8IS0tIGxhdGV4JiM0NTtiZSYjNDU7Jmd0O3RleCYjNDU7YmUgLS0+CjxnIGlkPSJlZGdlNjYiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPmxhdGV4LWJlLSZndDt0ZXgtYmU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNjI5LjkzLC0xODI3QzY0NC42OSwtMTgyNyA2NjAuOCwtMTgyNyA2NzMuODEsLTE4MjciLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNjI5Ljk4LC0xODIzLjUgNjE5Ljk4LC0xODI3IDYyOS45OCwtMTgzMC41IDYyOS45OCwtMTgyMy41Ii8+CjwvZz4KPCEtLSB0ZXgmIzQ1O2UgLS0+CjxnIGlkPSJub2RlNzYiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRleC1lPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjAxLjUsLTE3MzdDNjAxLjUsLTE3MzcgNTcxLjUsLTE3MzcgNTcxLjUsLTE3MzcgNTY1LjUsLTE3MzcgNTU5LjUsLTE3MzEgNTU5LjUsLTE3MjUgNTU5LjUsLTE3MjUgNTU5LjUsLTE3MTMgNTU5LjUsLTE3MTMgNTU5LjUsLTE3MDcgNTY1LjUsLTE3MDEgNTcxLjUsLTE3MDEgNTcxLjUsLTE3MDEgNjAxLjUsLTE3MDEgNjAxLjUsLTE3MDEgNjA3LjUsLTE3MDEgNjEzLjUsLTE3MDcgNjEzLjUsLTE3MTMgNjEzLjUsLTE3MTMgNjEzLjUsLTE3MjUgNjEzLjUsLTE3MjUgNjEzLjUsLTE3MzEgNjA3LjUsLTE3MzcgNjAxLjUsLTE3MzciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTg2LjUiIHk9Ii0xNzEzLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnRleC1lPC90ZXh0Pgo8L2c+CjwhLS0gbGF0ZXgmIzQ1O2UmIzQ1OyZndDt0ZXgmIzQ1O2UgLS0+CjxnIGlkPSJlZGdlNjkiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPmxhdGV4LWUtJmd0O3RleC1lPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ4OC4yLC0xNzE5QzUxMS4xMiwtMTcxOSA1MzkuNTYsLTE3MTkgNTU5Ljc2LC0xNzE5Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjQ4OC4zMSwtMTcxNS41IDQ3OC4zMSwtMTcxOSA0ODguMzEsLTE3MjIuNSA0ODguMzEsLTE3MTUuNSIvPgo8L2c+CjwhLS0gdGV4IC0tPgo8ZyBpZD0ibm9kZTc3IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXg8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNjIsLTExNDNDNDYzLjYyLC0xMTQzIDQzMy42MiwtMTE0MyA0MzMuNjIsLTExNDMgNDI3LjYyLC0xMTQzIDQyMS42MiwtMTEzNyA0MjEuNjIsLTExMzEgNDIxLjYyLC0xMTMxIDQyMS42MiwtMTExOSA0MjEuNjIsLTExMTkgNDIxLjYyLC0xMTEzIDQyNy42MiwtMTEwNyA0MzMuNjIsLTExMDcgNDMzLjYyLC0xMTA3IDQ2My42MiwtMTEwNyA0NjMuNjIsLTExMDcgNDY5LjYyLC0xMTA3IDQ3NS42MiwtMTExMyA0NzUuNjIsLTExMTkgNDc1LjYyLC0xMTE5IDQ3NS42MiwtMTEzMSA0NzUuNjIsLTExMzEgNDc1LjYyLC0xMTM3IDQ2OS42MiwtMTE0MyA0NjMuNjIsLTExNDMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItMTExOS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50ZXg8L3RleHQ+CjwvZz4KPCEtLSBsYXRleCYjNDU7Jmd0O3RleCAtLT4KPGcgaWQ9ImVkZ2U3MCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bGF0ZXgtJmd0O3RleDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNDkuMzYsLTExMjVDMzcyLjQxLC0xMTI1IDQwMS40MSwtMTEyNSA0MjEuOTIsLTExMjUiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMzQ5LjQ0LC0xMTIxLjUgMzM5LjQ0LC0xMTI1IDM0OS40NCwtMTEyOC41IDM0OS40NCwtMTEyMS41Ii8+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YmMgLS0+CjxnIGlkPSJub2RlMjYiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1hcmtkb3duLWJjPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMzQ4LC0xMDM1QzM0OCwtMTAzNSAyNzQuMjUsLTEwMzUgMjc0LjI1LC0xMDM1IDI2OC4yNSwtMTAzNSAyNjIuMjUsLTEwMjkgMjYyLjI1LC0xMDIzIDI2Mi4yNSwtMTAyMyAyNjIuMjUsLTEwMTEgMjYyLjI1LC0xMDExIDI2Mi4yNSwtMTAwNSAyNjguMjUsLTk5OSAyNzQuMjUsLTk5OSAyNzQuMjUsLTk5OSAzNDgsLTk5OSAzNDgsLTk5OSAzNTQsLTk5OSAzNjAsLTEwMDUgMzYwLC0xMDExIDM2MCwtMTAxMSAzNjAsLTEwMjMgMzYwLC0xMDIzIDM2MCwtMTAyOSAzNTQsLTEwMzUgMzQ4LC0xMDM1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTEwMTEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWFya2Rvd24tYmM8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YiAtLT4KPGcgaWQ9Im5vZGUyNyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWFya2Rvd24tYjwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ4Mi4xMiwtMTA4OUM0ODIuMTIsLTEwODkgNDE1LjEyLC0xMDg5IDQxNS4xMiwtMTA4OSA0MDkuMTIsLTEwODkgNDAzLjEyLC0xMDgzIDQwMy4xMiwtMTA3NyA0MDMuMTIsLTEwNzcgNDAzLjEyLC0xMDY1IDQwMy4xMiwtMTA2NSA0MDMuMTIsLTEwNTkgNDA5LjEyLC0xMDUzIDQxNS4xMiwtMTA1MyA0MTUuMTIsLTEwNTMgNDgyLjEyLC0xMDUzIDQ4Mi4xMiwtMTA1MyA0ODguMTIsLTEwNTMgNDk0LjEyLC0xMDU5IDQ5NC4xMiwtMTA2NSA0OTQuMTIsLTEwNjUgNDk0LjEyLC0xMDc3IDQ5NC4xMiwtMTA3NyA0OTQuMTIsLTEwODMgNDg4LjEyLC0xMDg5IDQ4Mi4xMiwtMTA4OSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xMDY1LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1hcmtkb3duLWI8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YmMmIzQ1OyZndDttYXJrZG93biYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2UxOSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tYmMtJmd0O21hcmtkb3duLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzY3Ljg2LC0xMDM5LjIxQzM3OS42MiwtMTA0My45IDM5MS44OCwtMTA0OC43OSA0MDMuMTYsLTEwNTMuMjgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMzY5LjI0LC0xMDM1Ljk5IDM1OC42NSwtMTAzNS41NCAzNjYuNjQsLTEwNDIuNSAzNjkuMjQsLTEwMzUuOTkiLz4KPC9nPgo8IS0tIG1kJiM0NTtiYyAtLT4KPGcgaWQ9Im5vZGUzNSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWQtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNzUsLTEwMzVDNDYzLjc1LC0xMDM1IDQzMy41LC0xMDM1IDQzMy41LC0xMDM1IDQyNy41LC0xMDM1IDQyMS41LC0xMDI5IDQyMS41LC0xMDIzIDQyMS41LC0xMDIzIDQyMS41LC0xMDExIDQyMS41LC0xMDExIDQyMS41LC0xMDA1IDQyNy41LC05OTkgNDMzLjUsLTk5OSA0MzMuNSwtOTk5IDQ2My43NSwtOTk5IDQ2My43NSwtOTk5IDQ2OS43NSwtOTk5IDQ3NS43NSwtMTAwNSA0NzUuNzUsLTEwMTEgNDc1Ljc1LC0xMDExIDQ3NS43NSwtMTAyMyA0NzUuNzUsLTEwMjMgNDc1Ljc1LC0xMDI5IDQ2OS43NSwtMTAzNSA0NjMuNzUsLTEwMzUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItMTAxMS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5tZC1iYzwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtiYyYjNDU7Jmd0O21kJiM0NTtiYyAtLT4KPGcgaWQ9ImVkZ2UyOCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tYmMtJmd0O21kLWJjPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM3MS4yOCwtMTAxN0MzODguODYsLTEwMTcgNDA3LjIyLC0xMDE3IDQyMS41MywtMTAxNyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNzEuNDEsLTEwMTMuNSAzNjEuNDEsLTEwMTcgMzcxLjQxLC0xMDIwLjUgMzcxLjQxLC0xMDEzLjUiLz4KPC9nPgo8IS0tIG1sZCYjNDU7YmMgLS0+CjxnIGlkPSJub2RlNDMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1sZC1iYzwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2NS4yNSwtOTgxQzQ2NS4yNSwtOTgxIDQzMiwtOTgxIDQzMiwtOTgxIDQyNiwtOTgxIDQyMCwtOTc1IDQyMCwtOTY5IDQyMCwtOTY5IDQyMCwtOTU3IDQyMCwtOTU3IDQyMCwtOTUxIDQyNiwtOTQ1IDQzMiwtOTQ1IDQzMiwtOTQ1IDQ2NS4yNSwtOTQ1IDQ2NS4yNSwtOTQ1IDQ3MS4yNSwtOTQ1IDQ3Ny4yNSwtOTUxIDQ3Ny4yNSwtOTU3IDQ3Ny4yNSwtOTU3IDQ3Ny4yNSwtOTY5IDQ3Ny4yNSwtOTY5IDQ3Ny4yNSwtOTc1IDQ3MS4yNSwtOTgxIDQ2NS4yNSwtOTgxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTk1Ny41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5tbGQtYmM8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YmMmIzQ1OyZndDttbGQmIzQ1O2JjIC0tPgo8ZyBpZD0iZWRnZTM2IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1iYy0mZ3Q7bWxkLWJjPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM2Ny42OSwtOTk0Ljg1QzM4NS43NCwtOTg3LjY2IDQwNC45OSwtOTc5Ljk5IDQyMC4wNywtOTczLjk4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM2Ni42NCwtOTkxLjUgMzU4LjY1LC05OTguNDYgMzY5LjI0LC05OTguMDEgMzY2LjY0LC05OTEuNSIvPgo8L2c+CjwhLS0gbWQmIzQ1O2IgLS0+CjxnIGlkPSJub2RlMzQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1kLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02MDEuNSwtMTExNkM2MDEuNSwtMTExNiA1NzEuNSwtMTExNiA1NzEuNSwtMTExNiA1NjUuNSwtMTExNiA1NTkuNSwtMTExMCA1NTkuNSwtMTEwNCA1NTkuNSwtMTEwNCA1NTkuNSwtMTA5MiA1NTkuNSwtMTA5MiA1NTkuNSwtMTA4NiA1NjUuNSwtMTA4MCA1NzEuNSwtMTA4MCA1NzEuNSwtMTA4MCA2MDEuNSwtMTA4MCA2MDEuNSwtMTA4MCA2MDcuNSwtMTA4MCA2MTMuNSwtMTA4NiA2MTMuNSwtMTA5MiA2MTMuNSwtMTA5MiA2MTMuNSwtMTEwNCA2MTMuNSwtMTEwNCA2MTMuNSwtMTExMCA2MDcuNSwtMTExNiA2MDEuNSwtMTExNiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTEwOTIuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWQtYjwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtiJiM0NTsmZ3Q7bWQmIzQ1O2IgLS0+CjxnIGlkPSJlZGdlMjciIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1hcmtkb3duLWItJmd0O21kLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNTA1LjI5LC0xMDgyLjA2QzUyNC4wOSwtMTA4NS44IDU0NC4xOSwtMTA4OS43OSA1NTkuNTYsLTEwOTIuODUiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTA2LjA5LC0xMDc4LjY1IDQ5NS42LC0xMDgwLjE0IDUwNC43MywtMTA4NS41MiA1MDYuMDksLTEwNzguNjUiLz4KPC9nPgo8IS0tIG1sZCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU0MiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWxkLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02MDEuNSwtMTA2MkM2MDEuNSwtMTA2MiA1NzEuNSwtMTA2MiA1NzEuNSwtMTA2MiA1NjUuNSwtMTA2MiA1NTkuNSwtMTA1NiA1NTkuNSwtMTA1MCA1NTkuNSwtMTA1MCA1NTkuNSwtMTAzOCA1NTkuNSwtMTAzOCA1NTkuNSwtMTAzMiA1NjUuNSwtMTAyNiA1NzEuNSwtMTAyNiA1NzEuNSwtMTAyNiA2MDEuNSwtMTAyNiA2MDEuNSwtMTAyNiA2MDcuNSwtMTAyNiA2MTMuNSwtMTAzMiA2MTMuNSwtMTAzOCA2MTMuNSwtMTAzOCA2MTMuNSwtMTA1MCA2MTMuNSwtMTA1MCA2MTMuNSwtMTA1NiA2MDcuNSwtMTA2MiA2MDEuNSwtMTA2MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTEwMzguNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWxkLWI8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YiYjNDU7Jmd0O21sZCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2UzNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tYi0mZ3Q7bWxkLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNTA1LjI5LC0xMDU5Ljk0QzUyNC4wOSwtMTA1Ni4yIDU0NC4xOSwtMTA1Mi4yMSA1NTkuNTYsLTEwNDkuMTUiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTA0LjczLC0xMDU2LjQ4IDQ5NS42LC0xMDYxLjg2IDUwNi4wOSwtMTA2My4zNSA1MDQuNzMsLTEwNTYuNDgiLz4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtjJiM0NTsmZ3Q7bWFya2Rvd24mIzQ1O2JjIC0tPgo8ZyBpZD0iZWRnZTIwIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1jLSZndDttYXJrZG93bi1iYzwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMzUuMzQsLTk4NS40NUMyNDYuMTMsLTk5MCAyNTcuMzQsLTk5NC43MyAyNjcuNjksLTk5OS4xIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIzNi43MiwtOTgyLjIzIDIyNi4xNCwtOTgxLjU3IDIzMy45OSwtOTg4LjY4IDIzNi43MiwtOTgyLjIzIi8+CjwvZz4KPCEtLSBtYXJrZG93biAtLT4KPGcgaWQ9Im5vZGUzMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWFya2Rvd248L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmM5MjcyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMzguNjIsLTk4MUMzMzguNjIsLTk4MSAyODMuNjIsLTk4MSAyODMuNjIsLTk4MSAyNzcuNjIsLTk4MSAyNzEuNjIsLTk3NSAyNzEuNjIsLTk2OSAyNzEuNjIsLTk2OSAyNzEuNjIsLTk1NyAyNzEuNjIsLTk1NyAyNzEuNjIsLTk1MSAyNzcuNjIsLTk0NSAyODMuNjIsLTk0NSAyODMuNjIsLTk0NSAzMzguNjIsLTk0NSAzMzguNjIsLTk0NSAzNDQuNjIsLTk0NSAzNTAuNjIsLTk1MSAzNTAuNjIsLTk1NyAzNTAuNjIsLTk1NyAzNTAuNjIsLTk2OSAzNTAuNjIsLTk2OSAzNTAuNjIsLTk3NSAzNDQuNjIsLTk4MSAzMzguNjIsLTk4MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii05NTcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWFya2Rvd248L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YyYjNDU7Jmd0O21hcmtkb3duIC0tPgo8ZyBpZD0iZWRnZTI2IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1jLSZndDttYXJrZG93bjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMzcuNTksLTk2M0MyNDkuMTksLTk2MyAyNjEuMTcsLTk2MyAyNzEuOTcsLTk2MyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIyMzcuNjksLTk1OS41IDIyNy42OSwtOTYzIDIzNy42OSwtOTY2LjUgMjM3LjY5LC05NTkuNSIvPgo8L2c+CjwhLS0gbWQmIzQ1O2MgLS0+CjxnIGlkPSJub2RlMzgiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1kLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTkyN0MzMjYuMTIsLTkyNyAyOTYuMTIsLTkyNyAyOTYuMTIsLTkyNyAyOTAuMTIsLTkyNyAyODQuMTIsLTkyMSAyODQuMTIsLTkxNSAyODQuMTIsLTkxNSAyODQuMTIsLTkwMyAyODQuMTIsLTkwMyAyODQuMTIsLTg5NyAyOTAuMTIsLTg5MSAyOTYuMTIsLTg5MSAyOTYuMTIsLTg5MSAzMjYuMTIsLTg5MSAzMjYuMTIsLTg5MSAzMzIuMTIsLTg5MSAzMzguMTIsLTg5NyAzMzguMTIsLTkwMyAzMzguMTIsLTkwMyAzMzguMTIsLTkxNSAzMzguMTIsLTkxNSAzMzguMTIsLTkyMSAzMzIuMTIsLTkyNyAzMjYuMTIsLTkyNyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii05MDMuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWQtYzwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtjJiM0NTsmZ3Q7bWQmIzQ1O2MgLS0+CjxnIGlkPSJlZGdlMzEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1hcmtkb3duLWMtJmd0O21kLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjM1LjE3LC05NDAuNjJDMjUyLjIyLC05MzMuNDMgMjcwLjMyLC05MjUuNzkgMjg0LjQ3LC05MTkuODIiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjMzLjk5LC05MzcuMzIgMjI2LjE0LC05NDQuNDMgMjM2LjcyLC05NDMuNzcgMjMzLjk5LC05MzcuMzIiLz4KPC9nPgo8IS0tIG1sZCYjNDU7YyAtLT4KPGcgaWQ9Im5vZGU0NiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWxkLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTg3M0MzMjYuMTIsLTg3MyAyOTYuMTIsLTg3MyAyOTYuMTIsLTg3MyAyOTAuMTIsLTg3MyAyODQuMTIsLTg2NyAyODQuMTIsLTg2MSAyODQuMTIsLTg2MSAyODQuMTIsLTg0OSAyODQuMTIsLTg0OSAyODQuMTIsLTg0MyAyOTAuMTIsLTgzNyAyOTYuMTIsLTgzNyAyOTYuMTIsLTgzNyAzMjYuMTIsLTgzNyAzMjYuMTIsLTgzNyAzMzIuMTIsLTgzNyAzMzguMTIsLTg0MyAzMzguMTIsLTg0OSAzMzguMTIsLTg0OSAzMzguMTIsLTg2MSAzMzguMTIsLTg2MSAzMzguMTIsLTg2NyAzMzIuMTIsLTg3MyAzMjYuMTIsLTg3MyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii04NDkuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWxkLWM8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YyYjNDU7Jmd0O21sZCYjNDU7YyAtLT4KPGcgaWQ9ImVkZ2UzOSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tYy0mZ3Q7bWxkLWM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjA0LjU1LC05MzYuODNDMjE5Ljc4LC05MTkuOTcgMjQwLjk2LC04OTguMjUgMjYyLjI1LC04ODIgMjY5LjA4LC04NzYuNzkgMjc3LjAyLC04NzEuOSAyODQuNDUsLTg2Ny43NiIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIyMDIuMTksLTkzNC4yMiAxOTguMTYsLTk0NC4wMiAyMDcuNDIsLTkzOC44NyAyMDIuMTksLTkzNC4yMiIvPgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2JjZSAtLT4KPGcgaWQ9Im5vZGUzMCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWFya2Rvd24tYmNlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDg5LjI1LC0xNjI5QzQ4OS4yNSwtMTYyOSA0MDgsLTE2MjkgNDA4LC0xNjI5IDQwMiwtMTYyOSAzOTYsLTE2MjMgMzk2LC0xNjE3IDM5NiwtMTYxNyAzOTYsLTE2MDUgMzk2LC0xNjA1IDM5NiwtMTU5OSA0MDIsLTE1OTMgNDA4LC0xNTkzIDQwOCwtMTU5MyA0ODkuMjUsLTE1OTMgNDg5LjI1LC0xNTkzIDQ5NS4yNSwtMTU5MyA1MDEuMjUsLTE1OTkgNTAxLjI1LC0xNjA1IDUwMS4yNSwtMTYwNSA1MDEuMjUsLTE2MTcgNTAxLjI1LC0xNjE3IDUwMS4yNSwtMTYyMyA0OTUuMjUsLTE2MjkgNDg5LjI1LC0xNjI5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTE2MDUuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWFya2Rvd24tYmNlPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2NlJiM0NTsmZ3Q7bWFya2Rvd24mIzQ1O2JjZSAtLT4KPGcgaWQ9ImVkZ2UyMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tY2UtJmd0O21hcmtkb3duLWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNjcuNzUsLTE1NzkuMTdDMzc5LjM5LC0xNTgzLjgxIDM5MS41MSwtMTU4OC42NCA0MDIuNywtMTU5My4xIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM2OS4yNCwtMTU3NS45OSAzNTguNjUsLTE1NzUuNTQgMzY2LjY0LC0xNTgyLjUgMzY5LjI0LC0xNTc1Ljk5Ii8+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7ZSAtLT4KPGcgaWQ9Im5vZGUzMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWFya2Rvd24tZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ4Mi4xMiwtMTU3NUM0ODIuMTIsLTE1NzUgNDE1LjEyLC0xNTc1IDQxNS4xMiwtMTU3NSA0MDkuMTIsLTE1NzUgNDAzLjEyLC0xNTY5IDQwMy4xMiwtMTU2MyA0MDMuMTIsLTE1NjMgNDAzLjEyLC0xNTUxIDQwMy4xMiwtMTU1MSA0MDMuMTIsLTE1NDUgNDA5LjEyLC0xNTM5IDQxNS4xMiwtMTUzOSA0MTUuMTIsLTE1MzkgNDgyLjEyLC0xNTM5IDQ4Mi4xMiwtMTUzOSA0ODguMTIsLTE1MzkgNDk0LjEyLC0xNTQ1IDQ5NC4xMiwtMTU1MSA0OTQuMTIsLTE1NTEgNDk0LjEyLC0xNTYzIDQ5NC4xMiwtMTU2MyA0OTQuMTIsLTE1NjkgNDg4LjEyLC0xNTc1IDQ4Mi4xMiwtMTU3NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xNTUxLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1hcmtkb3duLWU8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7Y2UmIzQ1OyZndDttYXJrZG93biYjNDU7ZSAtLT4KPGcgaWQ9ImVkZ2UyNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tY2UtJmd0O21hcmtkb3duLWU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzcxLjQxLC0xNTU3QzM4Mi4xNywtMTU1NyAzOTMuMjIsLTE1NTcgNDAzLjQ1LC0xNTU3Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM3MS40MSwtMTU1My41IDM2MS40MSwtMTU1NyAzNzEuNDEsLTE1NjAuNSAzNzEuNDEsLTE1NTMuNSIvPgo8L2c+CjwhLS0gbWQmIzQ1O2NlIC0tPgo8ZyBpZD0ibm9kZTM5IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tZC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2My43NSwtMTUyMUM0NjMuNzUsLTE1MjEgNDMzLjUsLTE1MjEgNDMzLjUsLTE1MjEgNDI3LjUsLTE1MjEgNDIxLjUsLTE1MTUgNDIxLjUsLTE1MDkgNDIxLjUsLTE1MDkgNDIxLjUsLTE0OTcgNDIxLjUsLTE0OTcgNDIxLjUsLTE0OTEgNDI3LjUsLTE0ODUgNDMzLjUsLTE0ODUgNDMzLjUsLTE0ODUgNDYzLjc1LC0xNDg1IDQ2My43NSwtMTQ4NSA0NjkuNzUsLTE0ODUgNDc1Ljc1LC0xNDkxIDQ3NS43NSwtMTQ5NyA0NzUuNzUsLTE0OTcgNDc1Ljc1LC0xNTA5IDQ3NS43NSwtMTUwOSA0NzUuNzUsLTE1MTUgNDY5Ljc1LC0xNTIxIDQ2My43NSwtMTUyMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xNDk3LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1kLWNlPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2NlJiM0NTsmZ3Q7bWQmIzQ1O2NlIC0tPgo8ZyBpZD0iZWRnZTMyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1jZS0mZ3Q7bWQtY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzY3Ljc1LC0xNTM0LjgzQzM4Ni40MiwtMTUyNy4zOSA0MDYuMzcsLTE1MTkuNDQgNDIxLjY2LC0xNTEzLjM1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM2Ni42NCwtMTUzMS41IDM1OC42NSwtMTUzOC40NiAzNjkuMjQsLTE1MzguMDEgMzY2LjY0LC0xNTMxLjUiLz4KPC9nPgo8IS0tIG1sZCYjNDU7Y2UgLS0+CjxnIGlkPSJub2RlNDciIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1sZC1jZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2NS4yNSwtMTQ2N0M0NjUuMjUsLTE0NjcgNDMyLC0xNDY3IDQzMiwtMTQ2NyA0MjYsLTE0NjcgNDIwLC0xNDYxIDQyMCwtMTQ1NSA0MjAsLTE0NTUgNDIwLC0xNDQzIDQyMCwtMTQ0MyA0MjAsLTE0MzcgNDI2LC0xNDMxIDQzMiwtMTQzMSA0MzIsLTE0MzEgNDY1LjI1LC0xNDMxIDQ2NS4yNSwtMTQzMSA0NzEuMjUsLTE0MzEgNDc3LjI1LC0xNDM3IDQ3Ny4yNSwtMTQ0MyA0NzcuMjUsLTE0NDMgNDc3LjI1LC0xNDU1IDQ3Ny4yNSwtMTQ1NSA0NzcuMjUsLTE0NjEgNDcxLjI1LC0xNDY3IDQ2NS4yNSwtMTQ2NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xNDQzLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1sZC1jZTwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtjZSYjNDU7Jmd0O21sZCYjNDU7Y2UgLS0+CjxnIGlkPSJlZGdlNDAiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1hcmtkb3duLWNlLSZndDttbGQtY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzM1LjYzLC0xNTMwLjY4QzM1MS41OSwtMTUxMy43NyAzNzMuNzcsLTE0OTIuMDQgMzk2LC0xNDc2IDQwMy40NiwtMTQ3MC42MiA0MTIuMTUsLTE0NjUuNjUgNDIwLjIzLC0xNDYxLjQ4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjMzMy4xNSwtMTUyOC4yMSAzMjguOTEsLTE1MzcuOTMgMzM4LjI4LC0xNTMyLjk4IDMzMy4xNSwtMTUyOC4yMSIvPgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2JlIC0tPgo8ZyBpZD0ibm9kZTMxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tYXJrZG93bi1iZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTYyMy43NSwtMTY4M0M2MjMuNzUsLTE2ODMgNTQ5LjI1LC0xNjgzIDU0OS4yNSwtMTY4MyA1NDMuMjUsLTE2ODMgNTM3LjI1LC0xNjc3IDUzNy4yNSwtMTY3MSA1MzcuMjUsLTE2NzEgNTM3LjI1LC0xNjU5IDUzNy4yNSwtMTY1OSA1MzcuMjUsLTE2NTMgNTQzLjI1LC0xNjQ3IDU0OS4yNSwtMTY0NyA1NDkuMjUsLTE2NDcgNjIzLjc1LC0xNjQ3IDYyMy43NSwtMTY0NyA2MjkuNzUsLTE2NDcgNjM1Ljc1LC0xNjUzIDYzNS43NSwtMTY1OSA2MzUuNzUsLTE2NTkgNjM1Ljc1LC0xNjcxIDYzNS43NSwtMTY3MSA2MzUuNzUsLTE2NzcgNjI5Ljc1LC0xNjgzIDYyMy43NSwtMTY4MyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTE2NTkuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWFya2Rvd24tYmU8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YmNlJiM0NTsmZ3Q7bWFya2Rvd24mIzQ1O2JlIC0tPgo8ZyBpZD0iZWRnZTIyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1iY2UtJmd0O21hcmtkb3duLWJlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTUwNS40LC0xNjMzLjE3QzUxNy4wNywtMTYzNy44MSA1MjkuMjMsLTE2NDIuNjQgNTQwLjQ1LC0xNjQ3LjEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTA2Ljg2LC0xNjI5Ljk4IDQ5Ni4yOCwtMTYyOS41NCA1MDQuMjgsLTE2MzYuNDkgNTA2Ljg2LC0xNjI5Ljk4Ii8+CjwvZz4KPCEtLSBtZCYjNDU7YmNlIC0tPgo8ZyBpZD0ibm9kZTM2IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tZC1iY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik02MDUuMzgsLTE2MjlDNjA1LjM4LC0xNjI5IDU2Ny42MiwtMTYyOSA1NjcuNjIsLTE2MjkgNTYxLjYyLC0xNjI5IDU1NS42MiwtMTYyMyA1NTUuNjIsLTE2MTcgNTU1LjYyLC0xNjE3IDU1NS42MiwtMTYwNSA1NTUuNjIsLTE2MDUgNTU1LjYyLC0xNTk5IDU2MS42MiwtMTU5MyA1NjcuNjIsLTE1OTMgNTY3LjYyLC0xNTkzIDYwNS4zOCwtMTU5MyA2MDUuMzgsLTE1OTMgNjExLjM4LC0xNTkzIDYxNy4zOCwtMTU5OSA2MTcuMzgsLTE2MDUgNjE3LjM4LC0xNjA1IDYxNy4zOCwtMTYxNyA2MTcuMzgsLTE2MTcgNjE3LjM4LC0xNjIzIDYxMS4zOCwtMTYyOSA2MDUuMzgsLTE2MjkiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTg2LjUiIHk9Ii0xNjA1LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1kLWJjZTwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtiY2UmIzQ1OyZndDttZCYjNDU7YmNlIC0tPgo8ZyBpZD0iZWRnZTI5IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1iY2UtJmd0O21kLWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01MTIuNDMsLTE2MTFDNTI3LjUzLC0xNjExIDU0Mi45NywtMTYxMSA1NTUuNzQsLTE2MTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTEyLjUxLC0xNjA3LjUgNTAyLjUxLC0xNjExIDUxMi41MSwtMTYxNC41IDUxMi41MSwtMTYwNy41Ii8+CjwvZz4KPCEtLSBtbGQmIzQ1O2JjZSAtLT4KPGcgaWQ9Im5vZGU0NCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWxkLWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTYwNi44OCwtMTU3NUM2MDYuODgsLTE1NzUgNTY2LjEyLC0xNTc1IDU2Ni4xMiwtMTU3NSA1NjAuMTIsLTE1NzUgNTU0LjEyLC0xNTY5IDU1NC4xMiwtMTU2MyA1NTQuMTIsLTE1NjMgNTU0LjEyLC0xNTUxIDU1NC4xMiwtMTU1MSA1NTQuMTIsLTE1NDUgNTYwLjEyLC0xNTM5IDU2Ni4xMiwtMTUzOSA1NjYuMTIsLTE1MzkgNjA2Ljg4LC0xNTM5IDYwNi44OCwtMTUzOSA2MTIuODgsLTE1MzkgNjE4Ljg4LC0xNTQ1IDYxOC44OCwtMTU1MSA2MTguODgsLTE1NTEgNjE4Ljg4LC0xNTYzIDYxOC44OCwtMTU2MyA2MTguODgsLTE1NjkgNjEyLjg4LC0xNTc1IDYwNi44OCwtMTU3NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1ODYuNSIgeT0iLTE1NTEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bWxkLWJjZTwvdGV4dD4KPC9nPgo8IS0tIG1hcmtkb3duJiM0NTtiY2UmIzQ1OyZndDttbGQmIzQ1O2JjZSAtLT4KPGcgaWQ9ImVkZ2UzNyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tYmNlLSZndDttbGQtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTUwNS4xMSwtMTU4OC45NUM1MjEuODQsLTE1ODIuMyA1MzkuNjEsLTE1NzUuMjQgNTU0LjE3LC0xNTY5LjQ1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjUwNC4yOCwtMTU4NS41MSA0OTYuMjgsLTE1OTIuNDYgNTA2Ljg2LC0xNTkyLjAyIDUwNC4yOCwtMTU4NS41MSIvPgo8L2c+CjwhLS0gbWQmIzQ1O2JlIC0tPgo8ZyBpZD0ibm9kZTM3IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tZC1iZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTcxNi4yNSwtMTcxMEM3MTYuMjUsLTE3MTAgNjg1LjI1LC0xNzEwIDY4NS4yNSwtMTcxMCA2NzkuMjUsLTE3MTAgNjczLjI1LC0xNzA0IDY3My4yNSwtMTY5OCA2NzMuMjUsLTE2OTggNjczLjI1LC0xNjg2IDY3My4yNSwtMTY4NiA2NzMuMjUsLTE2ODAgNjc5LjI1LC0xNjc0IDY4NS4yNSwtMTY3NCA2ODUuMjUsLTE2NzQgNzE2LjI1LC0xNjc0IDcxNi4yNSwtMTY3NCA3MjIuMjUsLTE2NzQgNzI4LjI1LC0xNjgwIDcyOC4yNSwtMTY4NiA3MjguMjUsLTE2ODYgNzI4LjI1LC0xNjk4IDcyOC4yNSwtMTY5OCA3MjguMjUsLTE3MDQgNzIyLjI1LC0xNzEwIDcxNi4yNSwtMTcxMCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI3MDAuNzUiIHk9Ii0xNjg2LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1kLWJlPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2JlJiM0NTsmZ3Q7bWQmIzQ1O2JlIC0tPgo8ZyBpZD0iZWRnZTMwIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1iZS0mZ3Q7bWQtYmU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNjQ2LjQ3LC0xNjc5LjE4QzY1NS44OCwtMTY4MS40NSA2NjUuMTksLTE2ODMuNjkgNjczLjMzLC0xNjg1LjY1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjY0Ny40NCwtMTY3NS44MiA2MzYuOSwtMTY3Ni44OCA2NDUuODEsLTE2ODIuNjIgNjQ3LjQ0LC0xNjc1LjgyIi8+CjwvZz4KPCEtLSBtbGQmIzQ1O2JlIC0tPgo8ZyBpZD0ibm9kZTQ1IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tbGQtYmU8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik03MTcuNzUsLTE2NTZDNzE3Ljc1LC0xNjU2IDY4My43NSwtMTY1NiA2ODMuNzUsLTE2NTYgNjc3Ljc1LC0xNjU2IDY3MS43NSwtMTY1MCA2NzEuNzUsLTE2NDQgNjcxLjc1LC0xNjQ0IDY3MS43NSwtMTYzMiA2NzEuNzUsLTE2MzIgNjcxLjc1LC0xNjI2IDY3Ny43NSwtMTYyMCA2ODMuNzUsLTE2MjAgNjgzLjc1LC0xNjIwIDcxNy43NSwtMTYyMCA3MTcuNzUsLTE2MjAgNzIzLjc1LC0xNjIwIDcyOS43NSwtMTYyNiA3MjkuNzUsLTE2MzIgNzI5Ljc1LC0xNjMyIDcyOS43NSwtMTY0NCA3MjkuNzUsLTE2NDQgNzI5Ljc1LC0xNjUwIDcyMy43NSwtMTY1NiA3MTcuNzUsLTE2NTYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNzAwLjc1IiB5PSItMTYzMi41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5tbGQtYmU8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7YmUmIzQ1OyZndDttbGQmIzQ1O2JlIC0tPgo8ZyBpZD0iZWRnZTM4IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tYXJrZG93bi1iZS0mZ3Q7bWxkLWJlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTY0Ni41NSwtMTY1MC44QzY1NS4zNCwtMTY0OC42OCA2NjQuMDMsLTE2NDYuNTkgNjcxLjc2LC0xNjQ0LjczIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjY0NS44MSwtMTY0Ny4zOCA2MzYuOSwtMTY1My4xMiA2NDcuNDQsLTE2NTQuMTggNjQ1LjgxLC0xNjQ3LjM4Ii8+CjwvZz4KPCEtLSBtZCYjNDU7ZSAtLT4KPGcgaWQ9Im5vZGU0MCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bWQtZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTYwMS41LC0xNTIxQzYwMS41LC0xNTIxIDU3MS41LC0xNTIxIDU3MS41LC0xNTIxIDU2NS41LC0xNTIxIDU1OS41LC0xNTE1IDU1OS41LC0xNTA5IDU1OS41LC0xNTA5IDU1OS41LC0xNDk3IDU1OS41LC0xNDk3IDU1OS41LC0xNDkxIDU2NS41LC0xNDg1IDU3MS41LC0xNDg1IDU3MS41LC0xNDg1IDYwMS41LC0xNDg1IDYwMS41LC0xNDg1IDYwNy41LC0xNDg1IDYxMy41LC0xNDkxIDYxMy41LC0xNDk3IDYxMy41LC0xNDk3IDYxMy41LC0xNTA5IDYxMy41LC0xNTA5IDYxMy41LC0xNTE1IDYwNy41LC0xNTIxIDYwMS41LC0xNTIxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU4Ni41IiB5PSItMTQ5Ny41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5tZC1lPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2UmIzQ1OyZndDttZCYjNDU7ZSAtLT4KPGcgaWQ9ImVkZ2UzMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tZS0mZ3Q7bWQtZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01MDQuNzYsLTE1MzUuMDlDNTIzLjcyLC0xNTI3LjU1IDU0NC4wNCwtMTUxOS40OCA1NTkuNTYsLTE1MTMuMzEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTAzLjUyLC0xNTMxLjgxIDQ5NS41MiwtMTUzOC43NiA1MDYuMTEsLTE1MzguMzIgNTAzLjUyLC0xNTMxLjgxIi8+CjwvZz4KPCEtLSBtbGQmIzQ1O2UgLS0+CjxnIGlkPSJub2RlNDgiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1sZC1lPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjAxLjUsLTE0NjdDNjAxLjUsLTE0NjcgNTcxLjUsLTE0NjcgNTcxLjUsLTE0NjcgNTY1LjUsLTE0NjcgNTU5LjUsLTE0NjEgNTU5LjUsLTE0NTUgNTU5LjUsLTE0NTUgNTU5LjUsLTE0NDMgNTU5LjUsLTE0NDMgNTU5LjUsLTE0MzcgNTY1LjUsLTE0MzEgNTcxLjUsLTE0MzEgNTcxLjUsLTE0MzEgNjAxLjUsLTE0MzEgNjAxLjUsLTE0MzEgNjA3LjUsLTE0MzEgNjEzLjUsLTE0MzcgNjEzLjUsLTE0NDMgNjEzLjUsLTE0NDMgNjEzLjUsLTE0NTUgNjEzLjUsLTE0NTUgNjEzLjUsLTE0NjEgNjA3LjUsLTE0NjcgNjAxLjUsLTE0NjciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTg2LjUiIHk9Ii0xNDQzLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1sZC1lPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1O2UmIzQ1OyZndDttbGQmIzQ1O2UgLS0+CjxnIGlkPSJlZGdlNDEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1hcmtkb3duLWUtJmd0O21sZC1lPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ5OC40LC0xNTMyLjQzQzQ5OS4zOCwtMTUzMS42NCA1MDAuMzMsLTE1MzAuODMgNTAxLjI1LC0xNTMwIDUyMi43LC0xNTEwLjcxIDUxNi4wOCwtMTQ5NS41OSA1MzcuMjUsLTE0NzYgNTQzLjg3LC0xNDY5Ljg3IDU1Mi4xNCwtMTQ2NC42IDU1OS45NSwtMTQ2MC4zOSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0OTYuNDEsLTE1MjkuNTUgNDkwLjMsLTE1MzguMjEgNTAwLjQ4LC0xNTM1LjI1IDQ5Ni40MSwtMTUyOS41NSIvPgo8L2c+CjwhLS0gbWQgLS0+CjxnIGlkPSJub2RlNDEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1kPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDYzLjYyLC05MjdDNDYzLjYyLC05MjcgNDMzLjYyLC05MjcgNDMzLjYyLC05MjcgNDI3LjYyLC05MjcgNDIxLjYyLC05MjEgNDIxLjYyLC05MTUgNDIxLjYyLC05MTUgNDIxLjYyLC05MDMgNDIxLjYyLC05MDMgNDIxLjYyLC04OTcgNDI3LjYyLC04OTEgNDMzLjYyLC04OTEgNDMzLjYyLC04OTEgNDYzLjYyLC04OTEgNDYzLjYyLC04OTEgNDY5LjYyLC04OTEgNDc1LjYyLC04OTcgNDc1LjYyLC05MDMgNDc1LjYyLC05MDMgNDc1LjYyLC05MTUgNDc1LjYyLC05MTUgNDc1LjYyLC05MjEgNDY5LjYyLC05MjcgNDYzLjYyLC05MjciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItOTAzLjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm1kPC90ZXh0Pgo8L2c+CjwhLS0gbWFya2Rvd24mIzQ1OyZndDttZCAtLT4KPGcgaWQ9ImVkZ2UzNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tJmd0O21kPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM2MS4wOCwtOTQzLjQ5QzM4MS42NywtOTM1LjI4IDQwNC43OCwtOTI2LjA4IDQyMS45MywtOTE5LjI0Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1OS45OSwtOTQwLjE2IDM1MiwtOTQ3LjExIDM2Mi41OCwtOTQ2LjY2IDM1OS45OSwtOTQwLjE2Ii8+CjwvZz4KPCEtLSBtbGQgLS0+CjxnIGlkPSJub2RlNDkiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1sZDwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2My42MiwtODczQzQ2My42MiwtODczIDQzMy42MiwtODczIDQzMy42MiwtODczIDQyNy42MiwtODczIDQyMS42MiwtODY3IDQyMS42MiwtODYxIDQyMS42MiwtODYxIDQyMS42MiwtODQ5IDQyMS42MiwtODQ5IDQyMS42MiwtODQzIDQyNy42MiwtODM3IDQzMy42MiwtODM3IDQzMy42MiwtODM3IDQ2My42MiwtODM3IDQ2My42MiwtODM3IDQ2OS42MiwtODM3IDQ3NS42MiwtODQzIDQ3NS42MiwtODQ5IDQ3NS42MiwtODQ5IDQ3NS42MiwtODYxIDQ3NS42MiwtODYxIDQ3NS42MiwtODY3IDQ2OS42MiwtODczIDQ2My42MiwtODczIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTg0OS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5tbGQ8L3RleHQ+CjwvZz4KPCEtLSBtYXJrZG93biYjNDU7Jmd0O21sZCAtLT4KPGcgaWQ9ImVkZ2U0MiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bWFya2Rvd24tJmd0O21sZDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTcuMTgsLTkzOC40OEMzNTguMTUsLTkzNy42NyAzNTkuMDksLTkzNi44NCAzNjAsLTkzNiAzODEuMTQsLTkxNi4zOCAzNzQuNTUsLTkwMS4yOSAzOTYsLTg4MiA0MDMuNTIsLTg3NS4yNCA0MTMuMDQsLTg2OS42NCA0MjEuODYsLTg2NS4zMyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTUuMTIsLTkzNS42NiAzNDkuMTYsLTk0NC40MiAzNTkuMjgsLTk0MS4yOCAzNTUuMTIsLTkzNS42NiIvPgo8L2c+CjwhLS0gbXNzcWwmIzQ1O2IgLS0+CjxnIGlkPSJub2RlNTAiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm1zc3FsLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMzEuMTIsLTYwM0MzMzEuMTIsLTYwMyAyOTEuMTIsLTYwMyAyOTEuMTIsLTYwMyAyODUuMTIsLTYwMyAyNzkuMTIsLTU5NyAyNzkuMTIsLTU5MSAyNzkuMTIsLTU5MSAyNzkuMTIsLTU3OSAyNzkuMTIsLTU3OSAyNzkuMTIsLTU3MyAyODUuMTIsLTU2NyAyOTEuMTIsLTU2NyAyOTEuMTIsLTU2NyAzMzEuMTIsLTU2NyAzMzEuMTIsLTU2NyAzMzcuMTIsLTU2NyAzNDMuMTIsLTU3MyAzNDMuMTIsLTU3OSAzNDMuMTIsLTU3OSAzNDMuMTIsLTU5MSAzNDMuMTIsLTU5MSAzNDMuMTIsLTU5NyAzMzcuMTIsLTYwMyAzMzEuMTIsLTYwMyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii01NzkuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bXNzcWwtYjwvdGV4dD4KPC9nPgo8IS0tIG1zX3NxbCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU1MSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bXNfc3FsLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NzIuMzgsLTY1N0M0NzIuMzgsLTY1NyA0MjQuODgsLTY1NyA0MjQuODgsLTY1NyA0MTguODgsLTY1NyA0MTIuODgsLTY1MSA0MTIuODgsLTY0NSA0MTIuODgsLTY0NSA0MTIuODgsLTYzMyA0MTIuODgsLTYzMyA0MTIuODgsLTYyNyA0MTguODgsLTYyMSA0MjQuODgsLTYyMSA0MjQuODgsLTYyMSA0NzIuMzgsLTYyMSA0NzIuMzgsLTYyMSA0NzguMzgsLTYyMSA0ODQuMzgsLTYyNyA0ODQuMzgsLTYzMyA0ODQuMzgsLTYzMyA0ODQuMzgsLTY0NSA0ODQuMzgsLTY0NSA0ODQuMzgsLTY1MSA0NzguMzgsLTY1NyA0NzIuMzgsLTY1NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii02MzMuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bXNfc3FsLWI8L3RleHQ+CjwvZz4KPCEtLSBtc3NxbCYjNDU7YiYjNDU7Jmd0O21zX3NxbCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U0MyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bXNzcWwtYi0mZ3Q7bXNfc3FsLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzUzLjQsLTYwMS40NUMzNzIuNTIsLTYwOS4wNyAzOTQuOTksLTYxOC4wMiA0MTMuMTksLTYyNS4yOCIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTQuODYsLTU5OC4yNiAzNDQuMjgsLTU5Ny44MSAzNTIuMjcsLTYwNC43NyAzNTQuODYsLTU5OC4yNiIvPgo8L2c+CjwhLS0gc3FsX3NlcnZlciYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU2NCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+c3FsX3NlcnZlci1iPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDgxLjc1LC02MDNDNDgxLjc1LC02MDMgNDE1LjUsLTYwMyA0MTUuNSwtNjAzIDQwOS41LC02MDMgNDAzLjUsLTU5NyA0MDMuNSwtNTkxIDQwMy41LC01OTEgNDAzLjUsLTU3OSA0MDMuNSwtNTc5IDQwMy41LC01NzMgNDA5LjUsLTU2NyA0MTUuNSwtNTY3IDQxNS41LC01NjcgNDgxLjc1LC01NjcgNDgxLjc1LC01NjcgNDg3Ljc1LC01NjcgNDkzLjc1LC01NzMgNDkzLjc1LC01NzkgNDkzLjc1LC01NzkgNDkzLjc1LC01OTEgNDkzLjc1LC01OTEgNDkzLjc1LC01OTcgNDg3Ljc1LC02MDMgNDgxLjc1LC02MDMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItNTc5LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnNxbF9zZXJ2ZXItYjwvdGV4dD4KPC9nPgo8IS0tIG1zc3FsJiM0NTtiJiM0NTsmZ3Q7c3FsX3NlcnZlciYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U1NyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bXNzcWwtYi0mZ3Q7c3FsX3NlcnZlci1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM1NC4zNywtNTg1QzM3MC4wMywtNTg1IDM4Ny44MywtNTg1IDQwMy42NCwtNTg1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1NC4zOSwtNTgxLjUgMzQ0LjM5LC01ODUgMzU0LjM5LC01ODguNSAzNTQuMzksLTU4MS41Ii8+CjwvZz4KPCEtLSBzcWxzZXJ2ZXImIzQ1O2IgLS0+CjxnIGlkPSJub2RlNjgiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnNxbHNlcnZlci1iPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDc4LC01NDlDNDc4LC01NDkgNDE5LjI1LC01NDkgNDE5LjI1LC01NDkgNDEzLjI1LC01NDkgNDA3LjI1LC01NDMgNDA3LjI1LC01MzcgNDA3LjI1LC01MzcgNDA3LjI1LC01MjUgNDA3LjI1LC01MjUgNDA3LjI1LC01MTkgNDEzLjI1LC01MTMgNDE5LjI1LC01MTMgNDE5LjI1LC01MTMgNDc4LC01MTMgNDc4LC01MTMgNDg0LC01MTMgNDkwLC01MTkgNDkwLC01MjUgNDkwLC01MjUgNDkwLC01MzcgNDkwLC01MzcgNDkwLC01NDMgNDg0LC01NDkgNDc4LC01NDkiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDQ4LjYyIiB5PSItNTI1LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnNxbHNlcnZlci1iPC90ZXh0Pgo8L2c+CjwhLS0gbXNzcWwmIzQ1O2ImIzQ1OyZndDtzcWxzZXJ2ZXImIzQ1O2IgLS0+CjxnIGlkPSJlZGdlNjEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1zc3FsLWItJmd0O3NxbHNlcnZlci1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM1My4xOSwtNTY4LjYzQzM3MC40MSwtNTYxLjc3IDM5MC4zNiwtNTUzLjgyIDQwNy40OCwtNTQ3Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1Mi4yNywtNTY1LjIzIDM0NC4yOCwtNTcyLjE5IDM1NC44NiwtNTcxLjc0IDM1Mi4yNywtNTY1LjIzIi8+CjwvZz4KPCEtLSBtc3NxbCYjNDU7Jmd0O21zc3FsJiM0NTtiIC0tPgo8ZyBpZD0iZWRnZTQ1IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5tc3NxbC0mZ3Q7bXNzcWwtYjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMTcuMzUsLTQ2OC43MUMyMjAuNTgsLTQ3MS4yNCAyMjMuNjIsLTQ3NC4wMSAyMjYuMjUsLTQ3NyAyNTIuMjMsLTUwNi42MiAyMzUuNzUsLTUyOC44NSAyNjIuMjUsLTU1OCAyNjcsLTU2My4yMyAyNzMsLTU2Ny42OSAyNzkuMTQsLTU3MS4zOSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIyMTkuMzksLTQ2NS44NiAyMDkuMTcsLTQ2My4wOCAyMTUuNDIsLTQ3MS42MyAyMTkuMzksLTQ2NS44NiIvPgo8L2c+CjwhLS0gbXNfc3FsIC0tPgo8ZyBpZD0ibm9kZTUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5tc19zcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjguODgsLTU0OUMzMjguODgsLTU0OSAyOTMuMzgsLTU0OSAyOTMuMzgsLTU0OSAyODcuMzgsLTU0OSAyODEuMzgsLTU0MyAyODEuMzgsLTUzNyAyODEuMzgsLTUzNyAyODEuMzgsLTUyNSAyODEuMzgsLTUyNSAyODEuMzgsLTUxOSAyODcuMzgsLTUxMyAyOTMuMzgsLTUxMyAyOTMuMzgsLTUxMyAzMjguODgsLTUxMyAzMjguODgsLTUxMyAzMzQuODgsLTUxMyAzNDAuODgsLTUxOSAzNDAuODgsLTUyNSAzNDAuODgsLTUyNSAzNDAuODgsLTUzNyAzNDAuODgsLTUzNyAzNDAuODgsLTU0MyAzMzQuODgsLTU0OSAzMjguODgsLTU0OSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii01MjUuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+bXNfc3FsPC90ZXh0Pgo8L2c+CjwhLS0gbXNzcWwmIzQ1OyZndDttc19zcWwgLS0+CjxnIGlkPSJlZGdlNDQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1zc3FsLSZndDttc19zcWw8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE3LjUzLC00NzEuMjZDMjIwLjUsLTQ3My4xNiAyMjMuNDQsLTQ3NS4wOSAyMjYuMjUsLTQ3NyAyNDIuOCwtNDg4LjIzIDI0NS41LC00OTMuMDYgMjYyLjI1LC01MDQgMjY4LjMyLC01MDcuOTcgMjc1LjAxLC01MTEuOTYgMjgxLjQxLC01MTUuNjEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjE5LjY2LC00NjguNDYgMjA5LjMzLC00NjYuMTEgMjE1Ljk0LC00NzQuMzkgMjE5LjY2LC00NjguNDYiLz4KPC9nPgo8IS0tIHNxbF9zZXJ2ZXIgLS0+CjxnIGlkPSJub2RlNjUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnNxbF9zZXJ2ZXI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMzguMjUsLTQ5NUMzMzguMjUsLTQ5NSAyODQsLTQ5NSAyODQsLTQ5NSAyNzgsLTQ5NSAyNzIsLTQ4OSAyNzIsLTQ4MyAyNzIsLTQ4MyAyNzIsLTQ3MSAyNzIsLTQ3MSAyNzIsLTQ2NSAyNzgsLTQ1OSAyODQsLTQ1OSAyODQsLTQ1OSAzMzguMjUsLTQ1OSAzMzguMjUsLTQ1OSAzNDQuMjUsLTQ1OSAzNTAuMjUsLTQ2NSAzNTAuMjUsLTQ3MSAzNTAuMjUsLTQ3MSAzNTAuMjUsLTQ4MyAzNTAuMjUsLTQ4MyAzNTAuMjUsLTQ4OSAzNDQuMjUsLTQ5NSAzMzguMjUsLTQ5NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii00NzEuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+c3FsX3NlcnZlcjwvdGV4dD4KPC9nPgo8IS0tIG1zc3FsJiM0NTsmZ3Q7c3FsX3NlcnZlciAtLT4KPGcgaWQ9ImVkZ2U1OCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bXNzcWwtJmd0O3NxbF9zZXJ2ZXI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE5LjAxLC00NTcuNzhDMjM1LjY3LC00NjEuMjkgMjU1LjMzLC00NjUuNDQgMjcyLjEyLC00NjguOTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjIwLjAyLC00NTQuNDIgMjA5LjUxLC00NTUuNzggMjE4LjU3LC00NjEuMjYgMjIwLjAyLC00NTQuNDIiLz4KPC9nPgo8IS0tIHNxbHNlcnZlciAtLT4KPGcgaWQ9Im5vZGU2OSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+c3Fsc2VydmVyPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMzM0LjUsLTQ0MUMzMzQuNSwtNDQxIDI4Ny43NSwtNDQxIDI4Ny43NSwtNDQxIDI4MS43NSwtNDQxIDI3NS43NSwtNDM1IDI3NS43NSwtNDI5IDI3NS43NSwtNDI5IDI3NS43NSwtNDE3IDI3NS43NSwtNDE3IDI3NS43NSwtNDExIDI4MS43NSwtNDA1IDI4Ny43NSwtNDA1IDI4Ny43NSwtNDA1IDMzNC41LC00MDUgMzM0LjUsLTQwNSAzNDAuNSwtNDA1IDM0Ni41LC00MTEgMzQ2LjUsLTQxNyAzNDYuNSwtNDE3IDM0Ni41LC00MjkgMzQ2LjUsLTQyOSAzNDYuNSwtNDM1IDM0MC41LC00NDEgMzM0LjUsLTQ0MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii00MTcuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+c3Fsc2VydmVyPC90ZXh0Pgo8L2c+CjwhLS0gbXNzcWwmIzQ1OyZndDtzcWxzZXJ2ZXIgLS0+CjxnIGlkPSJlZGdlNjIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm1zc3FsLSZndDtzcWxzZXJ2ZXI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE5LjIzLC00NDIuMTdDMjM3LjE0LC00MzguMzkgMjU4LjUsLTQzMy44OSAyNzYsLTQzMC4yIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxOC41NywtNDM4Ljc0IDIwOS41MSwtNDQ0LjIyIDIyMC4wMiwtNDQ1LjU4IDIxOC41NywtNDM4Ljc0Ii8+CjwvZz4KPCEtLSBteXNxbCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU1NSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+bXlzcWwtYjwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMzMS4xMiwtMzg3QzMzMS4xMiwtMzg3IDI5MS4xMiwtMzg3IDI5MS4xMiwtMzg3IDI4NS4xMiwtMzg3IDI3OS4xMiwtMzgxIDI3OS4xMiwtMzc1IDI3OS4xMiwtMzc1IDI3OS4xMiwtMzYzIDI3OS4xMiwtMzYzIDI3OS4xMiwtMzU3IDI4NS4xMiwtMzUxIDI5MS4xMiwtMzUxIDI5MS4xMiwtMzUxIDMzMS4xMiwtMzUxIDMzMS4xMiwtMzUxIDMzNy4xMiwtMzUxIDM0My4xMiwtMzU3IDM0My4xMiwtMzYzIDM0My4xMiwtMzYzIDM0My4xMiwtMzc1IDM0My4xMiwtMzc1IDM0My4xMiwtMzgxIDMzNy4xMiwtMzg3IDMzMS4xMiwtMzg3Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTM2My41NyIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5teXNxbC1iPC90ZXh0Pgo8L2c+CjwhLS0gbXlzcWwmIzQ1OyZndDtteXNxbCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U0NyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+bXlzcWwtJmd0O215c3FsLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE5LjMxLC0zNjlDMjM4LjM1LC0zNjkgMjYxLjI1LC0zNjkgMjc5LjMsLTM2OSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIyMTkuNTQsLTM2NS41IDIwOS41NCwtMzY5IDIxOS41NCwtMzcyLjUgMjE5LjU0LC0zNjUuNSIvPgo8L2c+CjwhLS0gb3JhY2xlJiM0NTtiIC0tPgo8ZyBpZD0ibm9kZTU3IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5vcmFjbGUtYjwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmY2JiYTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMzMS41LC0zMzNDMzMxLjUsLTMzMyAyOTAuNzUsLTMzMyAyOTAuNzUsLTMzMyAyODQuNzUsLTMzMyAyNzguNzUsLTMyNyAyNzguNzUsLTMyMSAyNzguNzUsLTMyMSAyNzguNzUsLTMwOSAyNzguNzUsLTMwOSAyNzguNzUsLTMwMyAyODQuNzUsLTI5NyAyOTAuNzUsLTI5NyAyOTAuNzUsLTI5NyAzMzEuNSwtMjk3IDMzMS41LC0yOTcgMzM3LjUsLTI5NyAzNDMuNSwtMzAzIDM0My41LC0zMDkgMzQzLjUsLTMwOSAzNDMuNSwtMzIxIDM0My41LC0zMjEgMzQzLjUsLTMyNyAzMzcuNSwtMzMzIDMzMS41LC0zMzMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMzA5LjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPm9yYWNsZS1iPC90ZXh0Pgo8L2c+CjwhLS0gb3JhY2xlJiM0NTsmZ3Q7b3JhY2xlJiM0NTtiIC0tPgo8ZyBpZD0iZWRnZTQ5IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5vcmFjbGUtJmd0O29yYWNsZS1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIxOS40OSwtMzE1QzIzOC4zMywtMzE1IDI2MC45MiwtMzE1IDI3OC44MywtMzE1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxOS41NCwtMzExLjUgMjA5LjU0LC0zMTUgMjE5LjU0LC0zMTguNSAyMTkuNTQsLTMxMS41Ii8+CjwvZz4KPCEtLSBvcmFjbGVfZGIgLS0+CjxnIGlkPSJub2RlNTkiIGNsYXNzPSJub2RlIj4KPHRpdGxlPm9yYWNsZV9kYjwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMzNi43NSwtMjc5QzMzNi43NSwtMjc5IDI4NS41LC0yNzkgMjg1LjUsLTI3OSAyNzkuNSwtMjc5IDI3My41LC0yNzMgMjczLjUsLTI2NyAyNzMuNSwtMjY3IDI3My41LC0yNTUgMjczLjUsLTI1NSAyNzMuNSwtMjQ5IDI3OS41LC0yNDMgMjg1LjUsLTI0MyAyODUuNSwtMjQzIDMzNi43NSwtMjQzIDMzNi43NSwtMjQzIDM0Mi43NSwtMjQzIDM0OC43NSwtMjQ5IDM0OC43NSwtMjU1IDM0OC43NSwtMjU1IDM0OC43NSwtMjY3IDM0OC43NSwtMjY3IDM0OC43NSwtMjczIDM0Mi43NSwtMjc5IDMzNi43NSwtMjc5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTI1NS41NyIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5vcmFjbGVfZGI8L3RleHQ+CjwvZz4KPCEtLSBvcmFjbGUmIzQ1OyZndDtvcmFjbGVfZGIgLS0+CjxnIGlkPSJlZGdlNTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm9yYWNsZS0mZ3Q7b3JhY2xlX2RiPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIxOC4zLC0yOTkuNzRDMjM1LjU5LC0yOTIuNDQgMjU2LjI1LC0yODMuNzMgMjczLjU5LC0yNzYuNDEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjE3LjI4LC0yOTYuMzcgMjA5LjQyLC0zMDMuNDggMjIwLC0zMDIuODIgMjE3LjI4LC0yOTYuMzciLz4KPC9nPgo8IS0tIG9yYWNsZV9kYiYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU1OCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+b3JhY2xlX2RiLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00ODAuMjUsLTMzM0M0ODAuMjUsLTMzMyA0MTcsLTMzMyA0MTcsLTMzMyA0MTEsLTMzMyA0MDUsLTMyNyA0MDUsLTMyMSA0MDUsLTMyMSA0MDUsLTMwOSA0MDUsLTMwOSA0MDUsLTMwMyA0MTEsLTI5NyA0MTcsLTI5NyA0MTcsLTI5NyA0ODAuMjUsLTI5NyA0ODAuMjUsLTI5NyA0ODYuMjUsLTI5NyA0OTIuMjUsLTMwMyA0OTIuMjUsLTMwOSA0OTIuMjUsLTMwOSA0OTIuMjUsLTMyMSA0OTIuMjUsLTMyMSA0OTIuMjUsLTMyNyA0ODYuMjUsLTMzMyA0ODAuMjUsLTMzMyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0zMDkuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+b3JhY2xlX2RiLWI8L3RleHQ+CjwvZz4KPCEtLSBvcmFjbGUmIzQ1O2ImIzQ1OyZndDtvcmFjbGVfZGImIzQ1O2IgLS0+CjxnIGlkPSJlZGdlNTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPm9yYWNsZS1iLSZndDtvcmFjbGVfZGItYjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNTQuNDksLTMxNUMzNzAuNjIsLTMxNSAzODguOTksLTMxNSA0MDUuMTMsLTMxNSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTQuNzMsLTMxMS41IDM0NC43MiwtMzE1IDM1NC43MiwtMzE4LjUgMzU0LjczLC0zMTEuNSIvPgo8L2c+CjwhLS0gcG9zdGdyZXNxbCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU2MCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+cG9zdGdyZXNxbC1iPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjYmJhMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNMzQ0LjI1LC0yMjVDMzQ0LjI1LC0yMjUgMjc4LC0yMjUgMjc4LC0yMjUgMjcyLC0yMjUgMjY2LC0yMTkgMjY2LC0yMTMgMjY2LC0yMTMgMjY2LC0yMDEgMjY2LC0yMDEgMjY2LC0xOTUgMjcyLC0xODkgMjc4LC0xODkgMjc4LC0xODkgMzQ0LjI1LC0xODkgMzQ0LjI1LC0xODkgMzUwLjI1LC0xODkgMzU2LjI1LC0xOTUgMzU2LjI1LC0yMDEgMzU2LjI1LC0yMDEgMzU2LjI1LC0yMTMgMzU2LjI1LC0yMTMgMzU2LjI1LC0yMTkgMzUwLjI1LC0yMjUgMzQ0LjI1LC0yMjUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzExLjEyIiB5PSItMjAxLjU3IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnBvc3RncmVzcWwtYjwvdGV4dD4KPC9nPgo8IS0tIHBvc3RncmVzJiM0NTtiIC0tPgo8ZyBpZD0ibm9kZTYxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5wb3N0Z3Jlcy1iPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDc2LjUsLTIyNUM0NzYuNSwtMjI1IDQyMC43NSwtMjI1IDQyMC43NSwtMjI1IDQxNC43NSwtMjI1IDQwOC43NSwtMjE5IDQwOC43NSwtMjEzIDQwOC43NSwtMjEzIDQwOC43NSwtMjAxIDQwOC43NSwtMjAxIDQwOC43NSwtMTk1IDQxNC43NSwtMTg5IDQyMC43NSwtMTg5IDQyMC43NSwtMTg5IDQ3Ni41LC0xODkgNDc2LjUsLTE4OSA0ODIuNSwtMTg5IDQ4OC41LC0xOTUgNDg4LjUsLTIwMSA0ODguNSwtMjAxIDQ4OC41LC0yMTMgNDg4LjUsLTIxMyA0ODguNSwtMjE5IDQ4Mi41LC0yMjUgNDc2LjUsLTIyNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0yMDEuNTciIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+cG9zdGdyZXMtYjwvdGV4dD4KPC9nPgo8IS0tIHBvc3RncmVzcWwmIzQ1O2ImIzQ1OyZndDtwb3N0Z3JlcyYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U1MyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+cG9zdGdyZXNxbC1iLSZndDtwb3N0Z3Jlcy1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM2Ny41NSwtMjA3QzM4MS40MiwtMjA3IDM5Ni4wMSwtMjA3IDQwOC44NywtMjA3Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM2Ny42MywtMjAzLjUgMzU3LjYzLC0yMDcgMzY3LjYzLC0yMTAuNSAzNjcuNjMsLTIwMy41Ii8+CjwvZz4KPCEtLSBwb3N0Z3Jlc3FsJiM0NTsmZ3Q7cG9zdGdyZXNxbCYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U1NSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+cG9zdGdyZXNxbC0mZ3Q7cG9zdGdyZXNxbC1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIzMS4zNSwtMjA3QzI0Mi44MSwtMjA3IDI1NC45MywtMjA3IDI2Ni4xNCwtMjA3Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIzMS43LC0yMDMuNSAyMjEuNywtMjA3IDIzMS43LC0yMTAuNSAyMzEuNywtMjAzLjUiLz4KPC9nPgo8IS0tIHBvc3RncmVzIC0tPgo8ZyBpZD0ibm9kZTYzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5wb3N0Z3JlczwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMzMywtMTcxQzMzMywtMTcxIDI4OS4yNSwtMTcxIDI4OS4yNSwtMTcxIDI4My4yNSwtMTcxIDI3Ny4yNSwtMTY1IDI3Ny4yNSwtMTU5IDI3Ny4yNSwtMTU5IDI3Ny4yNSwtMTQ3IDI3Ny4yNSwtMTQ3IDI3Ny4yNSwtMTQxIDI4My4yNSwtMTM1IDI4OS4yNSwtMTM1IDI4OS4yNSwtMTM1IDMzMywtMTM1IDMzMywtMTM1IDMzOSwtMTM1IDM0NSwtMTQxIDM0NSwtMTQ3IDM0NSwtMTQ3IDM0NSwtMTU5IDM0NSwtMTU5IDM0NSwtMTY1IDMzOSwtMTcxIDMzMywtMTcxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTE0Ny41NyIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5wb3N0Z3JlczwvdGV4dD4KPC9nPgo8IS0tIHBvc3RncmVzcWwmIzQ1OyZndDtwb3N0Z3JlcyAtLT4KPGcgaWQ9ImVkZ2U1NCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+cG9zdGdyZXNxbC0mZ3Q7cG9zdGdyZXM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjMwLjc3LC0xODYuNDhDMjQ2LjQ0LC0xNzkuODcgMjYzLjQxLC0xNzIuNzEgMjc3LjYyLC0xNjYuNzEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI5LjQzLC0xODMuMjQgMjIxLjU4LC0xOTAuMzYgMjMyLjE1LC0xODkuNjkgMjI5LjQzLC0xODMuMjQiLz4KPC9nPgo8IS0tIHNxbGl0ZSYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU2NyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+c3FsaXRlLWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmVlMGQyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjguODgsLTExN0MzMjguODgsLTExNyAyOTMuMzgsLTExNyAyOTMuMzgsLTExNyAyODcuMzgsLTExNyAyODEuMzgsLTExMSAyODEuMzgsLTEwNSAyODEuMzgsLTEwNSAyODEuMzgsLTkzIDI4MS4zOCwtOTMgMjgxLjM4LC04NyAyODcuMzgsLTgxIDI5My4zOCwtODEgMjkzLjM4LC04MSAzMjguODgsLTgxIDMyOC44OCwtODEgMzM0Ljg4LC04MSAzNDAuODgsLTg3IDM0MC44OCwtOTMgMzQwLjg4LC05MyAzNDAuODgsLTEwNSAzNDAuODgsLTEwNSAzNDAuODgsLTExMSAzMzQuODgsLTExNyAzMjguODgsLTExNyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii05My41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj5zcWxpdGUtYjwvdGV4dD4KPC9nPgo8IS0tIHNxbGl0ZSYjNDU7Jmd0O3NxbGl0ZSYjNDU7YiAtLT4KPGcgaWQ9ImVkZ2U1OSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+c3FsaXRlLSZndDtzcWxpdGUtYjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0yMTkuMTcsLTExOC4xOUMyMzkuMDUsLTExMy45OSAyNjMuMTgsLTEwOC45IDI4MS41OSwtMTA1LjAyIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxOC41NywtMTE0Ljc0IDIwOS41MSwtMTIwLjIyIDIyMC4wMiwtMTIxLjU4IDIxOC41NywtMTE0Ljc0Ii8+CjwvZz4KPCEtLSB0ZXh0JiM0NTtiIC0tPgo8ZyBpZD0ibm9kZTc5IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXh0LWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmNiYmExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTgxOUMzMjYuMTIsLTgxOSAyOTYuMTIsLTgxOSAyOTYuMTIsLTgxOSAyOTAuMTIsLTgxOSAyODQuMTIsLTgxMyAyODQuMTIsLTgwNyAyODQuMTIsLTgwNyAyODQuMTIsLTc5NSAyODQuMTIsLTc5NSAyODQuMTIsLTc4OSAyOTAuMTIsLTc4MyAyOTYuMTIsLTc4MyAyOTYuMTIsLTc4MyAzMjYuMTIsLTc4MyAzMjYuMTIsLTc4MyAzMzIuMTIsLTc4MyAzMzguMTIsLTc4OSAzMzguMTIsLTc5NSAzMzguMTIsLTc5NSAzMzguMTIsLTgwNyAzMzguMTIsLTgwNyAzMzguMTIsLTgxMyAzMzIuMTIsLTgxOSAzMjYuMTIsLTgxOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii03OTUuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4dC1iPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7YyYjNDU7Jmd0O3RleHQmIzQ1O2IgLS0+CjxnIGlkPSJlZGdlNzEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRleHQtYy0mZ3Q7dGV4dC1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIxOC40OSwtNzYyLjM0QzIzOS40NywtNzcxLjE5IDI2NS4zNiwtNzgyLjExIDI4NC4yNiwtNzkwLjA5Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIyMCwtNzU5LjE4IDIwOS40MiwtNzU4LjUyIDIxNy4yOCwtNzY1LjYzIDIyMCwtNzU5LjE4Ii8+CjwvZz4KPCEtLSB0ZXh0JiM0NTtiYyAtLT4KPGcgaWQ9Im5vZGU4MCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4dC1iYzwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTMyNy4zOCwtNzY1QzMyNy4zOCwtNzY1IDI5NC44OCwtNzY1IDI5NC44OCwtNzY1IDI4OC44OCwtNzY1IDI4Mi44OCwtNzU5IDI4Mi44OCwtNzUzIDI4Mi44OCwtNzUzIDI4Mi44OCwtNzQxIDI4Mi44OCwtNzQxIDI4Mi44OCwtNzM1IDI4OC44OCwtNzI5IDI5NC44OCwtNzI5IDI5NC44OCwtNzI5IDMyNy4zOCwtNzI5IDMyNy4zOCwtNzI5IDMzMy4zOCwtNzI5IDMzOS4zOCwtNzM1IDMzOS4zOCwtNzQxIDMzOS4zOCwtNzQxIDMzOS4zOCwtNzUzIDMzOS4zOCwtNzUzIDMzOS4zOCwtNzU5IDMzMy4zOCwtNzY1IDMyNy4zOCwtNzY1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMxMS4xMiIgeT0iLTc0MS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50ZXh0LWJjPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7YyYjNDU7Jmd0O3RleHQmIzQ1O2JjIC0tPgo8ZyBpZD0iZWRnZTcyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWMtJmd0O3RleHQtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE5LjQxLC03NDdDMjM5LjczLC03NDcgMjY0LjQ0LC03NDcgMjgyLjk0LC03NDciLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjE5LjU0LC03NDMuNSAyMDkuNTQsLTc0NyAyMTkuNTQsLTc1MC41IDIxOS41NCwtNzQzLjUiLz4KPC9nPgo8IS0tIHRleHQgLS0+CjxnIGlkPSJub2RlODUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRleHQ8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmM5MjcyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTcxMUMzMjYuMTIsLTcxMSAyOTYuMTIsLTcxMSAyOTYuMTIsLTcxMSAyOTAuMTIsLTcxMSAyODQuMTIsLTcwNSAyODQuMTIsLTY5OSAyODQuMTIsLTY5OSAyODQuMTIsLTY4NyAyODQuMTIsLTY4NyAyODQuMTIsLTY4MSAyOTAuMTIsLTY3NSAyOTYuMTIsLTY3NSAyOTYuMTIsLTY3NSAzMjYuMTIsLTY3NSAzMjYuMTIsLTY3NSAzMzIuMTIsLTY3NSAzMzguMTIsLTY4MSAzMzguMTIsLTY4NyAzMzguMTIsLTY4NyAzMzguMTIsLTY5OSAzMzguMTIsLTY5OSAzMzguMTIsLTcwNSAzMzIuMTIsLTcxMSAzMjYuMTIsLTcxMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii02ODcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4dDwvdGV4dD4KPC9nPgo8IS0tIHRleHQmIzQ1O2MmIzQ1OyZndDt0ZXh0IC0tPgo8ZyBpZD0iZWRnZTc4IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWMtJmd0O3RleHQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMjE4LjQ5LC03MzEuNjZDMjM5LjQ3LC03MjIuODEgMjY1LjM2LC03MTEuODkgMjg0LjI2LC03MDMuOTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjE3LjI4LC03MjguMzcgMjA5LjQyLC03MzUuNDggMjIwLC03MzQuODIgMjE3LjI4LC03MjguMzciLz4KPC9nPgo8IS0tIHR4dCYjNDU7YyAtLT4KPGcgaWQ9Im5vZGU5MCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dHh0LWM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik0zMjYuMTIsLTY1N0MzMjYuMTIsLTY1NyAyOTYuMTIsLTY1NyAyOTYuMTIsLTY1NyAyOTAuMTIsLTY1NyAyODQuMTIsLTY1MSAyODQuMTIsLTY0NSAyODQuMTIsLTY0NSAyODQuMTIsLTYzMyAyODQuMTIsLTYzMyAyODQuMTIsLTYyNyAyOTAuMTIsLTYyMSAyOTYuMTIsLTYyMSAyOTYuMTIsLTYyMSAzMjYuMTIsLTYyMSAzMjYuMTIsLTYyMSAzMzIuMTIsLTYyMSAzMzguMTIsLTYyNyAzMzguMTIsLTYzMyAzMzguMTIsLTYzMyAzMzguMTIsLTY0NSAzMzguMTIsLTY0NSAzMzguMTIsLTY1MSAzMzIuMTIsLTY1NyAzMjYuMTIsLTY1NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMTEuMTIiIHk9Ii02MzMuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dHh0LWM8L3RleHQ+CjwvZz4KPCEtLSB0ZXh0JiM0NTtjJiM0NTsmZ3Q7dHh0JiM0NTtjIC0tPgo8ZyBpZD0iZWRnZTgzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWMtJmd0O3R4dC1jPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTIwNC41NSwtNzIwLjgzQzIxOS43OCwtNzAzLjk3IDI0MC45NiwtNjgyLjI1IDI2Mi4yNSwtNjY2IDI2OS4wOCwtNjYwLjc5IDI3Ny4wMiwtNjU1LjkgMjg0LjQ1LC02NTEuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjAyLjE5LC03MTguMjIgMTk4LjE2LC03MjguMDIgMjA3LjQyLC03MjIuODcgMjAyLjE5LC03MTguMjIiLz4KPC9nPgo8IS0tIHR4dCYjNDU7YiAtLT4KPGcgaWQ9Im5vZGU4NiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dHh0LWI8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNjIsLTgxOUM0NjMuNjIsLTgxOSA0MzMuNjIsLTgxOSA0MzMuNjIsLTgxOSA0MjcuNjIsLTgxOSA0MjEuNjIsLTgxMyA0MjEuNjIsLTgwNyA0MjEuNjIsLTgwNyA0MjEuNjIsLTc5NSA0MjEuNjIsLTc5NSA0MjEuNjIsLTc4OSA0MjcuNjIsLTc4MyA0MzMuNjIsLTc4MyA0MzMuNjIsLTc4MyA0NjMuNjIsLTc4MyA0NjMuNjIsLTc4MyA0NjkuNjIsLTc4MyA0NzUuNjIsLTc4OSA0NzUuNjIsLTc5NSA0NzUuNjIsLTc5NSA0NzUuNjIsLTgwNyA0NzUuNjIsLTgwNyA0NzUuNjIsLTgxMyA0NjkuNjIsLTgxOSA0NjMuNjIsLTgxOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii03OTUuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dHh0LWI8L3RleHQ+CjwvZz4KPCEtLSB0ZXh0JiM0NTtiJiM0NTsmZ3Q7dHh0JiM0NTtiIC0tPgo8ZyBpZD0iZWRnZTc5IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWItJmd0O3R4dC1iPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM0OS4zNiwtODAxQzM3Mi40MSwtODAxIDQwMS40MSwtODAxIDQyMS45MiwtODAxIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM0OS40NCwtNzk3LjUgMzM5LjQ0LC04MDEgMzQ5LjQ0LC04MDQuNSAzNDkuNDQsLTc5Ny41Ii8+CjwvZz4KPCEtLSB0eHQmIzQ1O2JjIC0tPgo8ZyBpZD0ibm9kZTg3IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50eHQtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNjIsLTc2NUM0NjMuNjIsLTc2NSA0MzMuNjIsLTc2NSA0MzMuNjIsLTc2NSA0MjcuNjIsLTc2NSA0MjEuNjIsLTc1OSA0MjEuNjIsLTc1MyA0MjEuNjIsLTc1MyA0MjEuNjIsLTc0MSA0MjEuNjIsLTc0MSA0MjEuNjIsLTczNSA0MjcuNjIsLTcyOSA0MzMuNjIsLTcyOSA0MzMuNjIsLTcyOSA0NjMuNjIsLTcyOSA0NjMuNjIsLTcyOSA0NjkuNjIsLTcyOSA0NzUuNjIsLTczNSA0NzUuNjIsLTc0MSA0NzUuNjIsLTc0MSA0NzUuNjIsLTc1MyA0NzUuNjIsLTc1MyA0NzUuNjIsLTc1OSA0NjkuNjIsLTc2NSA0NjMuNjIsLTc2NSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii03NDEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dHh0LWJjPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7YmMmIzQ1OyZndDt0eHQmIzQ1O2JjIC0tPgo8ZyBpZD0iZWRnZTgwIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWJjLSZndDt0eHQtYmM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzUwLjYsLTc0N0MzNzMuNDUsLTc0NyA0MDEuODEsLTc0NyA0MjEuOTUsLTc0NyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIzNTAuNzMsLTc0My41IDM0MC43MywtNzQ3IDM1MC43MywtNzUwLjUgMzUwLjczLC03NDMuNSIvPgo8L2c+CjwhLS0gdGV4dCYjNDU7YmNlIC0tPgo8ZyBpZD0ibm9kZTgyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXh0LWJjZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTQ2OC42MiwtMTQxM0M0NjguNjIsLTE0MTMgNDI4LjYyLC0xNDEzIDQyOC42MiwtMTQxMyA0MjIuNjIsLTE0MTMgNDE2LjYyLC0xNDA3IDQxNi42MiwtMTQwMSA0MTYuNjIsLTE0MDEgNDE2LjYyLC0xMzg5IDQxNi42MiwtMTM4OSA0MTYuNjIsLTEzODMgNDIyLjYyLC0xMzc3IDQyOC42MiwtMTM3NyA0MjguNjIsLTEzNzcgNDY4LjYyLC0xMzc3IDQ2OC42MiwtMTM3NyA0NzQuNjIsLTEzNzcgNDgwLjYyLC0xMzgzIDQ4MC42MiwtMTM4OSA0ODAuNjIsLTEzODkgNDgwLjYyLC0xNDAxIDQ4MC42MiwtMTQwMSA0ODAuNjIsLTE0MDcgNDc0LjYyLC0xNDEzIDQ2OC42MiwtMTQxMyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii0xMzg5LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnRleHQtYmNlPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7Y2UmIzQ1OyZndDt0ZXh0JiM0NTtiY2UgLS0+CjxnIGlkPSJlZGdlNzMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRleHQtY2UtJmd0O3RleHQtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM1MC4zNCwtMTM3NS42MUMzNzEuMzUsLTEzNzkuOCAzOTcuMDcsLTEzODQuOTMgNDE2Ljc5LC0xMzg4Ljg2Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM1MS4yLC0xMzcyLjIyIDM0MC43LC0xMzczLjY5IDM0OS44MywtMTM3OS4wOCAzNTEuMiwtMTM3Mi4yMiIvPgo8L2c+CjwhLS0gdGV4dCYjNDU7ZSAtLT4KPGcgaWQ9Im5vZGU4NCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGV4dC1lPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjYmJhMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDYzLjYyLC0xMzU5QzQ2My42MiwtMTM1OSA0MzMuNjIsLTEzNTkgNDMzLjYyLC0xMzU5IDQyNy42MiwtMTM1OSA0MjEuNjIsLTEzNTMgNDIxLjYyLC0xMzQ3IDQyMS42MiwtMTM0NyA0MjEuNjIsLTEzMzUgNDIxLjYyLC0xMzM1IDQyMS42MiwtMTMyOSA0MjcuNjIsLTEzMjMgNDMzLjYyLC0xMzIzIDQzMy42MiwtMTMyMyA0NjMuNjIsLTEzMjMgNDYzLjYyLC0xMzIzIDQ2OS42MiwtMTMyMyA0NzUuNjIsLTEzMjkgNDc1LjYyLC0xMzM1IDQ3NS42MiwtMTMzNSA0NzUuNjIsLTEzNDcgNDc1LjYyLC0xMzQ3IDQ3NS42MiwtMTM1MyA0NjkuNjIsLTEzNTkgNDYzLjYyLC0xMzU5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTEzMzUuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dGV4dC1lPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7Y2UmIzQ1OyZndDt0ZXh0JiM0NTtlIC0tPgo8ZyBpZD0iZWRnZTc3IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWNlLSZndDt0ZXh0LWU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzUwLjI4LC0xMzYwLjRDMzczLjE5LC0xMzU1LjgzIDQwMS43MiwtMTM1MC4xNSA0MjEuOTUsLTEzNDYuMTIiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMzQ5LjgzLC0xMzU2LjkyIDM0MC43LC0xMzYyLjMxIDM1MS4yLC0xMzYzLjc4IDM0OS44MywtMTM1Ni45MiIvPgo8L2c+CjwhLS0gdHh0JiM0NTtjZSAtLT4KPGcgaWQ9Im5vZGU5MSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dHh0LWNlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNDYzLjYyLC0xMzA1QzQ2My42MiwtMTMwNSA0MzMuNjIsLTEzMDUgNDMzLjYyLC0xMzA1IDQyNy42MiwtMTMwNSA0MjEuNjIsLTEyOTkgNDIxLjYyLC0xMjkzIDQyMS42MiwtMTI5MyA0MjEuNjIsLTEyODEgNDIxLjYyLC0xMjgxIDQyMS42MiwtMTI3NSA0MjcuNjIsLTEyNjkgNDMzLjYyLC0xMjY5IDQzMy42MiwtMTI2OSA0NjMuNjIsLTEyNjkgNDYzLjYyLC0xMjY5IDQ2OS42MiwtMTI2OSA0NzUuNjIsLTEyNzUgNDc1LjYyLC0xMjgxIDQ3NS42MiwtMTI4MSA0NzUuNjIsLTEyOTMgNDc1LjYyLC0xMjkzIDQ3NS42MiwtMTI5OSA0NjkuNjIsLTEzMDUgNDYzLjYyLC0xMzA1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ0OC42MiIgeT0iLTEyODEuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dHh0LWNlPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7Y2UmIzQ1OyZndDt0eHQmIzQ1O2NlIC0tPgo8ZyBpZD0iZWRnZTg0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXh0LWNlLSZndDt0eHQtY2U8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMzQ3LjgyLC0xMzQ0LjAxQzM2Mi41NSwtMTMzNC4zOCAzNzkuOTEsLTEzMjMuMzYgMzk2LC0xMzE0IDQwNC4yMiwtMTMwOS4yMiA0MTMuMzYsLTEzMDQuMzEgNDIxLjY0LC0xMzAwLjAxIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM0Ni4yNSwtMTM0MC44NSAzMzkuODMsLTEzNDkuMjggMzUwLjEsLTEzNDYuNyAzNDYuMjUsLTEzNDAuODUiLz4KPC9nPgo8IS0tIHRleHQmIzQ1O2JlIC0tPgo8ZyBpZD0ibm9kZTgzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXh0LWJlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZjYmJhMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjAzLjEyLC0xNDEzQzYwMy4xMiwtMTQxMyA1NjkuODgsLTE0MTMgNTY5Ljg4LC0xNDEzIDU2My44OCwtMTQxMyA1NTcuODgsLTE0MDcgNTU3Ljg4LC0xNDAxIDU1Ny44OCwtMTQwMSA1NTcuODgsLTEzODkgNTU3Ljg4LC0xMzg5IDU1Ny44OCwtMTM4MyA1NjMuODgsLTEzNzcgNTY5Ljg4LC0xMzc3IDU2OS44OCwtMTM3NyA2MDMuMTIsLTEzNzcgNjAzLjEyLC0xMzc3IDYwOS4xMiwtMTM3NyA2MTUuMTIsLTEzODMgNjE1LjEyLC0xMzg5IDYxNS4xMiwtMTM4OSA2MTUuMTIsLTE0MDEgNjE1LjEyLC0xNDAxIDYxNS4xMiwtMTQwNyA2MDkuMTIsLTE0MTMgNjAzLjEyLC0xNDEzIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU4Ni41IiB5PSItMTM4OS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50ZXh0LWJlPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7YmNlJiM0NTsmZ3Q7dGV4dCYjNDU7YmUgLS0+CjxnIGlkPSJlZGdlNzQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRleHQtYmNlLSZndDt0ZXh0LWJlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ5MS45NCwtMTM5NUM1MTMuNDksLTEzOTUgNTM5LjA2LC0xMzk1IDU1OC4wMiwtMTM5NSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0OTEuOTcsLTEzOTEuNSA0ODEuOTcsLTEzOTUgNDkxLjk3LC0xMzk4LjUgNDkxLjk3LC0xMzkxLjUiLz4KPC9nPgo8IS0tIHR4dCYjNDU7YmNlIC0tPgo8ZyBpZD0ibm9kZTg4IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50eHQtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0iI2ZmZjVmMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIwIiBkPSJNNjAyLjc1LC0xMzU5QzYwMi43NSwtMTM1OSA1NzAuMjUsLTEzNTkgNTcwLjI1LC0xMzU5IDU2NC4yNSwtMTM1OSA1NTguMjUsLTEzNTMgNTU4LjI1LC0xMzQ3IDU1OC4yNSwtMTM0NyA1NTguMjUsLTEzMzUgNTU4LjI1LC0xMzM1IDU1OC4yNSwtMTMyOSA1NjQuMjUsLTEzMjMgNTcwLjI1LC0xMzIzIDU3MC4yNSwtMTMyMyA2MDIuNzUsLTEzMjMgNjAyLjc1LC0xMzIzIDYwOC43NSwtMTMyMyA2MTQuNzUsLTEzMjkgNjE0Ljc1LC0xMzM1IDYxNC43NSwtMTMzNSA2MTQuNzUsLTEzNDcgNjE0Ljc1LC0xMzQ3IDYxNC43NSwtMTM1MyA2MDguNzUsLTEzNTkgNjAyLjc1LC0xMzU5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU4Ni41IiB5PSItMTMzNS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50eHQtYmNlPC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7YmNlJiM0NTsmZ3Q7dHh0JiM0NTtiY2UgLS0+CjxnIGlkPSJlZGdlODEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRleHQtYmNlLSZndDt0eHQtYmNlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTQ5MS4xMiwtMTM3OC41MUM1MTMuMDEsLTEzNjkuODEgNTM5LjIyLC0xMzU5LjM5IDU1OC40NywtMTM1MS43NCIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0ODkuODYsLTEzNzUuMjQgNDgxLjg2LC0xMzgyLjE5IDQ5Mi40NSwtMTM4MS43NSA0ODkuODYsLTEzNzUuMjQiLz4KPC9nPgo8IS0tIHR4dCYjNDU7YmUgLS0+CjxnIGlkPSJub2RlODkiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnR4dC1iZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTcxNS43NSwtMTQxM0M3MTUuNzUsLTE0MTMgNjg1Ljc1LC0xNDEzIDY4NS43NSwtMTQxMyA2NzkuNzUsLTE0MTMgNjczLjc1LC0xNDA3IDY3My43NSwtMTQwMSA2NzMuNzUsLTE0MDEgNjczLjc1LC0xMzg5IDY3My43NSwtMTM4OSA2NzMuNzUsLTEzODMgNjc5Ljc1LC0xMzc3IDY4NS43NSwtMTM3NyA2ODUuNzUsLTEzNzcgNzE1Ljc1LC0xMzc3IDcxNS43NSwtMTM3NyA3MjEuNzUsLTEzNzcgNzI3Ljc1LC0xMzgzIDcyNy43NSwtMTM4OSA3MjcuNzUsLTEzODkgNzI3Ljc1LC0xNDAxIDcyNy43NSwtMTQwMSA3MjcuNzUsLTE0MDcgNzIxLjc1LC0xNDEzIDcxNS43NSwtMTQxMyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI3MDAuNzUiIHk9Ii0xMzg5LjU4IiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQuMDAiPnR4dC1iZTwvdGV4dD4KPC9nPgo8IS0tIHRleHQmIzQ1O2JlJiM0NTsmZ3Q7dHh0JiM0NTtiZSAtLT4KPGcgaWQ9ImVkZ2U4MiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGV4dC1iZS0mZ3Q7dHh0LWJlPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTYyNi4wNywtMTM5NUM2NDEuOTQsLTEzOTUgNjU5LjksLTEzOTUgNjc0LjExLC0xMzk1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjYyNi40NywtMTM5MS41IDYxNi40NywtMTM5NSA2MjYuNDcsLTEzOTguNSA2MjYuNDcsLTEzOTEuNSIvPgo8L2c+CjwhLS0gdHh0JiM0NTtlIC0tPgo8ZyBpZD0ibm9kZTkyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50eHQtZTwvdGl0bGU+CjxwYXRoIGZpbGw9IiNmZmY1ZjAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMCIgZD0iTTYwMS41LC0xMzA1QzYwMS41LC0xMzA1IDU3MS41LC0xMzA1IDU3MS41LC0xMzA1IDU2NS41LC0xMzA1IDU1OS41LC0xMjk5IDU1OS41LC0xMjkzIDU1OS41LC0xMjkzIDU1OS41LC0xMjgxIDU1OS41LC0xMjgxIDU1OS41LC0xMjc1IDU2NS41LC0xMjY5IDU3MS41LC0xMjY5IDU3MS41LC0xMjY5IDYwMS41LC0xMjY5IDYwMS41LC0xMjY5IDYwNy41LC0xMjY5IDYxMy41LC0xMjc1IDYxMy41LC0xMjgxIDYxMy41LC0xMjgxIDYxMy41LC0xMjkzIDYxMy41LC0xMjkzIDYxMy41LC0xMjk5IDYwNy41LC0xMzA1IDYwMS41LC0xMzA1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU4Ni41IiB5PSItMTI4MS41OCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0LjAwIj50eHQtZTwvdGV4dD4KPC9nPgo8IS0tIHRleHQmIzQ1O2UmIzQ1OyZndDt0eHQmIzQ1O2UgLS0+CjxnIGlkPSJlZGdlODUiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRleHQtZS0mZ3Q7dHh0LWU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNDg2LjAyLC0xMzI2LjU0QzUwOS4yNywtMTMxNy4yOSA1MzguODcsLTEzMDUuNTMgNTU5LjcyLC0xMjk3LjI1Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjQ4NC45MSwtMTMyMy4yMSA0NzYuOTEsLTEzMzAuMTYgNDg3LjQ5LC0xMzI5LjcyIDQ4NC45MSwtMTMyMy4yMSIvPgo8L2c+CjwhLS0gdHh0IC0tPgo8ZyBpZD0ibm9kZTkzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50eHQ8L3RpdGxlPgo8cGF0aCBmaWxsPSIjZmZmNWYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIGQ9Ik00NjMuNjIsLTcxMUM0NjMuNjIsLTcxMSA0MzMuNjIsLTcxMSA0MzMuNjIsLTcxMSA0MjcuNjIsLTcxMSA0MjEuNjIsLTcwNSA0MjEuNjIsLTY5OSA0MjEuNjIsLTY5OSA0MjEuNjIsLTY4NyA0MjEuNjIsLTY4NyA0MjEuNjIsLTY4MSA0MjcuNjIsLTY3NSA0MzMuNjIsLTY3NSA0MzMuNjIsLTY3NSA0NjMuNjIsLTY3NSA0NjMuNjIsLTY3NSA0NjkuNjIsLTY3NSA0NzUuNjIsLTY4MSA0NzUuNjIsLTY4NyA0NzUuNjIsLTY4NyA0NzUuNjIsLTY5OSA0NzUuNjIsLTY5OSA0NzUuNjIsLTcwNSA0NjkuNjIsLTcxMSA0NjMuNjIsLTcxMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NDguNjIiIHk9Ii02ODcuNTgiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNC4wMCI+dHh0PC90ZXh0Pgo8L2c+CjwhLS0gdGV4dCYjNDU7Jmd0O3R4dCAtLT4KPGcgaWQ9ImVkZ2U4NiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGV4dC0mZ3Q7dHh0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTM0OS4zNiwtNjkzQzM3Mi40MSwtNjkzIDQwMS40MSwtNjkzIDQyMS45MiwtNjkzIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjM0OS40NCwtNjg5LjUgMzM5LjQ0LC02OTMgMzQ5LjQ0LC02OTYuNSAzNDkuNDQsLTY4OS41Ii8+CjwvZz4KPC9nPgo8L3N2Zz4=\"/>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Les teintes les plus foncées correspondent approximativement aux gabarits les plus complexes. Les autres ne sont souvent que des alias, par exemple, <code>tex.yaml</code> renvoie directement à <code>latex.yaml</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [189]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Code</span><span class=\"p\">(</span><span class=\"s2\">\"../../mocodo/resources/relation_templates/tex.yaml\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[189]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #FF0000 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #0044DD } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.output_html .no { color: #880000 } /* Name.Constant */\n.output_html .nd { color: #AA22FF } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #0000FF } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #bbbbbb } /* Text.Whitespace */\n.output_html .mb { color: #666666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666666 } /* Literal.Number.Float */\n.output_html .mh { color: #666666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #0000FF } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"nt\">parent</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex'</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La clé <code>\"parent\"</code> donne le chemin ou le nom du gabarit dont on souhaite créer une version dérivée :</p>\n<ul>\n<li>une chaîne terminée par <code>.yaml</code> est interprétée comme un chemin ;</li>\n<li>sinon, comme le nom d'un gabarit de la distribution.</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Tous les gabarits textuels (<code>text.yaml</code>, <code>latex.yaml</code>, <code>markdown.yaml</code>, <code>html.yaml</code> et leurs alias) dérivent des gabarits <code>html-c.yaml</code> (version avec affichage des contraintes) et <code>html-ce.yaml</code> (version avec affichage des contraintes et des explications).</p>\n<p>Par exemple, le gabarit <code>latex</code> se borne à ajouter un message d'aide pour la ligne de commande et à empêcher l'ajout des contraintes d'unicité et d'optionalité :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [190]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Code</span><span class=\"p\">(</span><span class=\"s2\">\"../../mocodo/resources/relation_templates/latex.yaml\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[190]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #FF0000 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #0044DD } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.output_html .no { color: #880000 } /* Name.Constant */\n.output_html .nd { color: #AA22FF } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #0000FF } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #bbbbbb } /* Text.Whitespace */\n.output_html .mb { color: #666666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666666 } /* Literal.Number.Float */\n.output_html .mh { color: #666666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #0000FF } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"nt\">help_en</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'convert</span><span class=\"nv\"> </span><span class=\"s\">the</span><span class=\"nv\"> </span><span class=\"s\">conceptual</span><span class=\"nv\"> </span><span class=\"s\">model</span><span class=\"nv\"> </span><span class=\"s\">into</span><span class=\"nv\"> </span><span class=\"s\">a</span><span class=\"nv\"> </span><span class=\"s\">relational</span><span class=\"nv\"> </span><span class=\"s\">schema</span><span class=\"nv\"> </span><span class=\"s\">in</span><span class=\"nv\"> </span><span class=\"s\">LaTeX</span><span class=\"nv\"> </span><span class=\"s\">format'</span>\n<span class=\"nt\">help_fr</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'convertit</span><span class=\"nv\"> </span><span class=\"s\">le</span><span class=\"nv\"> </span><span class=\"s\">modèle</span><span class=\"nv\"> </span><span class=\"s\">conceptuel</span><span class=\"nv\"> </span><span class=\"s\">en</span><span class=\"nv\"> </span><span class=\"s\">un</span><span class=\"nv\"> </span><span class=\"s\">schéma</span><span class=\"nv\"> </span><span class=\"s\">relationnel</span><span class=\"nv\"> </span><span class=\"s\">au</span><span class=\"nv\"> </span><span class=\"s\">format</span><span class=\"nv\"> </span><span class=\"s\">LaTeX'</span>\n<span class=\"nt\">help_zh</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'将概念模型转换为</span><span class=\"nv\"> </span><span class=\"s\">LaTeX</span><span class=\"nv\"> </span><span class=\"s\">格式的关系模式'</span>\n<span class=\"nt\">fr_examples</span><span class=\"p\">:</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1</span>\n<span class=\"w\">    </span><span class=\"nt\">example</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex'</span>\n<span class=\"w\">    </span><span class=\"nt\">explanation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'version</span><span class=\"nv\"> </span><span class=\"s\">de</span><span class=\"nv\"> </span><span class=\"s\">base'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">2</span>\n<span class=\"w\">    </span><span class=\"nt\">example</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex:b'</span>\n<span class=\"w\">    </span><span class=\"nt\">explanation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'avec</span><span class=\"nv\"> </span><span class=\"s\">_boilerplate_'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">3</span>\n<span class=\"w\">    </span><span class=\"nt\">example</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex:c'</span>\n<span class=\"w\">    </span><span class=\"nt\">explanation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'avec</span><span class=\"nv\"> </span><span class=\"s\">contraintes</span><span class=\"nv\"> </span><span class=\"s\">d</span><span class=\"se\">''</span><span class=\"s\">unicité</span><span class=\"nv\"> </span><span class=\"s\">et</span><span class=\"nv\"> </span><span class=\"s\">d</span><span class=\"se\">''</span><span class=\"s\">optionalité'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">4</span>\n<span class=\"w\">    </span><span class=\"nt\">example</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex:e'</span>\n<span class=\"w\">    </span><span class=\"nt\">explanation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'avec</span><span class=\"nv\"> </span><span class=\"s\">explications'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">5</span>\n<span class=\"w\">    </span><span class=\"nt\">example</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex:bce'</span>\n<span class=\"w\">    </span><span class=\"nt\">explanation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'avec</span><span class=\"nv\"> </span><span class=\"s\">_boilerplate_,</span><span class=\"nv\"> </span><span class=\"s\">contraintes</span><span class=\"nv\"> </span><span class=\"s\">et</span><span class=\"nv\"> </span><span class=\"s\">explications'</span>\n<span class=\"nt\">parent</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex-c'</span>\n<span class=\"nt\">add_unicity_constraints</span><span class=\"p\">:</span>\n<span class=\"nt\">add_optionality_constraints</span><span class=\"p\">:</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Si maintenant on regarde le contenu de son parent <code>latex-c</code> :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [191]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"n\">display</span><span class=\"o\">.</span><span class=\"n\">Code</span><span class=\"p\">(</span><span class=\"s2\">\"../../mocodo/resources/relation_templates/latex-c.yaml\"</span><span class=\"p\">)</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child jp-OutputArea-executeResult\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\">Out[191]:</div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output jp-OutputArea-executeResult\" data-mime-type=\"text/html\" tabindex=\"0\">\n<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #FF0000 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #0044DD } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.output_html .no { color: #880000 } /* Name.Constant */\n.output_html .nd { color: #AA22FF } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #0000FF } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #bbbbbb } /* Text.Whitespace */\n.output_html .mb { color: #666666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666666 } /* Literal.Number.Float */\n.output_html .mh { color: #666666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #0000FF } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"nt\">parent</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'html-c'</span>\n<span class=\"nt\">extension</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'tex'</span>\n<span class=\"nt\">highlight</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'latex'</span>\n<span class=\"nt\">column_separator</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">',</span><span class=\"nv\"> </span><span class=\"s\">'</span>\n<span class=\"nt\">compose_relation</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'</span><span class=\"nv\">  </span><span class=\"s\">\\item</span><span class=\"nv\"> </span><span class=\"s\">\\relat{{{this_relation_name}}}</span><span class=\"nv\"> </span><span class=\"s\">({columns})'</span>\n<span class=\"nt\">compose_relational_schema</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'%</span><span class=\"nv\"> </span><span class=\"s\">Generated</span><span class=\"nv\"> </span><span class=\"s\">by</span><span class=\"nv\"> </span><span class=\"s\">Mocodo</span><span class=\"nv\"> </span><span class=\"s\">{version}\\n\\n\\begin{{itemize}}\\n{relations}\\n\\end{{itemize}}\\n'</span>\n<span class=\"nt\">transform_relation</span><span class=\"p\">:</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1000</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Compose</span><span class=\"nv\"> </span><span class=\"s\">normal</span><span class=\"nv\"> </span><span class=\"s\">attributes'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'&lt;span</span><span class=\"nv\"> </span><span class=\"s\">class=</span><span class=\"se\">''</span><span class=\"s\">normal</span><span class=\"se\">''</span><span class=\"s\">&gt;(.+?)&lt;/span&gt;'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\\\attr{\\1}'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1100</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Compose</span><span class=\"nv\"> </span><span class=\"s\">primary</span><span class=\"nv\"> </span><span class=\"s\">keys'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'&lt;span</span><span class=\"nv\"> </span><span class=\"s\">class=</span><span class=\"se\">''</span><span class=\"s\">primary</span><span class=\"se\">''</span><span class=\"s\">&gt;(.+?)&lt;/span&gt;'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\\\prim{\\1}'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1200</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Compose</span><span class=\"nv\"> </span><span class=\"s\">foreign</span><span class=\"nv\"> </span><span class=\"s\">primary</span><span class=\"nv\"> </span><span class=\"s\">keys'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'&lt;span</span><span class=\"nv\"> </span><span class=\"s\">class=</span><span class=\"se\">''</span><span class=\"s\">foreign</span><span class=\"nv\"> </span><span class=\"s\">primary</span><span class=\"se\">''</span><span class=\"s\">&gt;#(.+?)&lt;/span&gt;'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\\\foreign{\\\\prim{\\1}}'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1300</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Compose</span><span class=\"nv\"> </span><span class=\"s\">foreign</span><span class=\"nv\"> </span><span class=\"s\">attributes'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'&lt;span</span><span class=\"nv\"> </span><span class=\"s\">class=</span><span class=\"se\">''</span><span class=\"s\">foreign</span><span class=\"se\">''</span><span class=\"s\">&gt;#(.+?)&lt;/span&gt;'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\\\foreign{\\1}'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1400</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Exponents'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'(&lt;sup&gt;.*u)(\\d)(.*&lt;/sup&gt;)'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\1_\\2\\3'</span>\n<span class=\"w\">    </span><span class=\"nt\">iterated</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">true</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1500</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Exponents'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'</span><span class=\"nv\"> </span><span class=\"s\">&lt;sup&gt;(.+?)&lt;/sup&gt;'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'$^{\\1}$'</span>\n<span class=\"w\">  </span><span class=\"p p-Indicator\">-</span><span class=\"w\"> </span><span class=\"nt\">order</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"l l-Scalar l-Scalar-Plain\">1600</span>\n<span class=\"w\">    </span><span class=\"nt\">comment</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'Escape</span><span class=\"nv\"> </span><span class=\"s\">underlines'</span>\n<span class=\"w\">    </span><span class=\"nt\">search</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'_'</span>\n<span class=\"w\">    </span><span class=\"nt\">replace</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"s\">'\\_'</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>... on voit que les opérations consistent simplement à modifier le séparateur de colonne, à composer les tables et le schéma relationnel complet avec un <em>boilerplate</em>, et enfin à remplacer les balises HTML par leur équivalent en  $\\LaTeX$. Toute la logique complexe est traitée dans le gabarit <code>html-c</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"Exemples-de-cr%C3%A9ation-de-gabarit-d%C3%A9riv%C3%A9-\">Exemples de création de gabarit dérivé <a id=\"t_relation\"></a><a class=\"anchor-link\" href=\"#Exemples-de-cr%C3%A9ation-de-gabarit-d%C3%A9riv%C3%A9-\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le gabarit SQL par défaut rend explicite la contrainte <code>NOT NULL</code> des clés primaires :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [192]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%</span><span class=\"k\">mocodo</span> -t sql\nPERSONNE: id. personne [VARCHAR(8)], nom [VARCHAR(255)]\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">PERSONNE</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">id_personne</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">id_personne</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">  </span><span class=\"n\">nom</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Supposons que cette redondance nous défrise, et voyons comment l'éliminer. Pour cela, examinons le contenu du gabarit <code>sql.yaml</code> :</p>\n<p><img alt=\"\" src=\"examples/sql_template_1.png\"/></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>La contrainte d'optionalité <code>{optionality}</code> apparaît à côté de <code>PRIMARY KEY</code> en lignes 28 et 31. Nous pouvons donc simplement remplacer les valeurs associées à <code>compose_primary_key</code> et <code>compose_primary_foreign_key</code> par des copies supprimant cette mention :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [193]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%file</span> new_sql.yaml\n<span class=\"n\">parent</span><span class=\"p\">:</span> <span class=\"s1\">'sql'</span>\n<span class=\"n\">compose_primary_key</span><span class=\"p\">:</span> <span class=\"s1\">'</span><span class=\"si\">{label}</span><span class=\"s1\"> </span><span class=\"si\">{datatype}</span><span class=\"se\">\\n</span><span class=\"s1\">PRIMARY KEY (</span><span class=\"si\">{label}</span><span class=\"s1\">)'</span>\n<span class=\"n\">compose_primary_foreign_key</span><span class=\"p\">:</span> <span class=\"s1\">'</span><span class=\"si\">{label}</span><span class=\"s1\"> </span><span class=\"si\">{datatype}</span><span class=\"se\">\\n</span><span class=\"s1\">PRIMARY KEY (</span><span class=\"si\">{label}</span><span class=\"s1\">)</span><span class=\"se\">\\n</span><span class=\"s1\">FOREIGN KEY (</span><span class=\"si\">{label}</span><span class=\"s1\">) REFERENCES </span><span class=\"si\">{outer_source}</span><span class=\"s1\"> (</span><span class=\"si\">{non_disambiguated_label}</span><span class=\"s1\">)'</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>Overwriting new_sql.yaml\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Pour tester ce nouveau gabarit, nous devons ajouter la sous-option <code>-t relation</code> avec en sous-argument le chemin complet du fichier créé :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [194]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t relation:new_sql.yaml\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">PERSONNE</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">id_personne</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">id_personne</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">nom</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Mission accomplie !</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Nous aurions pu procéder autrement. Reprenons le gabarit original :</p>\n<p><img alt=\"\" src=\"examples/sql_template_2.png\"/></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le dictionnaire <code>transform_relation</code> spécifie une séquence de réécritures à appliquer à chacune des clauses <code>CREATE TABLE</code> (composées ligne 37). La première accumule toutes les lignes contenant <code>PRIMARY KEY</code> en fin de table (où elles seront concaténées avant d'être ramenées au début). Nous devons donc intervenir <em>avant</em> que <code>NOT NULL</code> ne soit séparé de <code>PRIMARY KEY</code>. Pour cela, définissons un gabarit qui se borne à <strong>insérer</strong> avant cette transformation (de numéro d'ordre 100) une suppression des <code>NOT NULL</code> incriminés :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [195]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%%file</span> new_sql.yaml\n<span class=\"n\">parent</span><span class=\"p\">:</span> <span class=\"s1\">'sql'</span>\n<span class=\"n\">transform_relation</span><span class=\"p\">:</span>\n  <span class=\"o\">-</span> <span class=\"n\">order</span><span class=\"p\">:</span> <span class=\"mi\">50</span>\n    <span class=\"n\">comment</span><span class=\"p\">:</span> <span class=\"s1\">'Suppress PK NN redundancy.'</span>\n    <span class=\"n\">search</span><span class=\"p\">:</span> <span class=\"s1\">' NOT NULL</span><span class=\"se\">\\n</span><span class=\"s1\">PRIMARY KEY'</span>\n    <span class=\"n\">replace</span><span class=\"p\">:</span> <span class=\"s1\">'</span><span class=\"se\">\\n</span><span class=\"s1\">PRIMARY KEY'</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedText jp-OutputArea-output\" data-mime-type=\"text/plain\" tabindex=\"0\">\n<pre>Overwriting new_sql.yaml\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le résultat est le même :</p>\n</div>\n</div>\n</div>\n</div><div class=\"jp-Cell jp-CodeCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\">\n<div class=\"jp-InputPrompt jp-InputArea-prompt\">In [196]:</div>\n<div class=\"jp-CodeMirrorEditor jp-Editor jp-InputArea-editor\" data-type=\"inline\">\n<div class=\"cm-editor cm-s-jupyter\">\n<div class=\"highlight hl-ipython3\"><pre><span></span><span class=\"o\">%</span><span class=\"k\">mocodo</span> -i sandbox -t relation:new_sql.yaml\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell-outputWrapper\">\n<div class=\"jp-Collapser jp-OutputCollapser jp-Cell-outputCollapser\">\n</div>\n<div class=\"jp-OutputArea jp-Cell-outputArea\">\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n<hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\"/>\n<span style=\"position: absolute; right: 0; color: #BBB\">\n<tt>\nsandbox_ddl.sql\n</tt>\n</span>\n</div>\n</div>\n</div>\n<div class=\"jp-OutputArea-child\">\n<div class=\"jp-OutputPrompt jp-OutputArea-prompt\"></div>\n<div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output\" data-mime-type=\"text/markdown\" tabindex=\"0\">\n<div class=\"highlight\"><pre><span></span><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"n\">PERSONNE</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">  </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">id_personne</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">id_personne</span><span class=\"w\"> </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">8</span><span class=\"p\">),</span>\n<span class=\"w\">  </span><span class=\"n\">nom</span><span class=\"w\">         </span><span class=\"nb\">VARCHAR</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n<span class=\"p\">);</span>\n</pre></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p><strong>NB.</strong> Les gabarits définis par l'utilisateur n'ont <strong>pas</strong> vocation à être placés dans le répertoire <code>relation_templates</code> de la distribution. Votre nouveau gabarit <code>new_sql</code> ne peut donc pas être invoqué aussi simplement que les gabarits officiels (i.e., avec <code>-t new_sql</code>). Si vous faites une modification ou un ajout que vous voulez voir inclus dans la distribution, n'hésitez pas à faire une PR.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h3 id=\"M%C3%A9canisme-de-mise-%C3%A0-jour\">Mécanisme de mise à jour<a class=\"anchor-link\" href=\"#M%C3%A9canisme-de-mise-%C3%A0-jour\">¶</a></h3>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<p>Le mécanisme de mise à jour des clés dépend de la scalarité de leur valeur associée.</p>\n<p><strong>Cas scalaire.</strong></p>\n<p>Pour les valeurs scalaires (chaînes, nombres, booléens, <code>null</code>), selon la présence d'une entrée donnée dans le gabarit enfant et/ou le gabarit parent, l'association clé-valeur correspondante sera créée, mise à jour ou conservée :</p>\n<table>\n<thead>\n<tr>\n<th>enfant</th>\n<th>parent</th>\n<th>résultat</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>oui</td>\n<td>non</td>\n<td>création</td>\n</tr>\n<tr>\n<td>oui</td>\n<td>oui</td>\n<td>mise à jour</td>\n</tr>\n<tr>\n<td>non</td>\n<td>oui</td>\n<td>conservation</td>\n</tr>\n</tbody>\n</table>\n<p>Il n'y a pas de moyen de supprimer une association clé-valeur, mais étant donné que toutes celles qui sont absentes se voient substituer une association par défaut, il est équivalent de spécifier explicitement la valeur-défaut.</p>\n<p><strong>Cas non scalaire.</strong></p>\n<p>Dans les gabarits de relations de Mocodo, une seule catégorie de valeur non scalaire est possible : la liste de dictionnaires. Dans l'exemple précédent, c'est le cas de <code>transform_relation</code>.</p>\n<p>Une clé <code>\"order\"</code> est systématiquement présente dans chacun des dictionnaires de la liste. Selon la présence d'un dictionnaire de numéro d'ordre donné dans le gabarit enfant et/ou le gabarit parent, ce dictionnaire sera inséré, supprimé, mis à jour ou conservé :</p>\n<table>\n<thead>\n<tr>\n<th>enfant</th>\n<th>parent</th>\n<th>résultat</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>oui</td>\n<td>non</td>\n<td>insertion</td>\n</tr>\n<tr>\n<td>oui</td>\n<td>oui</td>\n<td>si les clés sont parmi {<code>\"order\"</code>, <code>\"comment\"</code>} : suppression<br/> s'il y a plusieurs clés : <a href=\"https://docs.python.org/3/library/stdtypes.html#dict.update\">mise à jour</a></td>\n</tr>\n<tr>\n<td>non</td>\n<td>oui</td>\n<td>conservation</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Nouveauté de la version 4.0.</strong> Si une clé d'un gabarit enfant est associée à une liste vide, cette association remplace l'éventuelle association existante.</p>\n<p><strong>Remarque.</strong> Les numéros d'ordre utilisés dans les dictionnaires sont des multiples de 100. Si vous voulez créer des gabarits dérivés, évitez par précaution les multiples de 10 : cela augmentera les chances que votre gabarit survive à une mise à jour de l'un de ses ancêtres. Vous pouvez aussi partir d'une copie de ceux-ci, sachant que vous renoncez alors aux bénéfices de leurs éventuelles mises à jour.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<h1 id=\"Annexe-C%C2%A0:-Cr%C3%A9dits\">Annexe C : Crédits<a class=\"anchor-link\" href=\"#Annexe-C%C2%A0:-Cr%C3%A9dits\">¶</a></h1>\n</div>\n</div>\n</div>\n</div>\n<div class=\"jp-Cell jp-MarkdownCell jp-Notebook-cell\">\n<div class=\"jp-Cell-inputWrapper\" tabindex=\"0\">\n<div class=\"jp-Collapser jp-InputCollapser jp-Cell-inputCollapser\">\n</div>\n<div class=\"jp-InputArea jp-Cell-inputArea\"><div class=\"jp-InputPrompt jp-InputArea-prompt\">\n</div><div class=\"jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput\" data-mime-type=\"text/markdown\">\n<ul>\n<li><strong>Auteur</strong><ul>\n<li>Aristide Grange, Université de Lorraine, Metz, <a href=\"http://lcoms.univ-lorraine.fr\">LCOMS</a>.</li>\n</ul>\n</li>\n<li><strong>Administration système</strong><ul>\n<li>Cyril Minette.</li>\n</ul>\n</li>\n<li><strong>Outils</strong><ul>\n<li>Aspect visuel<ul>\n<li><a href=\"http://colorbrewer2.org\">Color Brewer</a> (Cynthia Brewer).</li>\n<li><a href=\"http://realfavicongenerator.net\">Real Favicon Generator</a> (Philippe Bernard).</li>\n<li><a href=\"http://meyerweb.com/eric/tools/css/reset/\">reset.css</a> (Eric Meyer).</li>\n</ul>\n</li>\n<li>JavaScript<ul>\n<li><a href=\"http://jquery.com/\">JQuery</a> (John Resig).</li>\n<li><a href=\"https://github.com/js-cookie/js-cookie\">JS-Cookie</a> (Klaus Hartl).</li>\n<li><a href=\"https://ace.c9.io\">Ace Editor</a> (<a href=\"https://c9.io/\">Cloud9 IDE</a> et <a href=\"https://mozilla.org/\">Mozilla</a>).</li>\n</ul>\n</li>\n<li>Python<ul>\n<li><a href=\"http://mwh.geek.nz/2009/04/26/python-damerau-levenshtein-distance/\">Distance de Damerau-Levenshtein</a> (Michael Homer).</li>\n<li><a href=\"https://github.com/lark-parser/lark\">Lark Parser</a> (Erez Shinan).</li>\n<li><a href=\"https://cairosvg.org\">CairoSVG</a> (<a href=\"https://www.courtbouillon.org\">CourtBouillon</a>).</li>\n<li><a href=\"https://github.com/asweigart/pyperclip\">Pyperclip</a> (Al Sweigart).</li>\n</ul>\n</li>\n<li>Services de rendu<ul>\n<li><a href=\"https://kroki.io\">Kroki.io</a> (Guillaume Grossetie).</li>\n<li><a href=\"https://goqr.me/api/\">QR Code Generator</a> (Foundata GmbH).</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><strong>Divers</strong><ul>\n<li><a href=\"https://modern-sql.com\">Modern SQL</a> (Markus Winand).</li>\n<li><a href=\"https://dbml.dbdiagram.io/home/\">DBML</a> (<a href=\"https://www.holistics.io\">Holistics</a>).</li>\n<li><a href=\"https://d2lang.com\">D2</a> (<a href=\"https://terrastruct.com\">Terrastruct</a>).</li>\n<li><a href=\"https://basthon.fr\">Basthon</a> (Romain Casati).</li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "doc/fr_refman.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"toc\": true\n   },\n   \"source\": [\n    \"<h1>Mocodo<span class=\\\"tocSkip\\\"></span></h1>\\n\",\n    \"<div class=\\\"toc\\\"><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Introduction\\\" data-toc-modified-id=\\\"Introduction-1\\\"><span class=\\\"toc-item-num\\\">1&nbsp;&nbsp;</span>Introduction</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Tracé-du-modèle-conceptuel\\\" data-toc-modified-id=\\\"Tracé-du-modèle-conceptuel-1.1\\\"><span class=\\\"toc-item-num\\\">1.1&nbsp;&nbsp;</span>Tracé du modèle conceptuel</a></span></li><li><span><a href=\\\"#Opérations-de-conversion\\\" data-toc-modified-id=\\\"Opérations-de-conversion-1.2\\\"><span class=\\\"toc-item-num\\\">1.2&nbsp;&nbsp;</span>Opérations de conversion</a></span></li><li><span><a href=\\\"#Opérations-de-réécriture\\\" data-toc-modified-id=\\\"Opérations-de-réécriture-1.3\\\"><span class=\\\"toc-item-num\\\">1.3&nbsp;&nbsp;</span>Opérations de réécriture</a></span></li></ul></li><li><span><a href=\\\"#Installation-et-lancement-du-programme\\\" data-toc-modified-id=\\\"Installation-et-lancement-du-programme-2\\\"><span class=\\\"toc-item-num\\\">2&nbsp;&nbsp;</span>Installation et lancement du programme</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Installation-minimale\\\" data-toc-modified-id=\\\"Installation-minimale-2.1\\\"><span class=\\\"toc-item-num\\\">2.1&nbsp;&nbsp;</span>Installation minimale</a></span></li><li><span><a href=\\\"#Installation-complète-(recommandé)\\\" data-toc-modified-id=\\\"Installation-complète-(recommandé)-2.2\\\"><span class=\\\"toc-item-num\\\">2.2&nbsp;&nbsp;</span>Installation complète (recommandé)</a></span></li><li><span><a href=\\\"#Utilisation-par-importation\\\" data-toc-modified-id=\\\"Utilisation-par-importation-2.3\\\"><span class=\\\"toc-item-num\\\">2.3&nbsp;&nbsp;</span>Utilisation par importation</a></span></li></ul></li><li><span><a href=\\\"#Syntaxe-de-description-d'un-MCD\\\" data-toc-modified-id=\\\"Syntaxe-de-description-d'un-MCD-3\\\"><span class=\\\"toc-item-num\\\">3&nbsp;&nbsp;</span>Syntaxe de description d'un MCD</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Notions-élémentaires\\\" data-toc-modified-id=\\\"Notions-élémentaires-3.1\\\"><span class=\\\"toc-item-num\\\">3.1&nbsp;&nbsp;</span>Notions élémentaires</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Entités,-associations,-attributs,-identifiants,-cardinalités\\\" data-toc-modified-id=\\\"Entités,-associations,-attributs,-identifiants,-cardinalités-3.1.1\\\"><span class=\\\"toc-item-num\\\">3.1.1&nbsp;&nbsp;</span>Entités, associations, attributs, identifiants, cardinalités</a></span></li><li><span><a href=\\\"#Dépendances-fonctionnelles-entre-entités\\\" data-toc-modified-id=\\\"Dépendances-fonctionnelles-entre-entités-3.1.2\\\"><span class=\\\"toc-item-num\\\">3.1.2&nbsp;&nbsp;</span>Dépendances fonctionnelles entre entités</a></span></li><li><span><a href=\\\"#Associations-réflexives\\\" data-toc-modified-id=\\\"Associations-réflexives-3.1.3\\\"><span class=\\\"toc-item-num\\\">3.1.3&nbsp;&nbsp;</span>Associations réflexives</a></span></li><li><span><a href=\\\"#Identifiants-composites\\\" data-toc-modified-id=\\\"Identifiants-composites-3.1.4\\\"><span class=\\\"toc-item-num\\\">3.1.4&nbsp;&nbsp;</span>Identifiants composites</a></span></li><li><span><a href=\\\"#Flèches-sur-les-pattes\\\" data-toc-modified-id=\\\"Flèches-sur-les-pattes-3.1.5\\\"><span class=\\\"toc-item-num\\\">3.1.5&nbsp;&nbsp;</span>Flèches sur les pattes</a></span></li><li><span><a href=\\\"#Types-de-données\\\" data-toc-modified-id=\\\"Types-de-données-3.1.6\\\"><span class=\\\"toc-item-num\\\">3.1.6&nbsp;&nbsp;</span>Types de données</a></span></li><li><span><a href=\\\"#Tracé-d'un-MCD&nbsp;:-principes\\\" data-toc-modified-id=\\\"Tracé-d'un-MCD&nbsp;:-principes-3.1.7\\\"><span class=\\\"toc-item-num\\\">3.1.7&nbsp;&nbsp;</span>Tracé d'un MCD&nbsp;: principes</a></span></li></ul></li><li><span><a href=\\\"#Extensions-du-modèle\\\" data-toc-modified-id=\\\"Extensions-du-modèle-3.2\\\"><span class=\\\"toc-item-num\\\">3.2&nbsp;&nbsp;</span>Extensions du modèle</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Entité-faible-(ou-identification-relative)\\\" data-toc-modified-id=\\\"Entité-faible-(ou-identification-relative)-3.2.1\\\"><span class=\\\"toc-item-num\\\">3.2.1&nbsp;&nbsp;</span>Entité faible (ou identification relative)</a></span></li><li><span><a href=\\\"#Héritage-(généralisation-/-spécialisation)\\\" data-toc-modified-id=\\\"Héritage-(généralisation-/-spécialisation)-3.2.2\\\"><span class=\\\"toc-item-num\\\">3.2.2&nbsp;&nbsp;</span>Héritage (généralisation / spécialisation)</a></span></li><li><span><a href=\\\"#Contrainte-inter-associations\\\" data-toc-modified-id=\\\"Contrainte-inter-associations-3.2.3\\\"><span class=\\\"toc-item-num\\\">3.2.3&nbsp;&nbsp;</span>Contrainte inter-associations</a></span></li><li><span><a href=\\\"#Agrégat-(ou-pseudo-entité)\\\" data-toc-modified-id=\\\"Agrégat-(ou-pseudo-entité)-3.2.4\\\"><span class=\\\"toc-item-num\\\">3.2.4&nbsp;&nbsp;</span>Agrégat (ou pseudo-entité)</a></span></li><li><span><a href=\\\"#CIF-à-unicité-complète\\\" data-toc-modified-id=\\\"CIF-à-unicité-complète-3.2.5\\\"><span class=\\\"toc-item-num\\\">3.2.5&nbsp;&nbsp;</span>CIF à unicité complète</a></span></li><li><span><a href=\\\"#Identifiants-explicites-dans-les-associations\\\" data-toc-modified-id=\\\"Identifiants-explicites-dans-les-associations-3.2.6\\\"><span class=\\\"toc-item-num\\\">3.2.6&nbsp;&nbsp;</span>Identifiants explicites dans les associations</a></span></li></ul></li></ul></li><li><span><a href=\\\"#Conversion-d'un-MCD\\\" data-toc-modified-id=\\\"Conversion-d'un-MCD-4\\\"><span class=\\\"toc-item-num\\\">4&nbsp;&nbsp;</span>Conversion d'un MCD</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Passage-au-relationnel\\\" data-toc-modified-id=\\\"Passage-au-relationnel-4.1\\\"><span class=\\\"toc-item-num\\\">4.1&nbsp;&nbsp;</span>Passage au relationnel</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Niveau-logique\\\" data-toc-modified-id=\\\"Niveau-logique-4.1.1\\\"><span class=\\\"toc-item-num\\\">4.1.1&nbsp;&nbsp;</span>Niveau logique</a></span></li><li><span><a href=\\\"#Niveau-physique&nbsp;:-DDL\\\" data-toc-modified-id=\\\"Niveau-physique&nbsp;:-DDL-4.1.2\\\"><span class=\\\"toc-item-num\\\">4.1.2&nbsp;&nbsp;</span>Niveau physique&nbsp;: DDL</a></span></li><li><span><a href=\\\"#Notes-sur-les-règles-de-passage\\\" data-toc-modified-id=\\\"Notes-sur-les-règles-de-passage-4.1.3\\\"><span class=\\\"toc-item-num\\\">4.1.3&nbsp;&nbsp;</span>Notes sur les règles de passage</a></span></li><li><span><a href=\\\"#Ajustement-des-règles-de-passage\\\" data-toc-modified-id=\\\"Ajustement-des-règles-de-passage-4.1.4\\\"><span class=\\\"toc-item-num\\\">4.1.4&nbsp;&nbsp;</span>Ajustement des règles de passage</a></span></li><li><span><a href=\\\"#Autres-sorties-relationnelles\\\" data-toc-modified-id=\\\"Autres-sorties-relationnelles-4.1.5\\\"><span class=\\\"toc-item-num\\\">4.1.5&nbsp;&nbsp;</span>Autres sorties relationnelles</a></span></li></ul></li><li><span><a href=\\\"#Autres-conversions\\\" data-toc-modified-id=\\\"Autres-conversions-4.2\\\"><span class=\\\"toc-item-num\\\">4.2&nbsp;&nbsp;</span>Autres conversions</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Diagramme-de-classes-UML\\\" data-toc-modified-id=\\\"Diagramme-de-classes-UML-4.2.1\\\"><span class=\\\"toc-item-num\\\">4.2.1&nbsp;&nbsp;</span>Diagramme de classes UML</a></span></li><li><span><a href=\\\"#ERD-avec-la-convention-Look-across\\\" data-toc-modified-id=\\\"ERD-avec-la-convention-Look-across-4.2.2\\\"><span class=\\\"toc-item-num\\\">4.2.2&nbsp;&nbsp;</span>ERD avec la convention <em>Look across</em></a></span></li><li><span><a href=\\\"#Dictionnaire-des-données\\\" data-toc-modified-id=\\\"Dictionnaire-des-données-4.2.3\\\"><span class=\\\"toc-item-num\\\">4.2.3&nbsp;&nbsp;</span>Dictionnaire des données</a></span></li><li><span><a href=\\\"#URL-de-partage\\\" data-toc-modified-id=\\\"URL-de-partage-4.2.4\\\"><span class=\\\"toc-item-num\\\">4.2.4&nbsp;&nbsp;</span>URL de partage</a></span></li></ul></li></ul></li><li><span><a href=\\\"#Mocodo-pour-la-pédagogie\\\" data-toc-modified-id=\\\"Mocodo-pour-la-pédagogie-5\\\"><span class=\\\"toc-item-num\\\">5&nbsp;&nbsp;</span>Mocodo pour la pédagogie</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Vue-en-extension\\\" data-toc-modified-id=\\\"Vue-en-extension-5.1\\\"><span class=\\\"toc-item-num\\\">5.1&nbsp;&nbsp;</span>Vue en extension</a></span></li><li><span><a href=\\\"#MCD-interactif\\\" data-toc-modified-id=\\\"MCD-interactif-5.2\\\"><span class=\\\"toc-item-num\\\">5.2&nbsp;&nbsp;</span>MCD interactif</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Afficher-des-explications-au-survol\\\" data-toc-modified-id=\\\"Afficher-des-explications-au-survol-5.2.1\\\"><span class=\\\"toc-item-num\\\">5.2.1&nbsp;&nbsp;</span>Afficher des explications au survol</a></span></li><li><span><a href=\\\"#Dévoiler-un-MCD-par-étapes\\\" data-toc-modified-id=\\\"Dévoiler-un-MCD-par-étapes-5.2.2\\\"><span class=\\\"toc-item-num\\\">5.2.2&nbsp;&nbsp;</span>Dévoiler un MCD par étapes</a></span></li></ul></li><li><span><a href=\\\"#Explications-du-passage-au-relationnel\\\" data-toc-modified-id=\\\"Explications-du-passage-au-relationnel-5.3\\\"><span class=\\\"toc-item-num\\\">5.3&nbsp;&nbsp;</span>Explications du passage au relationnel</a></span></li><li><span><a href=\\\"#MCD-à-compléter\\\" data-toc-modified-id=\\\"MCD-à-compléter-5.4\\\"><span class=\\\"toc-item-num\\\">5.4&nbsp;&nbsp;</span>MCD à compléter</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Supprimer-le-marquage-d'un-identifiant\\\" data-toc-modified-id=\\\"Supprimer-le-marquage-d'un-identifiant-5.4.1\\\"><span class=\\\"toc-item-num\\\">5.4.1&nbsp;&nbsp;</span>Supprimer le marquage d'un identifiant</a></span></li><li><span><a href=\\\"#Masquer-un-couple-de-cardinalités\\\" data-toc-modified-id=\\\"Masquer-un-couple-de-cardinalités-5.4.2\\\"><span class=\\\"toc-item-num\\\">5.4.2&nbsp;&nbsp;</span>Masquer un couple de cardinalités</a></span></li><li><span><a href=\\\"#Masquer-un-attribut\\\" data-toc-modified-id=\\\"Masquer-un-attribut-5.4.3\\\"><span class=\\\"toc-item-num\\\">5.4.3&nbsp;&nbsp;</span>Masquer un attribut</a></span></li><li><span><a href=\\\"#Ne-faire-apparaître-que-le-squelette-du-schéma-conceptuel\\\" data-toc-modified-id=\\\"Ne-faire-apparaître-que-le-squelette-du-schéma-conceptuel-5.4.4\\\"><span class=\\\"toc-item-num\\\">5.4.4&nbsp;&nbsp;</span>Ne faire apparaître que le squelette du schéma conceptuel</a></span></li></ul></li><li><span><a href=\\\"#Obfuscation-d'un-MCD-donné\\\" data-toc-modified-id=\\\"Obfuscation-d'un-MCD-donné-5.5\\\"><span class=\\\"toc-item-num\\\">5.5&nbsp;&nbsp;</span>Obfuscation d'un MCD donné</a></span></li><li><span><a href=\\\"#Croissance-stochastique\\\" data-toc-modified-id=\\\"Croissance-stochastique-5.6\\\"><span class=\\\"toc-item-num\\\">5.6&nbsp;&nbsp;</span>Croissance stochastique</a></span></li><li><span><a href=\\\"#Génération-d'un-QR-code\\\" data-toc-modified-id=\\\"Génération-d'un-QR-code-5.7\\\"><span class=\\\"toc-item-num\\\">5.7&nbsp;&nbsp;</span>Génération d'un QR code</a></span></li><li><span><a href=\\\"#Bibliothèque-de-MCD-en-ligne\\\" data-toc-modified-id=\\\"Bibliothèque-de-MCD-en-ligne-5.8\\\"><span class=\\\"toc-item-num\\\">5.8&nbsp;&nbsp;</span>Bibliothèque de MCD en ligne</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Accès-sous-Mocodo-online\\\" data-toc-modified-id=\\\"Accès-sous-Mocodo-online-5.8.1\\\"><span class=\\\"toc-item-num\\\">5.8.1&nbsp;&nbsp;</span>Accès sous Mocodo online</a></span></li><li><span><a href=\\\"#Accès-sous-terminal-ou-Jupyter-Notebook\\\" data-toc-modified-id=\\\"Accès-sous-terminal-ou-Jupyter-Notebook-5.8.2\\\"><span class=\\\"toc-item-num\\\">5.8.2&nbsp;&nbsp;</span>Accès sous terminal ou Jupyter Notebook</a></span></li></ul></li></ul></li><li><span><a href=\\\"#Compléments-sur-l'aspect-visuel\\\" data-toc-modified-id=\\\"Compléments-sur-l'aspect-visuel-6\\\"><span class=\\\"toc-item-num\\\">6&nbsp;&nbsp;</span>Compléments sur l'aspect visuel</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Styles\\\" data-toc-modified-id=\\\"Styles-6.1\\\"><span class=\\\"toc-item-num\\\">6.1&nbsp;&nbsp;</span>Styles</a></span></li><li><span><a href=\\\"#Paramétrage-du-réarrangement-automatique\\\" data-toc-modified-id=\\\"Paramétrage-du-réarrangement-automatique-6.2\\\"><span class=\\\"toc-item-num\\\">6.2&nbsp;&nbsp;</span>Paramétrage du réarrangement automatique</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Méthode-exacte-(branch-&amp;-bound)\\\" data-toc-modified-id=\\\"Méthode-exacte-(branch-&amp;-bound)-6.2.1\\\"><span class=\\\"toc-item-num\\\">6.2.1&nbsp;&nbsp;</span>Méthode exacte (<em>branch &amp; bound</em>)</a></span></li><li><span><a href=\\\"#Méthode-heuristique-(algorithme-génétique)\\\" data-toc-modified-id=\\\"Méthode-heuristique-(algorithme-génétique)-6.2.2\\\"><span class=\\\"toc-item-num\\\">6.2.2&nbsp;&nbsp;</span>Méthode heuristique (algorithme génétique)</a></span></li></ul></li><li><span><a href=\\\"#Amélioration-du-plongement\\\" data-toc-modified-id=\\\"Amélioration-du-plongement-6.3\\\"><span class=\\\"toc-item-num\\\">6.3&nbsp;&nbsp;</span>Amélioration du plongement</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Par-duplication-d'entités-réduites-à-leur-identifiant\\\" data-toc-modified-id=\\\"Par-duplication-d'entités-réduites-à-leur-identifiant-6.3.1\\\"><span class=\\\"toc-item-num\\\">6.3.1&nbsp;&nbsp;</span>Par duplication d'entités réduites à leur identifiant</a></span></li><li><span><a href=\\\"#Par-suppression-de-ces-mêmes-entités\\\" data-toc-modified-id=\\\"Par-suppression-de-ces-mêmes-entités-6.3.2\\\"><span class=\\\"toc-item-num\\\">6.3.2&nbsp;&nbsp;</span>Par suppression de ces mêmes entités</a></span></li></ul></li><li><span><a href=\\\"#Ajustement-de-l'aspect-de-certains-éléments\\\" data-toc-modified-id=\\\"Ajustement-de-l'aspect-de-certains-éléments-6.4\\\"><span class=\\\"toc-item-num\\\">6.4&nbsp;&nbsp;</span>Ajustement de l'aspect de certains éléments</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Format-des-cardinalités\\\" data-toc-modified-id=\\\"Format-des-cardinalités-6.4.1\\\"><span class=\\\"toc-item-num\\\">6.4.1&nbsp;&nbsp;</span>Format des cardinalités</a></span></li><li><span><a href=\\\"#Format-des-clés-étrangères\\\" data-toc-modified-id=\\\"Format-des-clés-étrangères-6.4.2\\\"><span class=\\\"toc-item-num\\\">6.4.2&nbsp;&nbsp;</span>Format des clés étrangères</a></span></li><li><span><a href=\\\"#Symbole-de-dépendance-fonctionnelle\\\" data-toc-modified-id=\\\"Symbole-de-dépendance-fonctionnelle-6.4.3\\\"><span class=\\\"toc-item-num\\\">6.4.3&nbsp;&nbsp;</span>Symbole de dépendance fonctionnelle</a></span></li><li><span><a href=\\\"#Basculement-des-cardinalités-et-inflexion-des-pattes-rectilignes\\\" data-toc-modified-id=\\\"Basculement-des-cardinalités-et-inflexion-des-pattes-rectilignes-6.4.4\\\"><span class=\\\"toc-item-num\\\">6.4.4&nbsp;&nbsp;</span>Basculement des cardinalités et inflexion des pattes rectilignes</a></span></li><li><span><a href=\\\"#Positionnement-des-contraintes\\\" data-toc-modified-id=\\\"Positionnement-des-contraintes-6.4.5\\\"><span class=\\\"toc-item-num\\\">6.4.5&nbsp;&nbsp;</span>Positionnement des contraintes</a></span></li><li><span><a href=\\\"#Gouttière-d'identifiants\\\" data-toc-modified-id=\\\"Gouttière-d'identifiants-6.4.6\\\"><span class=\\\"toc-item-num\\\">6.4.6&nbsp;&nbsp;</span>Gouttière d'identifiants</a></span></li><li><span><a href=\\\"#Style-et-direction-des-pattes-de-l'héritage\\\" data-toc-modified-id=\\\"Style-et-direction-des-pattes-de-l'héritage-6.4.7\\\"><span class=\\\"toc-item-num\\\">6.4.7&nbsp;&nbsp;</span>Style et direction des pattes de l'héritage</a></span></li></ul></li><li><span><a href=\\\"#Retouches-fines\\\" data-toc-modified-id=\\\"Retouches-fines-6.5\\\"><span class=\\\"toc-item-num\\\">6.5&nbsp;&nbsp;</span>Retouches fines</a></span></li><li><span><a href=\\\"#Conversion-dans-d'autres-formats-graphiques\\\" data-toc-modified-id=\\\"Conversion-dans-d'autres-formats-graphiques-6.6\\\"><span class=\\\"toc-item-num\\\">6.6&nbsp;&nbsp;</span>Conversion dans d'autres formats graphiques</a></span></li></ul></li><li><span><a href=\\\"#Annexe-A&nbsp;:-Miscellanées-académiques\\\" data-toc-modified-id=\\\"Annexe-A&nbsp;:-Miscellanées-académiques-7\\\"><span class=\\\"toc-item-num\\\">7&nbsp;&nbsp;</span>Annexe A&nbsp;: Miscellanées académiques</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Décompositions-d'un-MCD\\\" data-toc-modified-id=\\\"Décompositions-d'un-MCD-7.1\\\"><span class=\\\"toc-item-num\\\">7.1&nbsp;&nbsp;</span>Décompositions d'un MCD</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Vider-les-DF-de-leurs-attributs\\\" data-toc-modified-id=\\\"Vider-les-DF-de-leurs-attributs-7.1.1\\\"><span class=\\\"toc-item-num\\\">7.1.1&nbsp;&nbsp;</span>Vider les DF de leurs attributs</a></span></li><li><span><a href=\\\"#Décomposer-les-DF-n-aires\\\" data-toc-modified-id=\\\"Décomposer-les-DF-n-aires-7.1.2\\\"><span class=\\\"toc-item-num\\\">7.1.2&nbsp;&nbsp;</span>Décomposer les DF n-aires</a></span></li><li><span><a href=\\\"#Décomposer-les-associations-n-aires-non-DF\\\" data-toc-modified-id=\\\"Décomposer-les-associations-n-aires-non-DF-7.1.3\\\"><span class=\\\"toc-item-num\\\">7.1.3&nbsp;&nbsp;</span>Décomposer les associations n-aires non DF</a></span></li><li><span><a href=\\\"#Décomposer-les-associations-binaires-non-DF\\\" data-toc-modified-id=\\\"Décomposer-les-associations-binaires-non-DF-7.1.4\\\"><span class=\\\"toc-item-num\\\">7.1.4&nbsp;&nbsp;</span>Décomposer les associations binaires non DF</a></span></li><li><span><a href=\\\"#Décomposer-en-créant-des-entités-faibles\\\" data-toc-modified-id=\\\"Décomposer-en-créant-des-entités-faibles-7.1.5\\\"><span class=\\\"toc-item-num\\\">7.1.5&nbsp;&nbsp;</span>Décomposer en créant des entités faibles</a></span></li><li><span><a href=\\\"#Conclusion-sur-ces-décompositions\\\" data-toc-modified-id=\\\"Conclusion-sur-ces-décompositions-7.1.6\\\"><span class=\\\"toc-item-num\\\">7.1.6&nbsp;&nbsp;</span>Conclusion sur ces décompositions</a></span></li></ul></li><li><span><a href=\\\"#Équivalences-avec-la-convention-Look-Across\\\" data-toc-modified-id=\\\"Équivalences-avec-la-convention-Look-Across-7.2\\\"><span class=\\\"toc-item-num\\\">7.2&nbsp;&nbsp;</span>Équivalences avec la convention <em>Look Across</em></a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Associations-binaires-en-Look-Across\\\" data-toc-modified-id=\\\"Associations-binaires-en-Look-Across-7.2.1\\\"><span class=\\\"toc-item-num\\\">7.2.1&nbsp;&nbsp;</span>Associations binaires en <em>Look Across</em></a></span></li><li><span><a href=\\\"#Associations-n-aires-en-Look-Across\\\" data-toc-modified-id=\\\"Associations-n-aires-en-Look-Across-7.2.2\\\"><span class=\\\"toc-item-num\\\">7.2.2&nbsp;&nbsp;</span>Associations n-aires en <em>Look Across</em></a></span></li></ul></li></ul></li><li><span><a href=\\\"#Annexe-B&nbsp;:-La-commande-mocodo\\\" data-toc-modified-id=\\\"Annexe-B&nbsp;:-La-commande-mocodo-8\\\"><span class=\\\"toc-item-num\\\">8&nbsp;&nbsp;</span>Annexe B&nbsp;: La commande <code>mocodo</code></a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Paramétrage\\\" data-toc-modified-id=\\\"Paramétrage-8.1\\\"><span class=\\\"toc-item-num\\\">8.1&nbsp;&nbsp;</span>Paramétrage</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#mocodo---help\\\" data-toc-modified-id=\\\"mocodo---help-8.1.1\\\"><span class=\\\"toc-item-num\\\">8.1.1&nbsp;&nbsp;</span><code>mocodo --help</code></a></span></li><li><span><a href=\\\"#Paramétrage-à-long-terme\\\" data-toc-modified-id=\\\"Paramétrage-à-long-terme-8.1.2\\\"><span class=\\\"toc-item-num\\\">8.1.2&nbsp;&nbsp;</span>Paramétrage à long terme</a></span></li><li><span><a href=\\\"#Dissection-de-la-commande\\\" data-toc-modified-id=\\\"Dissection-de-la-commande-8.1.3\\\"><span class=\\\"toc-item-num\\\">8.1.3&nbsp;&nbsp;</span>Dissection de la commande</a></span></li></ul></li><li><span><a href=\\\"#L'option---transform-et-ses-arguments\\\" data-toc-modified-id=\\\"L'option---transform-et-ses-arguments-8.2\\\"><span class=\\\"toc-item-num\\\">8.2&nbsp;&nbsp;</span>L'option <code>--transform</code> et ses arguments</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Triage-et-exécution-des-transformations\\\" data-toc-modified-id=\\\"Triage-et-exécution-des-transformations-8.2.1\\\"><span class=\\\"toc-item-num\\\">8.2.1&nbsp;&nbsp;</span>Triage et exécution des transformations</a></span></li><li><span><a href=\\\"#Aide-mémoire-des-transformations\\\" data-toc-modified-id=\\\"Aide-mémoire-des-transformations-8.2.2\\\"><span class=\\\"toc-item-num\\\">8.2.2&nbsp;&nbsp;</span>Aide-mémoire des transformations</a></span></li><li><span><a href=\\\"#Réécriture-d'éléments-donnés\\\" data-toc-modified-id=\\\"Réécriture-d'éléments-donnés-8.2.3\\\"><span class=\\\"toc-item-num\\\">8.2.3&nbsp;&nbsp;</span>Réécriture d'éléments donnés</a></span></li></ul></li><li><span><a href=\\\"#Fonctionnement-de-la-commande-magique\\\" data-toc-modified-id=\\\"Fonctionnement-de-la-commande-magique-8.3\\\"><span class=\\\"toc-item-num\\\">8.3&nbsp;&nbsp;</span>Fonctionnement de la commande magique</a></span></li><li><span><a href=\\\"#Gabarits-de-passage-au-relationnel\\\" data-toc-modified-id=\\\"Gabarits-de-passage-au-relationnel-8.4\\\"><span class=\\\"toc-item-num\\\">8.4&nbsp;&nbsp;</span>Gabarits de passage au relationnel</a></span><ul class=\\\"toc-item\\\"><li><span><a href=\\\"#Format-des-gabarits\\\" data-toc-modified-id=\\\"Format-des-gabarits-8.4.1\\\"><span class=\\\"toc-item-num\\\">8.4.1&nbsp;&nbsp;</span>Format des gabarits</a></span></li><li><span><a href=\\\"#Dérivation-de-gabarits\\\" data-toc-modified-id=\\\"Dérivation-de-gabarits-8.4.2\\\"><span class=\\\"toc-item-num\\\">8.4.2&nbsp;&nbsp;</span>Dérivation de gabarits</a></span></li><li><span><a href=\\\"#Exemples-de-création-de-gabarit-dérivé-\\\" data-toc-modified-id=\\\"Exemples-de-création-de-gabarit-dérivé--8.4.3\\\"><span class=\\\"toc-item-num\\\">8.4.3&nbsp;&nbsp;</span>Exemples de création de gabarit dérivé <a rel=\\\"nofollow\\\"></a></a></span></li><li><span><a href=\\\"#Mécanisme-de-mise-à-jour\\\" data-toc-modified-id=\\\"Mécanisme-de-mise-à-jour-8.4.4\\\"><span class=\\\"toc-item-num\\\">8.4.4&nbsp;&nbsp;</span>Mécanisme de mise à jour</a></span></li></ul></li></ul></li><li><span><a href=\\\"#Annexe-C&nbsp;:-Crédits\\\" data-toc-modified-id=\\\"Annexe-C&nbsp;:-Crédits-9\\\"><span class=\\\"toc-item-num\\\">9&nbsp;&nbsp;</span>Annexe C&nbsp;: Crédits</a></span></li></ul></div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"init_cell\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo 4.3.2 loaded.\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%reload_ext mocodo\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"init_cell\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"from IPython import display\\n\",\n    \"from pathlib import Path\\n\",\n    \"import os\\n\",\n    \"if Path.cwd().name != \\\"mocodo_notebook\\\":\\n\",\n    \"    Path(\\\"mocodo_notebook\\\").mkdir(parents=True, exist_ok=True)\\n\",\n    \"    os.chdir(\\\"mocodo_notebook\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"![](https://cdn.rawgit.com/laowantong/mocodo/master/logos/banner.svg)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Introduction\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo est un logiciel d'aide à l'enseignement et à l'apprentissage des [bases de données relationnelles](https://fr.wikipedia.org/wiki/Base_de_données_relationnelle).\\n\",\n    \"\\n\",\n    \"- En entrée, il prend un [MCD](https://fr.wikipedia.org/wiki/Modèle_entité-association) (modèle conceptuel de données) décrit dans un langage dédié minimaliste.\\n\",\n    \"- En sortie, il produit un diagramme entité-association et, à la demande, un [MLD](https://fr.wikipedia.org/wiki/Merise_%28informatique%29%23MLD_%3A_mod%C3%A8le_logique_des_donn%C3%A9es) (schéma relationnel, sous forme graphique ou textuelle), un [DDL](https://fr.wikipedia.org/wiki/Langage_de_définition_de_données) (script SQL de création de la base), un [diagramme de classes UML](https://fr.wikipedia.org/wiki/Diagramme_de_classes), etc.\\n\",\n    \"- En bonus, il est capable de réarranger automatiquement votre MCD de façon esthétique, et de lui appliquer des opérations de réécriture qui vont du mondain (typographie) à l'académique (décomposition d'associations), en passant par le merveilleux (inférence de types, génération d'exercices et d'exemples).\\n\",\n    \"\\n\",\n    \"Vous pouvez utiliser Mocodo :\\n\",\n    \"\\n\",\n    \"- à distance, sans rien installer, avec [Mocodo _online_](https://www.mocodo.net) ;\\n\",\n    \"- en local, comme n'importe quel programme Python ;\\n\",\n    \"- dans un document [Jupyter Notebook](https://jupyter.org) (à l'instar de cette documentation).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Tracé du modèle conceptuel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ci-dessous, un exemple d'utilisation sous Jupyter Notebook. L'appel du programme est en première ligne ; le texte-source proprement dit, lignes suivantes. En sortie, le diagramme conceptuel, égayé au passage par l'option `--colors` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"594\\\" height=\\\"128\\\" viewBox=\\\"0 0 594 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"594\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M448 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M462 63 v16 a14 14 90 0 1 -14 14 H390 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"376\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"376\\\" y1=\\\"63\\\" x2=\\\"462\\\" y2=\\\"63\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"56.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"81.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"467\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"491\\\" y1=\\\"47\\\" x2=\\\"585\\\" y2=\\\"47\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"38.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"64.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"499\\\" y1=\\\"67\\\" x2=\\\"574\\\" y2=\\\"67\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"81.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"98\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --colors ocean\\n\",\n    \"Client: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\\n\",\n    \"Passer, 0N Client, 11 Commande\\n\",\n    \"Commande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\\n\",\n    \"Inclure, 1N Commande, 0N Produit: Quantité [INTEGER]\\n\",\n    \"Produit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Opérations de conversion\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'appel précédent a automatiquement enregistré le texte-source sous le nom de `sandbox.mcd`. Renommons-le `ccp.mcd` pour y avoir accès tout au long de ce document.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"Path(\\\"sandbox.mcd\\\").rename(\\\"ccp.mcd\\\");\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"On peut le récupérer avec `--input` pour lui appliquer diverses opérations. Ainsi, l'appel suivant génère et affiche son MLD, son diagramme relationnel et son DDL :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Client** (<u>Réf. client</u>, Nom, Prénom, Adresse)\\n\",\n       \"- **Commande** (<u>Num. commande</u>, Date, Montant, _#Réf. client_)\\n\",\n       \"- **Inclure** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\\n\",\n       \"- **Produit** (<u>Réf. produit</u>, Libellé, Prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2ODAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjgwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY4MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjZmVmZWVjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gY2xpZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkNMVVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSI0NyIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjE3IiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM1NiIgeTE9IjQ3IiB4Mj0iNDkwIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM4NyIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJPHRleHQgeD0iMzY0IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jTnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI2NyIgeDI9IjQ4MSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQ0OCIgeTI9Ijg0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU0OCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTQ4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU0OCIgeTE9IjQ3IiB4Mj0iNjQyIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU1OSIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU1NiIgeTE9IjY3IiB4Mj0iNjMxIiB5Mj0iNjciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NTYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDkwIDc4LjUgQzUxOSA3MCA1MDkuMzMgNjEuNSA1NDggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1NDggNjEuNSA1MzYgNjcuNSA1NDAgNjEuNSA1MzYgNTUuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ5MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgo8L3N2Zz4=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE Client (\\n\",\n       \"  PRIMARY KEY (Ref_client),\\n\",\n       \"  Ref_client VARCHAR(8) NOT NULL,\\n\",\n       \"  Nom        VARCHAR(255),\\n\",\n       \"  Prenom     VARCHAR(255),\\n\",\n       \"  Adresse    VARCHAR(255)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Commande (\\n\",\n       \"  PRIMARY KEY (Num_commande),\\n\",\n       \"  Num_commande VARCHAR(8) NOT NULL,\\n\",\n       \"  Date         DATE,\\n\",\n       \"  Montant      DECIMAL(10,2),\\n\",\n       \"  Ref_client   VARCHAR(8) NOT NULL\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Inclure (\\n\",\n       \"  PRIMARY KEY (Num_commande, Ref_produit),\\n\",\n       \"  Num_commande VARCHAR(8) NOT NULL,\\n\",\n       \"  Ref_produit  VARCHAR(8) NOT NULL,\\n\",\n       \"  Quantite     INTEGER\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Produit (\\n\",\n       \"  PRIMARY KEY (Ref_produit),\\n\",\n       \"  Ref_produit   VARCHAR(8) NOT NULL,\\n\",\n       \"  Libelle       VARCHAR(50),\\n\",\n       \"  Prix_unitaire DECIMAL(10,2)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"ALTER TABLE Commande ADD FOREIGN KEY (Ref_client) REFERENCES Client (Ref_client);\\n\",\n       \"\\n\",\n       \"ALTER TABLE Inclure ADD FOREIGN KEY (Ref_produit) REFERENCES Produit (Ref_produit);\\n\",\n       \"ALTER TABLE Inclure ADD FOREIGN KEY (Num_commande) REFERENCES Commande (Num_commande);\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo --input ccp --transform mld diagram ddl --colors mondrian\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans la suite, pour épargner la frappe, les options `--input` et `--transform` seront respectivement abrégées en `-i` et `-t`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les opérations de conversion ne se limitent pas forcément au schéma relationnel. En voici une qui extrait un dictionnaire des données, par défaut sous la forme d'un tableau Markdown à trois colonnes :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_data_dict_3.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"| Entité ou association | Libellé de l'attribut | Type          |\\n\",\n       \"|:----------------------|:----------------------|:--------------|\\n\",\n       \"| Client                | Adresse               | VARCHAR(255)  |\\n\",\n       \"| \\\"                     | Nom                   | VARCHAR(255)  |\\n\",\n       \"| \\\"                     | Prénom                | VARCHAR(255)  |\\n\",\n       \"| \\\"                     | Réf. client           | VARCHAR(8)    |\\n\",\n       \"| Commande              | Date                  | DATE          |\\n\",\n       \"| \\\"                     | Montant               | DECIMAL(10,2) |\\n\",\n       \"| \\\"                     | Num. commande         | VARCHAR(8)    |\\n\",\n       \"| Inclure               | Quantité              | INTEGER       |\\n\",\n       \"| Produit               | Libellé               | VARCHAR(50)   |\\n\",\n       \"| \\\"                     | Prix unitaire         | DECIMAL(10,2) |\\n\",\n       \"| \\\"                     | Réf. produit          | VARCHAR(8)    |\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t data_dict\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Une autre qui transcrit le MCD dans la notation _crow's foot_ (`crow`) pour [Mermaid](http://mermaid.js.org) (`mmd`) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_erd_crow.mmd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```mmd\\n\",\n       \"erDiagram\\n\",\n       \"  Client {\\n\",\n       \"    VARCHAR(8) Ref_client PK\\n\",\n       \"    VARCHAR(255) Nom\\n\",\n       \"    VARCHAR(255) Prenom\\n\",\n       \"    VARCHAR(255) Adresse\\n\",\n       \"  }\\n\",\n       \"  Commande {\\n\",\n       \"    VARCHAR(8) Num_commande PK\\n\",\n       \"    DATE Date\\n\",\n       \"    DECIMAL(10-2) Montant\\n\",\n       \"  }\\n\",\n       \"  Inclure {\\n\",\n       \"    INTEGER Quantite PK\\n\",\n       \"  }\\n\",\n       \"  Produit {\\n\",\n       \"    VARCHAR(8) Ref_produit PK\\n\",\n       \"    VARCHAR(50) Libelle\\n\",\n       \"    DECIMAL(10-2) Prix_unitaire\\n\",\n       \"  }\\n\",\n       \"  Client ||--o{ Commande: Passer\\n\",\n       \"  Inclure }|..|| Commande: DF\\n\",\n       \"  Inclure }o..|| Produit: DF\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t crow:mmd\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le rendu des diagrammes décrits dans des langages-tiers (comme Mermaid, PlantUML, etc.) n'est pas directement pris en charge, mais peut être délégué (`--defer`) de façon transparente au service web approprié. Dans ce cas, c'est la sortie graphique qui est affichée :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_erd_crow.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjYyNHB0IiBoZWlnaHQ9IjMzMnB0Igogdmlld0JveD0iMC4wMCAwLjAwIDYyNC4wMCAzMzEuNTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMzI3LjUpIj4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTMyNy41IDYyMCwtMzI3LjUgNjIwLDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzOSwtMTc2LjUgMzksLTMxOS41IDI2OSwtMzE5LjUgMjY5LC0xNzYuNSAzOSwtMTc2LjUiLz4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjM5LC0yODguNSAzOSwtMzE5LjUgMjY5LC0zMTkuNSAyNjksLTI4OC41IDM5LC0yODguNSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTI4OC41IDM5LC0zMTkuNSAyNjksLTMxOS41IDI2OSwtMjg4LjUgMzksLTI4OC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI3Ljc1IiB5PSItMjk3LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+Q2xpZW50PC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTI2MC41IDM5LC0yODguNSA2NywtMjg4LjUgNjcsLTI2MC41IDM5LC0yNjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQzLjYyIiB5PSItMjY5LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlBLPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjg4LjUgNjcsLTI4OC41IDY3LC0yNjAuNSAxNTEsLTI2MC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzEuODgiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gY2xpZW50PC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjYwLjUgMjY5LC0yNjAuNSAyNjksLTI4OC41IDE1MSwtMjg4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzQiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM5LC0yMzIuNSAzOSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAzOSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MC43NSIgeT0iLTI0MS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAxNTEsLTIzMi41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzIiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+Tm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjMyLjUgMjY5LC0yMzIuNSAyNjksLTI2MC41IDE1MSwtMjYwLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTIwNC41IDM5LC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDM5LC0yMDQuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMjEzLjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTUxLC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTIxMy4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QcsOpbm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMjA0LjUgMjY5LC0yMDQuNSAyNjksLTIzMi41IDE1MSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yMTMuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzksLTE3Ni41IDM5LC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDM5LC0xNzYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMTg1LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTUxLC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDE1MSwtMTc2LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTE4NS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5BZHJlc3NlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE1MSwtMTc2LjUgMjY5LC0xNzYuNSAyNjksLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0xODUuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjgsLTQgOCwtMTE5IDMwMCwtMTE5IDMwMCwtNCA4LC00Ii8+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSI4LC04OCA4LC0xMTkgMzAwLC0xMTkgMzAwLC04OCA4LC04OCIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtODggOCwtMTE5IDMwMCwtMTE5IDMwMCwtODggOCwtODgiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxMDIuMjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPkNvbW1hbmRlPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtNjAgOCwtODggMzYsLTg4IDM2LC02MCA4LC02MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjEyLjYyIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC04OCAzNiwtODggMzYsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MC43NSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk51bS4gY29tbWFuZGU8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC02MCAzMDAsLTYwIDMwMCwtODggMTczLC04OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIwNSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlZBUkNIQVIoOCk8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI4LC0zMiA4LC02MCAzNiwtNjAgMzYsLTMyIDgsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTkuNzUiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE3MywtNjAgMzYsLTYwIDM2LC0zMiAxNzMsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDEiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EYXRlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjE3MywtMzIgMzAwLC0zMiAzMDAsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIyNTkiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EQVRFPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iOCwtNCA4LC0zMiAzNiwtMzIgMzYsLTQgOCwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE5Ljc1IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+IDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNzMsLTMyIDM2LC0zMiAzNiwtNCAxNzMsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk1vbnRhbnQ8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTczLC00IDMwMCwtNCAzMDAsLTMyIDE3MywtMzIiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzgiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5ERUNJTUFMKDEwLDIpPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7Jmd0OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7Jmd0OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNTQsLTE2Mi45NEMxNTQsLTE1NS45NSAxNTQsLTE0OC44OSAxNTQsLTE0MS45MyIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU5LC0xNzEuNzUgMTQ5LC0xNzEuNzUgMTQ5LC0xNjkuNzUgMTU5LC0xNjkuNzUgMTU5LC0xNzEuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNTQsLTE3Mi43NSAxNTQsLTE2Ny43NSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU5LC0xNjYuNzUgMTQ5LC0xNjYuNzUgMTQ5LC0xNjQuNzUgMTU5LC0xNjQuNzUgMTU5LC0xNjYuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIxNTQsLTE2Ny43NSAxNTQsLTE2Mi43NSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMTU0LC0xMzMuMDYgMTU4LjUsLTEyMy4wNiAxNTQsLTEyNy43MyAxNTQsLTEyMy40IDE1NCwtMTIzLjQgMTU0LC0xMjMuNCAxNTQsLTEyNy43MyAxNDkuNSwtMTIzLjA2IDE1NCwtMTMzLjA2Ii8+CjxlbGxpcHNlIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgY3g9IjE1NCIgY3k9Ii0xMzguNzgiIHJ4PSI0IiByeT0iNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIiIHk9Ii0xNDQuMDUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEuMDAiIGZpbGw9IiMwMDAwMDAiPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjE4LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjE4LjUgMzU2LjUsLTIxOC41Ii8+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDE0LjYyIiB5PSItMjU1LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+SW5jbHVyZTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1Ni41LC0yMTguNSAzNTYuNSwtMjQ2LjUgMzg0LjUsLTI0Ni41IDM4NC41LC0yMTguNSAzNTYuNSwtMjE4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNjEuMTIiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDYwLjUsLTI0Ni41IDM4NC41LC0yNDYuNSAzODQuNSwtMjE4LjUgNDYwLjUsLTIxOC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg5LjUiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UXVhbnRpdMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2MC41LC0yMTguNSA1MzMuNSwtMjE4LjUgNTMzLjUsLTI0Ni41IDQ2MC41LC0yNDYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ2NS41IiB5PSItMjI3LjI1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPklOVEVHRVI8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmZ3Q7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmZ3Q7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWRhc2hhcnJheT0iMSw1IiBkPSJNMzgxLjA3LC0yMDYuNDdDMzQ0Ljg5LC0xODMuNTMgMjk4Ljc4LC0xNTQuMyAyNTcuNTgsLTEyOC4xNyIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMzg1LjI1LC0yMDkuMTIgMzkxLjI5LC0yMTguMjcgMzg5Ljc2LC0yMTEuOTcgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzg5Ljc2LC0yMTEuOTcgMzk2LjExLC0yMTAuNjcgMzg1LjI1LC0yMDkuMTIiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM4Ni4wNSwtMjAzLjcxIDM4MC43LC0yMTIuMTUgMzc5LjAxLC0yMTEuMDggMzg0LjM3LC0yMDIuNjQgMzg2LjA1LC0yMDMuNzEiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzODQuMjIsLTIwOC40NyAzODAsLTIwNS43OSIvPgo8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iMjQ3LjMsLTEyNy41OCAyNTIuNjYsLTExOS4xMyAyNTQuMzUsLTEyMC4yIDI0OC45OSwtMTI4LjY1IDI0Ny4zLC0xMjcuNTgiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIyNDkuMTQsLTEyMi44MiAyNTMuMzYsLTEyNS41Ii8+Cjxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIyNTEuNTMsLTEzMC4yNSAyNTYuODgsLTEyMS44MSAyNTguNTcsLTEyMi44OCAyNTMuMjIsLTEzMS4zMyAyNTEuNTMsLTEzMC4yNSIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjI1My4zNiwtMTI1LjUgMjU3LjU4LC0xMjguMTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjk4LjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMDAwMDAwIj5ERjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTIsLTQgMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC00IDM1MiwtNCIvPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iMzUyLC04OCAzNTIsLTExOSA2MDgsLTExOSA2MDgsLTg4IDM1MiwtODgiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtODggMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC04OCAzNTIsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDQ4LjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPlByb2R1aXQ8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSIzNTIsLTYwIDM1MiwtODggMzgwLC04OCAzODAsLTYwIDM1MiwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTYuNjIiIHk9Ii02OC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QSzwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0ODEsLTg4IDM4MCwtODggMzgwLC02MCA0ODEsLTYwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg1IiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0ODEsLTYwIDYwOCwtNjAgNjA4LC04OCA0ODEsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNTEzIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtMzIgMzUyLC02MCAzODAsLTYwIDM4MCwtMzIgMzUyLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDgxLC02MCAzODAsLTYwIDM4MCwtMzIgNDgxLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM4NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPkxpYmVsbMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ4MSwtMzIgNjA4LC0zMiA2MDgsLTYwIDQ4MSwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MDQiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5WQVJDSEFSKDUwKTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjM1MiwtNCAzNTIsLTMyIDM4MCwtMzIgMzgwLC00IDM1MiwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50cz0iNDgxLC0zMiAzODAsLTMyIDM4MCwtNCA0ODEsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzODQuNzUiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ4MSwtNCA2MDgsLTQgNjA4LC0zMiA0ODEsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDg2IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+REVDSU1BTCgxMCwyKTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyZndDs0IC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyZndDs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtZGFzaGFycmF5PSIxLDUiIGQ9Ik00NTQuNywtMTk1Ljg3QzQ1OC40MiwtMTc2LjI3IDQ2Mi43MywtMTUzLjU2IDQ2Ni43MiwtMTMyLjUiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ1My4wMiwtMjA0LjcxIDQ0Ni43NCwtMjEzLjcgNDUyLjAzLC0yMDkuOTUgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUyLjAzLC0yMDkuOTUgNDU1LjU4LC0yMTUuMzcgNDUzLjAyLC0yMDQuNzEiLz4KPGVsbGlwc2UgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBjeD0iNDU0LjA5IiBjeT0iLTE5OS4wOSIgcng9IjQiIHJ5PSI0Ii8+Cjxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRzPSI0NjMuNDMsLTEyMyA0NzMuMjYsLTEyNC44NyA0NzIuODksLTEyNi44MyA0NjMuMDYsLTEyNC45NyA0NjMuNDMsLTEyMyIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2OC41MywtMTIyLjk1IDQ2Ny42LC0xMjcuODYiLz4KPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2Mi41LC0xMjcuOTIgNDcyLjMzLC0xMjkuNzggNDcxLjk1LC0xMzEuNzQgNDYyLjEzLC0xMjkuODggNDYyLjUsLTEyNy45MiIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludHM9IjQ2Ny42LC0xMjcuODYgNDY2LjY3LC0xMzIuNzgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDcyLjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMDAwMDAwIj5ERjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t crow:plantuml --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Opérations de réécriture\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Une **réécriture** transforme un MCD Mocodo en un autre MCD Mocodo (au contraire d'une **conversion**, qui produit un animal d'une espèce différente).\\n\",\n    \"\\n\",\n    \"Heureusement, l'utilisateur n'a pas à réfléchir si la transformation qu'il souhaite appliquer est une réécriture ou une conversion : dans les deux cas, il invoque `-t` (c'est-à-dire `--transform`), et Mocodo se débrouille.\\n\",\n    \"\\n\",\n    \"En guise de premier exemple de réécriture, mettons les noms des entités et associations (`boxes`) en majuscules, et les libellés (`labels`) en ASCII et _snake case_ :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"128\\\" viewBox=\\\"0 0 630 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"128\\\" fill=\\\"#f7f7f7\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M196 35 a14 14 90 0 1 14 14 V63 h-88 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#c2a5cf\\\" stroke=\\\"#c2a5cf\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M210 63 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V63 H88\\\" fill=\\\"#e7d4e8\\\" stroke=\\\"#e7d4e8\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"35\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"63\\\" x2=\\\"210\\\" y2=\\\"63\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"571\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M478 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#c2a5cf\\\" stroke=\\\"#c2a5cf\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M492 63 v16 a14 14 90 0 1 -14 14 H408 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#e7d4e8\\\" stroke=\\\"#e7d4e8\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"63\\\" x2=\\\"492\\\" y2=\\\"63\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"402\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"401\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantite</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"370\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Ref_client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"80\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prenom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"239\\\" y1=\\\"47\\\" x2=\\\"365\\\" y2=\\\"47\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"248\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num_commande</text>\\n\",\n       \"\\t<line x1=\\\"247\\\" y1=\\\"67\\\" x2=\\\"356\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"521\\\" y1=\\\"47\\\" x2=\\\"621\\\" y2=\\\"47\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Ref_produit</text>\\n\",\n       \"\\t<line x1=\\\"529\\\" y1=\\\"67\\\" x2=\\\"605\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libelle</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix_unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --colors brewer+3\\n\",\n      \"CLIENT: Ref_client [VARCHAR(8)], Nom [VARCHAR(255)], Prenom [VARCHAR(255)], Adresse [VARCHAR(255)]\\n\",\n      \"PASSER, 0N CLIENT, 11 COMMANDE\\n\",\n      \"COMMANDE: Num_commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\\n\",\n      \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantite [INTEGER]\\n\",\n      \"PRODUIT: Ref_produit [VARCHAR(8)], Libelle [VARCHAR(50)], Prix_unitaire [DECIMAL(10,2)]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t upper:boxes ascii:labels snake:labels --colors brewer+3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Remarquez que l'exécution d'une réécriture affiche, au-dessous du diagramme, le code-source résultant. Celui-ci est précédé de la commande magique originale, _privée de l'option `-i` et de toute opération de réécriture_. Ces dispositions permettent de continuer à travailler directement dessus si on le copie-colle dans une autre cellule.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Plusieurs opérations de réécriture de nature sémantique sont également offertes. Par exemple, on peut décomposer un MCD quelconque en un MCD équivalent, mais n'employant que des dépendances fonctionnelles et des entités faibles :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"734\\\" height=\\\"128\\\" viewBox=\\\"0 0 734 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"734\\\" height=\\\"128\\\" fill=\\\"#f7f7f7\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#c2a5cf\\\" stroke=\\\"#c2a5cf\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#e7d4e8\\\" stroke=\\\"#e7d4e8\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"489\\\" y1=\\\"64\\\" x2=\\\"396\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"396\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"396\\\" cy=\\\"64\\\" r=\\\"20\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\" fill=\\\"#c2a5cf\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"68.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"422\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"422\\\" y1=\\\"82\\\" x2=\\\"440\\\" y2=\\\"82\\\" stroke=\\\"#1b7837\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"489\\\" y1=\\\"64\\\" x2=\\\"582\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"678\\\" y1=\\\"64\\\" x2=\\\"582\\\" y2=\\\"64\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"582\\\" cy=\\\"64\\\" r=\\\"20\\\" stroke=\\\"#9970ab\\\" stroke-width=\\\"1.5\\\" fill=\\\"#c2a5cf\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"569\\\" y=\\\"68.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"538\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"82\\\" x2=\\\"556\\\" y2=\\\"82\\\" stroke=\\\"#1b7837\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"607\\\" y=\\\"80\\\" fill=\\\"#1b7837\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"445\\\" y=\\\"34\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"445\\\" y=\\\"64\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"445\\\" y=\\\"34\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"445\\\" y1=\\\"64\\\" x2=\\\"533\\\" y2=\\\"64\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"453\\\" y=\\\"55.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t<text x=\\\"453\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"631\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#a6dba0\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"631\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#d9f0d3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"631\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"631\\\" y1=\\\"47\\\" x2=\\\"725\\\" y2=\\\"47\\\" stroke=\\\"#5aae61\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"642\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"639\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"639\\\" y1=\\\"67\\\" x2=\\\"714\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"639\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"639\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --seed=3 --colors brewer+3\\n\",\n      \"Client: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\\n\",\n      \"Passer, 0N Client, 11 Commande\\n\",\n      \"Commande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\\n\",\n      \"DF, _11 Inclure, 1N Commande\\n\",\n      \"Inclure: _Quantité [INTEGER]\\n\",\n      \"DF, _11 Inclure, 0N Produit\\n\",\n      \"Produit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t explode:weak,arity=2 arrange:wide --seed=3 --colors brewer+3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez l'argument `arrange:wide`. Il a procédé à une réorganisation aléatoire des boîtes, ce que l'insertion de deux nouvelles associations de dépendance fonctionnelles avait rendu nécessaire. Quant à l'option `--seed=3`, elle garantit que le résultat sera le même à chaque exécution.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Après cet aperçu de quelques-unes des fonctionnalités de Mocodo, entrons dans les détails.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Installation et lancement du programme\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme nous l'avons dit, vous pouvez utiliser Mocodo sans rien installer. Il vous suffit d'aller sur [mocodo.net](https://www.mocodo.net) et de commencer à taper votre MCD. Appuyez à tout moment sur le ventilateur pour rafraîchir les diagrammes conceptuel et relationnel. Quand le résultat vous convient, appuyez sur le bouton de téléchargement pour récupérer une archive ZIP contenant tous les fichiers d'entrée et de sortie spécifiés.\\n\",\n    \"\\n\",\n    \"Mocodo _online_ est conçu pour une utilisation occasionnelle et/ou interactive, et son interface vise avant tout à la simplicité. Vous n'avez donc accès qu'aux options essentielles du programme. Si vous en voulez davantage, tant en termes de paramétrage que de calcul ou de fonctionnalités, nous vous conseillons d'installer Mocodo sur votre machine.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Installation minimale\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo est un programme écrit en [Python 3](https://www.python.org). Si vous êtes sous macOS ou Linux, il est déjà installé. Dans le cas contraire, vous devrez peut-être [le faire](https://www.python.org/downloads/).\\n\",\n    \"\\n\",\n    \"Une fois Python présent sur votre machine, tapez sous un terminal:\\n\",\n    \"\\n\",\n    \"        python -m pip install mocodo\\n\",\n    \"\\n\",\n    \"Puis testez-le :\\n\",\n    \"\\n\",\n    \"        mocodo\\n\",\n    \"\\n\",\n    \"Invoqué sous cette forme, Mocodo récupère le texte d'entrée du MCD dans le répertoire courant sous le nom de `sandbox.mcd`. Si ce fichier n'existe pas, il y sera automatiquement créé avec un MCD d'exemple. Par la suite, vous n'aurez qu'à le garder ouvert sous un éditeur de texte, afin de le modifier à votre fantaisie avant de relancer la commande.\\n\",\n    \"\\n\",\n    \"Si votre système se plaint que cette commande n'existe pas, localisez le fichier `mocodo` et ajoutez à votre `PATH` le chemin du répertoire contenant:\\n\",\n    \"- [sous Linux ou macOS](http://www.commentcamarche.net/faq/3585-bash-la-variable-d-environnement-path#v-ajouter-un-repertoire-a-la-variable-path) ;\\n\",\n    \"- [sous Windows](http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Installation complète (recommandé)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"- Installez la [distribution Anaconda](https://www.anaconda.com/download), qui contient Python 3, Jupyter Notebook et bien plus encore.\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"- La ligne donnée précédemment installe en fait, en plus de Mocodo, sa « commande magique » pour [Jupyter Notebook](https://jupyter.org). Nous l'avons déjà invoquée plusieurs fois dans ce document :\\n\",\n    \"\\n\",\n    \"        python -m pip install mocodo\\n\",\n    \"\\n\",\n    \"- Mocodo fonctionne parfaitement sans aucune dépendance. Cependant, si vous souhaitez :\\n\",\n    \"    - utiliser l'option `--svg_to` pour générer des figures en PDF ou en PNG ;\\n\",\n    \"    - copier directement dans le presse-papier le résultat d'une réécriture ;\\n\",\n    \"\\n\",\n    \"  ... vous pouvez installer les dépendances optionnelles aux bibliothèques [CairoSVG](https://cairosvg.org) et [Pyperclip](https://github.com/asweigart/pyperclip) ainsi :\\n\",\n    \"  \\n\",\n    \"        python -m pip install 'mocodo[svg,clipboard]'\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour mettre la « commande magique » `mocodo` à disposition d'un _notebook_ donné, évaluez dans celui-ci la cellule suivante:\\n\",\n    \"\\n\",\n    \"    %reload_ext mocodo\\n\",\n    \"\\n\",\n    \"Techniquement, `%load_ext mocodo` suffit, mais cette forme vous épargnera un message d'erreur si vous réévaluez ultérieurement la cellule.\\n\",\n    \"\\n\",\n    \"Pour tester la commande :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"114\\\" height=\\\"78\\\" viewBox=\\\"0 0 114 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"114\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity MISSION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"96\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"105\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">MISSION</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">accomplie</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"80\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"MISSION: accomplie\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour charger automatiquement `mocodo` à chaque ouverture d'un notebook (ce qui dispense d'évaluer `%load_ext mocodo`) :\\n\",\n    \"\\n\",\n    \"- exécutez sous un terminal :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"ipython profile create\\n\",\n    \"```\\n\",\n    \"\\t\\n\",\n    \"- éditez le fichier créé (p. ex.: `~/.ipython/profile_default/ipython_config.py`) en remplaçant la ligne suivante :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"# c.TerminalIPythonApp.extensions = []\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"  par celle-ci :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"c.InteractiveShellApp.extensions = [\\\"mocodo\\\"]\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Utilisation par importation\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.1.3.** Un _wrapper_ minimaliste permet de simuler programmatiquement l'appel à la commande `mocodo`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from mocodo.api import mocodo\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ainsi, l'équivalent de :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"mocodo -i ccp --colors mondrian\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"... s'écrira :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"messages = mocodo(\\\"-i ccp --colors mondrian\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Par défaut (second argument `quiet=True`), la fonction n'affiche pas les messages de succès, mais renvoie leur concaténation :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Fichier de sortie « ~/Dropbox/Sites/mocodo/doc/mocodo_notebook/ccp.svg » généré avec succès.\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(messages)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Plus important, les fichiers de sortie sont bel bien créés :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"594\\\" height=\\\"128\\\" viewBox=\\\"0 0 594 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"594\\\" height=\\\"128\\\" fill=\\\"#fefeec\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#081a84\\\" stroke=\\\"#081a84\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#fefeec\\\" stroke=\\\"#fefeec\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M448 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#081a84\\\" stroke=\\\"#081a84\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M462 63 v16 a14 14 90 0 1 -14 14 H390 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#fefeec\\\" stroke=\\\"#fefeec\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"376\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"376\\\" y1=\\\"63\\\" x2=\\\"462\\\" y2=\\\"63\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"56.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"81.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"467\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"491\\\" y1=\\\"47\\\" x2=\\\"585\\\" y2=\\\"47\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"38.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"64.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"499\\\" y1=\\\"67\\\" x2=\\\"574\\\" y2=\\\"67\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"81.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"98\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"execution_count\": 15,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.SVG(\\\"ccp.svg\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Si vous travaillez sous une implantation de Jupyter Notebook qui ne prend pas en charge les commandes magiques, l'importation conseillée est :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 16,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from mocodo.magic import mocodo\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Elle permet de simuler les commandes magiques, aussi bien celles qui sont réduites à une ligne :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 17,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"594\\\" height=\\\"128\\\" viewBox=\\\"0 0 594 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"594\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M448 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M462 63 v16 a14 14 90 0 1 -14 14 H390 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"376\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"376\\\" y1=\\\"63\\\" x2=\\\"462\\\" y2=\\\"63\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"56.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"81.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"467\\\" y=\\\"80\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"491\\\" y1=\\\"47\\\" x2=\\\"585\\\" y2=\\\"47\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"38.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"64.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"499\\\" y1=\\\"67\\\" x2=\\\"574\\\" y2=\\\"67\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"81.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"98\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"mocodo(\\\"%mocodo -i ccp --colors ocean\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"... que celles qui portent sur toute une cellule :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"106\\\" height=\\\"78\\\" viewBox=\\\"0 0 106 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"106\\\" height=\\\"78\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity MISSION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"97\\\" y2=\\\"39\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Mission</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">accomplie</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"80\\\" y2=\\\"59\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"mocodo(\\\"\\\"\\\"\\n\",\n    \"%%mocodo --colors pond\\n\",\n    \"Mission: accomplie\\n\",\n    \"\\\"\\\"\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le préfixe `\\\"%mocodo\\\"` ou `\\\"%%mocodo\\\"` est ignoré, mais l'autoriser permet de copier toute une ligne ou toute une cellule (vraiment) magique, et de la coller directement comme argument de la fonction.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.2.** Avec cette technique, Mocodo peut être utilisé sous [Basthon](https://basthon.fr) v. 0.62.12 ou ultérieure. Basthon est une plateforme permettant de travailler sous Jupyter Notebook sans avoir à rien installer. Son auteur, Romain Casati, a ajouté un exemple d'utilisation de Mocodo dans la [galerie](https://basthon.fr/galerie.html) du logiciel, à tester [ici](https://notebook.basthon.fr/?from=examples/python3-mocodo.ipynb). Sous Mocodo _online_, cliquez sur le symbole de lecture de Basthon (dans le pied de page) pour ouvrir un notebook avec le MCD en cours d'édition.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Syntaxe de description d'un MCD\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Notions élémentaires\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Entités, associations, attributs, identifiants, cardinalités\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 19,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"128\\\" viewBox=\\\"0 0 630 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M196 35 a14 14 90 0 1 14 14 V63 h-88 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M210 63 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V63 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"35\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"63\\\" x2=\\\"210\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"571\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M478 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M492 63 v16 a14 14 90 0 1 -14 14 H408 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"63\\\" x2=\\\"492\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"402\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"401\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"370\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"239\\\" y1=\\\"47\\\" x2=\\\"365\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"248\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"247\\\" y1=\\\"67\\\" x2=\\\"355\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"521\\\" y1=\\\"47\\\" x2=\\\"621\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"529\\\" y1=\\\"67\\\" x2=\\\"604\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"PASSER, 0N CLIENT, 11 COMMANDE\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Passons en revue les principes de la syntaxe. Ils ne devraient pas poser trop de problèmes.\\n\",\n    \"\\n\",\n    \"**La première ligne** ne fait pas partie de la définition du MCD. Sous Jupyter Notebook, elle dénote l'appel à une « commande magique », qui lance Mocodo sur le reste de la cellule. En dehors d'un notebook, vous n'en avez pas besoin, et toute ligne commençant par un pourcentage (`%`) sera considérée comme un commentaire.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Une entité** est définie par :\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\overbrace{\\\\texttt{COMMANDE}}^{\\\\text{son nom}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{:}}^{\\\\text{deux-points}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{Num. commande, Date, Montant}}^{\\\\text{ses attributs séparés par des virgules}}\\n\",\n    \"$$ \\n\",\n    \"\\n\",\n    \"Notez que le premier attribut d'une entité est considéré par défaut comme son identifiant, et donc souligné.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Une association** est définie par :\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\overbrace{\\\\texttt{INCLURE}}^{\\\\text{son nom}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{,}}^{\\\\text{une virgule}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\n\",\n    \"    \\\\underbrace{\\\\texttt{1N}}_{\\\\text{cardinalités}}\\n\",\n    \"    \\\\underbrace{\\\\texttt{COMMANDE}}_{\\\\text{entité}}\\n\",\n    \"    \\\\quad\\n\",\n    \"    ,\\n\",\n    \"    \\\\quad\\n\",\n    \"    \\\\underbrace{\\\\texttt{0N}}_{\\\\text{cardinalités}}\\n\",\n    \"    \\\\underbrace{\\\\texttt{PRODUIT}}_{\\\\text{entité}}\\n\",\n    \"}^{\\\\text{ses pattes séparées par des virgules}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{:}}^{\\\\text{deux-points}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{Quantité}}^{\\\\text{ses attributs séparés par des virgules}}\\n\",\n    \"$$ \\n\",\n    \"\\n\",\n    \"Notez que pour les associations sans attributs (comme PASSER), le deux-points est facultatif.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Astuce.** Si vous recopiez un MCD ou que vous l'avez bien en tête, commencez par les associations et, à tout moment, faites apparaître les entités manquantes (double clic sur le lapin magique sous Mocodo online). Elles auront comme identifiant le nom de l'entité en minuscules, par défaut précédé de « id. » (sauf pour les entités DATE et PÉRIODE). Vous n'aurez plus qu'à remplir les autres attributs :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 20,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"312\\\" height=\\\"176\\\" viewBox=\\\"0 0 312 176\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"312\\\" height=\\\"176\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"129\\\" x2=\\\"165\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"165\\\" y1=\\\"129\\\" x2=\\\"165\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"273\\\" y1=\\\"129\\\" x2=\\\"165\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M201 9 a14 14 90 0 1 14 14 V37 h-100 V23 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M215 37 v16 a14 14 90 0 1 -14 14 H129 a14 14 90 0 1 -14 -14 V37 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"115\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"115\\\" y1=\\\"37\\\" x2=\\\"215\\\" y2=\\\"37\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"122\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réserver</text>\\n\",\n       \"\\t\\t<text x=\\\"122\\\" y=\\\"55.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"108.84\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"170\\\" y=\\\"83\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"113.5\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"91\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"121\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"91\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"121\\\" x2=\\\"87\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"112.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"138.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"141\\\" x2=\\\"70\\\" y2=\\\"141\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"91\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"121\\\" width=\\\"98\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"91\\\" width=\\\"98\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"121\\\" x2=\\\"214\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"125\\\" y=\\\"112.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"124\\\" y=\\\"138.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. chambre</text>\\n\",\n       \"\\t<line x1=\\\"124\\\" y1=\\\"141\\\" x2=\\\"197\\\" y2=\\\"141\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"243\\\" y=\\\"99\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"243\\\" y=\\\"129\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"243\\\" y=\\\"99\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"243\\\" y1=\\\"129\\\" x2=\\\"303\\\" y2=\\\"129\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"252\\\" y=\\\"120.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"251\\\" y=\\\"146.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"251\\\" y1=\\\"149\\\" x2=\\\"279\\\" y2=\\\"149\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo \\n\",\n      \"Réserver, 1N Client, 1N Chambre, 0N Date: Durée\\n\",\n      \"\\n\",\n      \"Client: id. client, \\n\",\n      \"Chambre: id. chambre, \\n\",\n      \"Date: date\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t guess:entities\\n\",\n    \"Réserver, 1N Client, 1N Chambre, 0N Date: Durée\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Dépendances fonctionnelles entre entités\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Lorsque l'une des cardinalités maximales d'une association binaire est 1 (ou quelquefois 0), on désigne cette association sous le nom de **dépendance fonctionnelle**. On la figure souvent par un cercle portant le symbole DF : cela évite de se creuser la tête pour trouver un nom à une association qui (_spoiler_) disparaîtra corps et biens au moment du passage au relationnel.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 21,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"582\\\" height=\\\"128\\\" viewBox=\\\"0 0 582 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"582\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"142\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"254\\\" y1=\\\"64\\\" x2=\\\"142\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"142\\\" cy=\\\"64\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"68.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"168\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"254\\\" y1=\\\"64\\\" x2=\\\"395\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"523\\\" y1=\\\"64\\\" x2=\\\"395\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M430 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M444 63 v16 a14 14 90 0 1 -14 14 H360 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"346\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"346\\\" y1=\\\"63\\\" x2=\\\"444\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"354\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"353\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"322\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"449\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"191\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"191\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"191\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"191\\\" y1=\\\"47\\\" x2=\\\"317\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"199\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"199\\\" y1=\\\"67\\\" x2=\\\"307\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"199\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"199\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"473\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"473\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"473\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"473\\\" y1=\\\"47\\\" x2=\\\"573\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"482\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"481\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"481\\\" y1=\\\"67\\\" x2=\\\"556\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"481\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"481\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"DF, 0N CLIENT, 11 COMMANDE\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Associations réflexives\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Quelquefois appelées **circulaires**, **unaires** ou **récursives**, elles associent une entité à elle-même. Voici par exemple une représentation des filiations patrilinéaires (le 01 permet d'« arrêter » la remontée des ancêtres) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"267\\\" height=\\\"112\\\" viewBox=\\\"0 0 267 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"267\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ENGENDRER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M53 56 C84.67 24 131 24 192 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M53 56 C84 88 130.33 88 192 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M244 27 a14 14 90 0 1 14 14 V55 h-132 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M258 55 v16 a14 14 90 0 1 -14 14 H140 a14 14 90 0 1 -14 -14 V55 H132\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"126\\\" y=\\\"27\\\" width=\\\"132\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"126\\\" y1=\\\"55\\\" x2=\\\"258\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"134\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ENGENDRER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"49\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"71\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity HOMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"97\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">HOMME</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. SS</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"71\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"HOMME: Num. SS, Nom, Prénom\\n\",\n    \"ENGENDRER, 0N HOMME, 01 HOMME\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Identifiants composites\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Préfixez d'un tiret bas (`_`) les second, troisième, etc. attributs pour les inclure dans l'identifiant.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"174\\\" height=\\\"146\\\" viewBox=\\\"0 0 174 146\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"174\\\" height=\\\"146\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRATTE_CIEL -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"156\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"156\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"156\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"165\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">GRATTE-CIEL</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">latitude</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"64\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">longitude</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"76\\\" x2=\\\"75\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">hauteur</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">année de construction</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"GRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Flèches sur les pattes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Suffixez d'un chevron (`<` ou `>`) les cardinalités de la patte concernée. La direction indiquée se lit en partant de l'association et en allant vers l'entité.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 24,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"762\\\" height=\\\"128\\\" viewBox=\\\"0 0 762 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"762\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PEUT_RECEVOIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M261 64 C194 96 133.67 96 80 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"180.0 87.39 168.53 94.36 172.03 88.05 167.54 82.41\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M261 64 C194 32 133.67 32 80 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"150.99 40.63 162.43 33.61 158.96 39.93 163.47 45.56\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M137 35 a14 14 90 0 1 14 14 V63 h-142 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M151 63 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V63 H142\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"142\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"63\\\" x2=\\\"151\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Peut recevoir</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"79\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"57\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association APPARTIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"567\\\" y1=\\\"64\\\" x2=\\\"428\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"514 64 502 70 506 64 502 58\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"261\\\" y1=\\\"64\\\" x2=\\\"428\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M471 35 a14 14 90 0 1 14 14 V63 h-114 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M485 63 v16 a14 14 90 0 1 -14 14 H385 a14 14 90 0 1 -14 -14 V63 H114\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"371\\\" y=\\\"35\\\" width=\\\"114\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"371\\\" y1=\\\"63\\\" x2=\\\"485\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"378\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Appartient</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"491\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"347\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ENGENDRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M567 64 C612.33 32 657 32 701 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"648.99 41.13 636.21 45.21 641.09 39.9 638.06 33.35\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M567 64 C611.67 96 656.33 96 701 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"620.01 86.95 632.76 82.79 627.92 88.14 630.99 94.66\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M739 35 a14 14 90 0 1 14 14 V63 h-104 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M753 63 v16 a14 14 90 0 1 -14 14 H663 a14 14 90 0 1 -14 -14 V63 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"649\\\" y=\\\"35\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"649\\\" y1=\\\"63\\\" x2=\\\"753\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"656\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Engendre</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"625\\\" y=\\\"57\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"625\\\" y=\\\"79\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">2,2</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GROUPE_SANGUIN -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"180\\\" y=\\\"34\\\" width=\\\"162\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"180\\\" y=\\\"64\\\" width=\\\"162\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"180\\\" y=\\\"34\\\" width=\\\"162\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"180\\\" y1=\\\"64\\\" x2=\\\"342\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"188\\\" y=\\\"55.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Groupe sanguin</text>\\n\",\n       \"\\t<text x=\\\"188\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">type de sang</text>\\n\",\n       \"\\t<line x1=\\\"188\\\" y1=\\\"84\\\" x2=\\\"266\\\" y2=\\\"84\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERSONNE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"514\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"514\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"514\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"514\\\" y1=\\\"39\\\" x2=\\\"620\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"523\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Personne</text>\\n\",\n       \"\\t<text x=\\\"522\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. SS</text>\\n\",\n       \"\\t<line x1=\\\"522\\\" y1=\\\"59\\\" x2=\\\"576\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"522\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"522\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"522\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Sexe</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Peut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin\\n\",\n    \"Groupe sanguin: type de sang\\n\",\n    \"Appartient, 11> Personne, 0N Groupe sanguin\\n\",\n    \"Personne: Num. SS, Nom, Prénom, Sexe\\n\",\n    \"Engendre, 0N< Personne, 22> Personne\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Types de données\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme on l'a vu dans l'introduction, chaque attribut peut être assorti d'un type entre crochets, qui servira lors de la conversion en SQL. À partir de la version 4.0, Mocodo est capable de deviner le type des attributs usuels à partir de leur nom :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 25,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_data_dict_3.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"| Entité ou association | Libellé de l'attribut | Type          |\\n\",\n       \"|:----------------------|:----------------------|:--------------|\\n\",\n       \"| CLIENT                | Adresse               | VARCHAR(30)   |\\n\",\n       \"| \\\"                     | Nom                   | VARCHAR(255)  |\\n\",\n       \"| \\\"                     | Prénom                | VARCHAR(255)  |\\n\",\n       \"| \\\"                     | Réf. client           | VARCHAR(8)    |\\n\",\n       \"| COMMANDE              | Date                  | DATE          |\\n\",\n       \"| \\\"                     | Montant               | DECIMAL(10,2) |\\n\",\n       \"| \\\"                     | Num. commande         | VARCHAR(8)    |\\n\",\n       \"| INCLURE               | Quantité              | INTEGER       |\\n\",\n       \"| PRODUIT               | Libellé               | VARCHAR(50)   |\\n\",\n       \"| \\\"                     | Prix unitaire         | DECIMAL(10,2) |\\n\",\n       \"| \\\"                     | Réf. produit          | VARCHAR(8)    |\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t guess:types data_dict --select cv\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"PASSER, 0N CLIENT, 11 COMMANDE\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.3.** Avec l'option `-t prompt:types`, Mocodo compose un _prompt_ à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec les types manquants. Ce _prompt_ est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les types générés par [Claude 3.5 Haiku](https://claude.ai/chat/d4fb8fa7-fb68-43ae-b255-fa10dcc5cb84) pour le MCD de la page d'accueil de Mocodo online :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_data_dict_3.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"| Entité ou association | Libellé de l'attribut | Type         |\\n\",\n       \"|:----------------------|:----------------------|:-------------|\\n\",\n       \"| AYANT-DROIT           | lien                  | VARCHAR(50)  |\\n\",\n       \"| \\\"                     | nom ayant-droit       | VARCHAR(100) |\\n\",\n       \"| COMPOSER              | quantité              | INTEGER      |\\n\",\n       \"| DÉPARTEMENT           | nom département       | VARCHAR(100) |\\n\",\n       \"| \\\"                     | num. département      | VARCHAR(20)  |\\n\",\n       \"| EMPLOYÉ               | matricule             | VARCHAR(20)  |\\n\",\n       \"| \\\"                     | nom employé           | VARCHAR(100) |\\n\",\n       \"| FOURNIR               | qté fournie           | INTEGER      |\\n\",\n       \"| PIÈCE                 | libellé pièce         | VARCHAR(255) |\\n\",\n       \"| \\\"                     | réf. pièce            | VARCHAR(20)  |\\n\",\n       \"| PROJET                | nom projet            | VARCHAR(255) |\\n\",\n       \"| \\\"                     | num. projet           | VARCHAR(20)  |\\n\",\n       \"| REQUÉRIR              | qté requise           | INTEGER      |\\n\",\n       \"| SOCIÉTÉ               | num. société          | VARCHAR(20)  |\\n\",\n       \"| \\\"                     | raison sociale        | VARCHAR(255) |\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t data_dict\\n\",\n    \"AYANT-DROIT: nom ayant-droit [VARCHAR(100)], lien [VARCHAR(50)]\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise [INTEGER]\\n\",\n    \"PIÈCE: réf. pièce [VARCHAR(20)], libellé pièce [VARCHAR(255)]\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité [INTEGER]\\n\",\n    \"\\n\",\n    \"DF, _11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule [VARCHAR(20)], nom employé [VARCHAR(100)]\\n\",\n    \"PROJET: num. projet [VARCHAR(20)], nom projet [VARCHAR(255)]\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie [INTEGER]\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département [VARCHAR(20)], nom département [VARCHAR(100)]\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société [VARCHAR(20)], raison sociale [VARCHAR(255)]\\n\",\n    \"CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ce problème d'inférence n'est pas très difficile pour une IA. Les résultats devraient être très bons, surtout en comparaison de ceux de la version purement algorithmique, qui sont généralement incomplets :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 27,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_data_dict_3.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"| Entité ou association | Libellé de l'attribut | Type         |\\n\",\n       \"|:----------------------|:----------------------|:-------------|\\n\",\n       \"| AYANT-DROIT           | lien                  |              |\\n\",\n       \"| \\\"                     | nom ayant-droit       | VARCHAR(255) |\\n\",\n       \"| COMPOSER              | quantité              | INTEGER      |\\n\",\n       \"| DÉPARTEMENT           | nom département       | VARCHAR(255) |\\n\",\n       \"| \\\"                     | num. département      | VARCHAR(8)   |\\n\",\n       \"| EMPLOYÉ               | matricule             |              |\\n\",\n       \"| \\\"                     | nom employé           | VARCHAR(255) |\\n\",\n       \"| FOURNIR               | qté fournie           | INTEGER      |\\n\",\n       \"| PIÈCE                 | libellé pièce         |              |\\n\",\n       \"| \\\"                     | réf. pièce            | VARCHAR(8)   |\\n\",\n       \"| PROJET                | nom projet            | VARCHAR(255) |\\n\",\n       \"| \\\"                     | num. projet           | VARCHAR(8)   |\\n\",\n       \"| REQUÉRIR              | qté requise           | INTEGER      |\\n\",\n       \"| SOCIÉTÉ               | num. société          | VARCHAR(8)   |\\n\",\n       \"| \\\"                     | raison sociale        |              |\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t guess:types data_dict --select cv\\n\",\n    \"AYANT-DROIT: nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, _11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Tracé d'un MCD : principes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo combine les avantages de l'approche _diagram as code_ (comme PlantUML, Mermaid ou Graphviz), avec la liberté de positionnement offerte par les logiciels WYSIWYG (_what you see is what you get_).\\n\",\n    \"\\n\",\n    \"Sa grande originalité est de se baser sur l'ordre et la séparation des lignes de la description pour définir une mise en page qui se révèle suffisante dans la majorité des cas.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Le pont aux ânes du langage Mocodo\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Premier principe : les boîtes (entités et associations) définies sur des **lignes consécutives** sont tracées sur **une seule rangée**.\\n\",\n    \"\\n\",\n    \"Si l'on écrit les définitions sur des lignes consécutives, on se retrouve donc vite avec des chevauchements qui ne sautent pas forcément aux yeux :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 28,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"128\\\" viewBox=\\\"0 0 630 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"450\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"185\\\" y1=\\\"64\\\" x2=\\\"450\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M480 35 a14 14 90 0 1 14 14 V63 h-88 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M494 63 v16 a14 14 90 0 1 -14 14 H420 a14 14 90 0 1 -14 -14 V63 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"406\\\" y=\\\"35\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"406\\\" y1=\\\"63\\\" x2=\\\"494\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"413\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"253\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"185\\\" y1=\\\"64\\\" x2=\\\"572\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"327\\\" y1=\\\"64\\\" x2=\\\"572\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M607 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M621 63 v16 a14 14 90 0 1 -14 14 H537 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"523\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"523\\\" y1=\\\"63\\\" x2=\\\"621\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"531\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"530\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"253\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"382\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"47\\\" x2=\\\"248\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"131\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"130\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"130\\\" y1=\\\"67\\\" x2=\\\"238\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"130\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"130\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"277\\\" y1=\\\"47\\\" x2=\\\"377\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"286\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"67\\\" x2=\\\"360\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\\n\",\n    \"PASSER, 0N CLIENT, 11 COMMANDE\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'option `--detect_overlaps` (active par défaut sous Mocodo online) signale le problème et donne la solution :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 29,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.29 - Mauvaise disposition des boîtes :\\n\",\n      \"  - La patte « INCLURE — COMMANDE » chevauche « PRODUIT ».\\n\",\n      \"  - La patte « INCLURE — PRODUIT » chevauche « PASSER ».\\n\",\n      \"  - La patte « PASSER — CLIENT » chevauche « COMMANDE ».\\n\",\n      \"  - Les pattes  « PASSER — COMMANDE » et « INCLURE — COMMANDE » se chevauchent.\\n\",\n      \"Pour corriger cela, réordonnez et/ou sautez des lignes dans le texte-source, soit à la\\n\",\n      \"main, soit à l'aide de l'option -t arrange (tablette de chocolat sous Mocodo online).\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --detect_overlaps\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Limitation.** Seuls les chevauchements mettant en jeu des pattes horizontales ou verticales sont détectés.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### MCD sur plusieurs lignes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Deuxième principe : pour commencer une nouvelle rangée, il faut sauter une ligne :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 30,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"415\\\" height=\\\"246\\\" viewBox=\\\"0 0 415 246\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"415\\\" height=\\\"246\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association EROS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"118\\\" y1=\\\"56\\\" x2=\\\"292\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"292\\\" y1=\\\"182\\\" x2=\\\"292\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M311 19 a14 14 90 0 1 14 14 V47 h-66 V33 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M325 47 v32 a14 14 90 0 1 -14 14 H273 a14 14 90 0 1 -14 -14 V47 H66\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"259\\\" y=\\\"19\\\" width=\\\"66\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"259\\\" y1=\\\"47\\\" x2=\\\"325\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"266\\\" y=\\\"40.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EROS</text>\\n\",\n       \"\\t\\t<text x=\\\"266\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t\\t<text x=\\\"266\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">congue</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"232\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association NIBH -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"118\\\" y1=\\\"56\\\" x2=\\\"118\\\" y2=\\\"182\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"292\\\" y1=\\\"182\\\" x2=\\\"118\\\" y2=\\\"182\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M135 153 a14 14 90 0 1 14 14 V181 h-62 V167 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M149 181 v16 a14 14 90 0 1 -14 14 H101 a14 14 90 0 1 -14 -14 V181 H62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"87\\\" y=\\\"153\\\" width=\\\"62\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"87\\\" y1=\\\"181\\\" x2=\\\"149\\\" y2=\\\"181\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"94\\\" y=\\\"174.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">NIBH</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"123\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"155\\\" y=\\\"198\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SCELERISQUE_LOREM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"218\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"218\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"218\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"227\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SCELERISQUE LOREM</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">blandit</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"59\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">elit</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PELLENTESQUE_IPSUM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"127\\\" width=\\\"228\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"157\\\" width=\\\"228\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"127\\\" width=\\\"228\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"178\\\" y1=\\\"157\\\" x2=\\\"406\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"187\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PELLENTESQUE IPSUM</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tincidunt</text>\\n\",\n       \"\\t<line x1=\\\"186\\\" y1=\\\"177\\\" x2=\\\"241\\\" y2=\\\"177\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bibendum</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"208.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"225\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">integer</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"SCELERISQUE LOREM: blandit, elit, ligula\\n\",\n    \"EROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue\\n\",\n    \"\\n\",\n    \"NIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM\\n\",\n    \"PELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les centres des boîtes sont placés aux intersections d'une grille invisible. Ils sont donc alignés aussi bien horizontalement que verticalement. De plus, dans un but esthétique, le dessin fait l'objet d'une compression dans les deux dimensions. Par exemple, ci-dessus, un espace horizontal négatif a été créé entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Mise en miroir\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo permet de calculer facilement les symétriques d'un MCD :\\n\",\n    \"\\n\",\n    \"- verticalement : `-t flip:v` ;\\n\",\n    \"- horizontalement : `-t flip:h` ;\\n\",\n    \"- selon la seconde diagonale (transposition) : `-t flip:d`.\\n\",\n    \"- selon la première diagonale (transposition) : `-t flip:vhd`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 31,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"415\\\" height=\\\"246\\\" viewBox=\\\"0 0 415 246\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"415\\\" height=\\\"246\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association EROS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"297\\\" y1=\\\"56\\\" x2=\\\"123\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"123\\\" y1=\\\"182\\\" x2=\\\"123\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M142 19 a14 14 90 0 1 14 14 V47 h-66 V33 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M156 47 v32 a14 14 90 0 1 -14 14 H104 a14 14 90 0 1 -14 -14 V47 H66\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"90\\\" y=\\\"19\\\" width=\\\"66\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"90\\\" y1=\\\"47\\\" x2=\\\"156\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"97\\\" y=\\\"40.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EROS</text>\\n\",\n       \"\\t\\t<text x=\\\"97\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t\\t<text x=\\\"97\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">congue</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"165\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association NIBH -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"297\\\" y1=\\\"56\\\" x2=\\\"297\\\" y2=\\\"182\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"123\\\" y1=\\\"182\\\" x2=\\\"297\\\" y2=\\\"182\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M314 153 a14 14 90 0 1 14 14 V181 h-62 V167 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M328 181 v16 a14 14 90 0 1 -14 14 H280 a14 14 90 0 1 -14 -14 V181 H62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"266\\\" y=\\\"153\\\" width=\\\"62\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"266\\\" y1=\\\"181\\\" x2=\\\"328\\\" y2=\\\"181\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"273\\\" y=\\\"174.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">NIBH</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"302\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"242\\\" y=\\\"198\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SCELERISQUE_LOREM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"188\\\" y=\\\"9\\\" width=\\\"218\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"188\\\" y=\\\"39\\\" width=\\\"218\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"188\\\" y=\\\"9\\\" width=\\\"218\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"188\\\" y1=\\\"39\\\" x2=\\\"406\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"196\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SCELERISQUE LOREM</text>\\n\",\n       \"\\t<text x=\\\"196\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">blandit</text>\\n\",\n       \"\\t<line x1=\\\"196\\\" y1=\\\"59\\\" x2=\\\"238\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"196\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">elit</text>\\n\",\n       \"\\t<text x=\\\"196\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PELLENTESQUE_IPSUM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"127\\\" width=\\\"228\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"157\\\" width=\\\"228\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"127\\\" width=\\\"228\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"157\\\" x2=\\\"237\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PELLENTESQUE IPSUM</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tincidunt</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"177\\\" x2=\\\"72\\\" y2=\\\"177\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bibendum</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"208.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"225\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">integer</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --select mcd -t flip:h\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Corrections de la version 4.0.**\\n\",\n    \"- Les sens de « horizontal » et « vertical » sont permutés pour être plus conformes à l'intuition.\\n\",\n    \"- La documentation parlait de première diagonale, c'était la seconde, et vice-versa.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Astuce.** Transposez le MCD  temporairement pour réaliser plus facilement certaines opérations d'édition en colonne, en particulier sous Mocodo online.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Insertion d'espacements\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Ce comportement n'est pas toujours idéal :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 32,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"579\\\" height=\\\"310\\\" viewBox=\\\"0 0 579 310\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"579\\\" height=\\\"310\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M176 64 C138.67 96 98.67 96 56 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M176 64 C138 32 98 32 56 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M89 35 a14 14 90 0 1 14 14 V63 h-94 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M103 63 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V63 H94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"94\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"63\\\" x2=\\\"103\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109\\\" y=\\\"79\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"57\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"311\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"64\\\" x2=\\\"311\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M330 35 a14 14 90 0 1 14 14 V63 h-66 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M344 63 v16 a14 14 90 0 1 -14 14 H292 a14 14 90 0 1 -14 -14 V63 H66\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"278\\\" y=\\\"35\\\" width=\\\"66\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"278\\\" y1=\\\"63\\\" x2=\\\"344\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"285\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"56\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"355\\\" y=\\\"56\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M415 64 C445.67 32 482.33 32 525 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M415 64 C445.67 96 482.33 96 525 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M556 35 a14 14 90 0 1 14 14 V63 h-90 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M570 63 v16 a14 14 90 0 1 -14 14 H494 a14 14 90 0 1 -14 -14 V63 H90\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"480\\\" y=\\\"35\\\" width=\\\"90\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"480\\\" y1=\\\"63\\\" x2=\\\"570\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"487\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"456\\\" y=\\\"58\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"456\\\" y=\\\"78\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"176\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"263\\\" x2=\\\"176\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M216 143 a14 14 90 0 1 14 14 V171 h-108 V157 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M230 171 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V171 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"143\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"171\\\" x2=\\\"230\\\" y2=\\\"171\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"130\\\" y=\\\"164.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"189.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"152\\\" y=\\\"135\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"359\\\" y=\\\"263.84\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"263\\\" x2=\\\"311\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"64\\\" x2=\\\"311\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M349 143 a14 14 90 0 1 14 14 V171 h-104 V157 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M363 171 v16 a14 14 90 0 1 -14 14 H273 a14 14 90 0 1 -14 -14 V171 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"259\\\" y=\\\"143\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"259\\\" y1=\\\"171\\\" x2=\\\"363\\\" y2=\\\"171\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"266\\\" y=\\\"164.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"360\\\" y=\\\"244.59\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"355\\\" y=\\\"100.27\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"263\\\" x2=\\\"311\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"263\\\" x2=\\\"311\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"311\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M340 226 a14 14 90 0 1 14 14 V254 h-86 V240 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M354 254 v32 a14 14 90 0 1 -14 14 H282 a14 14 90 0 1 -14 -14 V254 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"268\\\" y=\\\"226\\\" width=\\\"86\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"268\\\" y1=\\\"254\\\" x2=\\\"354\\\" y2=\\\"254\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"276\\\" y=\\\"247.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"275\\\" y=\\\"272.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"275\\\" y=\\\"289.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"279\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"359\\\" y=\\\"279\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"194.5\\\" y=\\\"135\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"39\\\" x2=\\\"220\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"140\\\" y1=\\\"59\\\" x2=\\\"199\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"379\\\" y=\\\"26\\\" width=\\\"72\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"379\\\" y=\\\"56\\\" width=\\\"72\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"379\\\" y=\\\"26\\\" width=\\\"72\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"379\\\" y1=\\\"56\\\" x2=\\\"451\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"387\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"387\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"387\\\" y1=\\\"76\\\" x2=\\\"426\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"387\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"233\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"263\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"233\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"263\\\" x2=\\\"220\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"254.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"280.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"140\\\" y1=\\\"283\\\" x2=\\\"183\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"383\\\" y=\\\"225\\\" width=\\\"64\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"383\\\" y=\\\"255\\\" width=\\\"64\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"383\\\" y=\\\"225\\\" width=\\\"64\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"383\\\" y1=\\\"255\\\" x2=\\\"447\\\" y2=\\\"255\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"393\\\" y=\\\"246.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"391\\\" y=\\\"272.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"391\\\" y1=\\\"275\\\" x2=\\\"421\\\" y2=\\\"275\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"391\\\" y=\\\"289.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo \\n\",\n    \"Ultrices, 01 Aliquet, 0N Aliquet\\n\",\n    \"Aliquet: hendrerit, metus, lacus, quis\\n\",\n    \"Risus, 1N Aliquet, 0N Massa\\n\",\n    \"Massa: metus, posuere\\n\",\n    \"Euismod, 0N Massa, 0N Massa\\n\",\n    \"\\n\",\n    \"Convallis, 0N Aliquet, 0N Ante: vestibulum\\n\",\n    \"Tincidunt, 11 Ante, 0N Massa\\n\",\n    \"\\n\",\n    \"Gravida: ornare\\n\",\n    \"Rutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae\\n\",\n    \"Ante: vitae, tempor\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'utilisateur peut alors spécifier les espacements qu'il désire en complétant les rangées par des boîtes invisibles dont le seul rôle est de « pousser » les autres à l'emplacement voulu. Cela se fait en insérant manuellement des lignes réduites au caractère deux-points :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 33,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"581\\\" height=\\\"310\\\" viewBox=\\\"0 0 581 310\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"581\\\" height=\\\"310\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M176 64 C138.67 96 98.67 96 56 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M176 64 C138 32 98 32 56 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M89 35 a14 14 90 0 1 14 14 V63 h-94 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M103 63 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V63 H94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"94\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"63\\\" x2=\\\"103\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109\\\" y=\\\"79\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"57\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"282\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"64\\\" x2=\\\"282\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M301 35 a14 14 90 0 1 14 14 V63 h-66 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M315 63 v16 a14 14 90 0 1 -14 14 H263 a14 14 90 0 1 -14 -14 V63 H66\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"249\\\" y=\\\"35\\\" width=\\\"66\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"249\\\" y1=\\\"63\\\" x2=\\\"315\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"256\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"56\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M417 64 C447.67 32 484.33 32 527 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M417 64 C447.67 96 484.33 96 527 64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M558 35 a14 14 90 0 1 14 14 V63 h-90 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M572 63 v16 a14 14 90 0 1 -14 14 H496 a14 14 90 0 1 -14 -14 V63 H90\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"482\\\" y=\\\"35\\\" width=\\\"90\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"482\\\" y1=\\\"63\\\" x2=\\\"572\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"489\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"458\\\" y=\\\"58\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"458\\\" y=\\\"78\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"282\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"263\\\" x2=\\\"282\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M322 143 a14 14 90 0 1 14 14 V171 h-108 V157 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M336 171 v16 a14 14 90 0 1 -14 14 H242 a14 14 90 0 1 -14 -14 V171 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"228\\\" y=\\\"143\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"228\\\" y1=\\\"171\\\" x2=\\\"336\\\" y2=\\\"171\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"236\\\" y=\\\"164.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"235\\\" y=\\\"189.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"107.81\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"361\\\" y=\\\"252.27\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"263\\\" x2=\\\"417\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"64\\\" x2=\\\"417\\\" y2=\\\"172\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M455 143 a14 14 90 0 1 14 14 V171 h-104 V157 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M469 171 v16 a14 14 90 0 1 -14 14 H379 a14 14 90 0 1 -14 -14 V171 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"365\\\" y=\\\"143\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"365\\\" y1=\\\"171\\\" x2=\\\"469\\\" y2=\\\"171\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"372\\\" y=\\\"164.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"422\\\" y=\\\"217\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"422\\\" y=\\\"118\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"56\\\" y1=\\\"263\\\" x2=\\\"176\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"263\\\" x2=\\\"176\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"176\\\" y1=\\\"64\\\" x2=\\\"176\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M205 226 a14 14 90 0 1 14 14 V254 h-86 V240 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M219 254 v32 a14 14 90 0 1 -14 14 H147 a14 14 90 0 1 -14 -14 V254 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"226\\\" width=\\\"86\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"133\\\" y1=\\\"254\\\" x2=\\\"219\\\" y2=\\\"254\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"141\\\" y=\\\"247.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"140\\\" y=\\\"272.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"140\\\" y=\\\"289.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"105\\\" y=\\\"279\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"361\\\" y=\\\"279\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"152\\\" y=\\\"135\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"39\\\" x2=\\\"220\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"140\\\" y1=\\\"59\\\" x2=\\\"199\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"381\\\" y=\\\"26\\\" width=\\\"72\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"381\\\" y=\\\"56\\\" width=\\\"72\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"381\\\" y=\\\"26\\\" width=\\\"72\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"381\\\" y1=\\\"56\\\" x2=\\\"453\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"389\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"389\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"389\\\" y1=\\\"76\\\" x2=\\\"428\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"389\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"12\\\" y=\\\"233\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"12\\\" y=\\\"263\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"12\\\" y=\\\"233\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"12\\\" y1=\\\"263\\\" x2=\\\"100\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"254.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"280.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"20\\\" y1=\\\"283\\\" x2=\\\"63\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"385\\\" y=\\\"225\\\" width=\\\"64\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"385\\\" y=\\\"255\\\" width=\\\"64\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"385\\\" y=\\\"225\\\" width=\\\"64\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"385\\\" y1=\\\"255\\\" x2=\\\"449\\\" y2=\\\"255\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"395\\\" y=\\\"246.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"393\\\" y=\\\"272.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"393\\\" y1=\\\"275\\\" x2=\\\"423\\\" y2=\\\"275\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"393\\\" y=\\\"289.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Ultrices, 01 Aliquet, 0N Aliquet\\n\",\n    \"Aliquet: hendrerit, metus, lacus, quis\\n\",\n    \"Risus, 1N Aliquet, 0N Massa\\n\",\n    \"Massa: metus, posuere\\n\",\n    \"Euismod, 0N Massa, 0N Massa\\n\",\n    \"\\n\",\n    \":\\n\",\n    \":\\n\",\n    \"Convallis, 0N Aliquet, 0N Ante: vestibulum\\n\",\n    \"Tincidunt, 11 Ante, 0N Massa\\n\",\n    \"\\n\",\n    \"Gravida: ornare\\n\",\n    \"Rutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae\\n\",\n    \":\\n\",\n    \"Ante: vitae, tempor\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Réarrangement automatique\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cependant, en général, ces manipulations sont inutiles : Mocodo est capable de calculer tout seul des plongements à la fois compacts et esthétiques. Voici une compilation des réarrangements automatiques du MCD précédent produits par :\\n\",\n    \"```\\n\",\n    \"%mocodo -i sandbox -t arrange --seed 1\\n\",\n    \"%mocodo -i sandbox -t arrange --seed 2\\n\",\n    \"%mocodo -i sandbox -t arrange --seed 3\\n\",\n    \"%mocodo -i sandbox -t arrange --seed 4\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 34,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"934\\\" height=\\\"582\\\" viewBox=\\\"0 0 934 582\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"934\\\" height=\\\"582\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"336\\\" y1=\\\"98\\\" x2=\\\"243\\\" y2=\\\"31\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"98\\\" x2=\\\"243\\\" y2=\\\"31\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M273.8 7 a11.2 11.2 90 0 1 11.2 11.2 V30 h-84 V18.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M285 30 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H212.2 a11.2 11.2 90 0 1 -11.2 -11.2 V30 H84\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"201\\\" y=\\\"7\\\" width=\\\"84\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"201\\\" y1=\\\"30\\\" x2=\\\"285\\\" y2=\\\"30\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"207\\\" y=\\\"24.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"292\\\" y=\\\"88.22\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"86.1\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M147 98 C127 123.33 93 123.33 45 98\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M147 98 C127 72.67 93 72.67 45 98\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M70.8 74 a11.2 11.2 90 0 1 11.2 11.2 V97 h-74 V85.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M82 97 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H19.2 a11.2 11.2 90 0 1 -11.2 -11.2 V97 H74\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"8\\\" y=\\\"74\\\" width=\\\"74\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"8\\\" y1=\\\"97\\\" x2=\\\"82\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"15\\\" y=\\\"91.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"99\\\" y=\\\"109.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"99\\\" y=\\\"92.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"243\\\" y1=\\\"187\\\" x2=\\\"243\\\" y2=\\\"98\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"336\\\" y1=\\\"98\\\" x2=\\\"243\\\" y2=\\\"98\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M275.8 74 a11.2 11.2 90 0 1 11.2 11.2 V97 h-88 V85.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M287 97 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H210.2 a11.2 11.2 90 0 1 -11.2 -11.2 V97 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"199\\\" y=\\\"74\\\" width=\\\"88\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"199\\\" y1=\\\"97\\\" x2=\\\"287\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"206\\\" y=\\\"91.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"205\\\" y=\\\"112.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"134.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"292\\\" y=\\\"110.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"187\\\" x2=\\\"674\\\" y2=\\\"98\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"776\\\" y1=\\\"98\\\" x2=\\\"674\\\" y2=\\\"98\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M689.8 74 a11.2 11.2 90 0 1 11.2 11.2 V97 h-54 V85.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M701 97 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H658.2 a11.2 11.2 90 0 1 -11.2 -11.2 V97 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"647\\\" y=\\\"74\\\" width=\\\"54\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"647\\\" y1=\\\"97\\\" x2=\\\"701\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"653\\\" y=\\\"91.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"678\\\" y=\\\"134.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"728\\\" y=\\\"110.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M776 98 C793.67 72.67 830 72.67 885 98\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M776 98 C793.67 123.33 830 123.33 885 98\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M910.8 74 a11.2 11.2 90 0 1 11.2 11.2 V97 h-74 V85.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M922 97 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H859.2 a11.2 11.2 90 0 1 -11.2 -11.2 V97 H74\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"848\\\" y=\\\"74\\\" width=\\\"74\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"848\\\" y1=\\\"97\\\" x2=\\\"922\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"855\\\" y=\\\"91.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"809\\\" y=\\\"92.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"809\\\" y=\\\"109.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"243\\\" y1=\\\"187\\\" x2=\\\"147\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"98\\\" x2=\\\"147\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M162.8 163 a11.2 11.2 90 0 1 11.2 11.2 V186 h-54 V174.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M174 186 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H131.2 a11.2 11.2 90 0 1 -11.2 -11.2 V186 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"120\\\" y=\\\"163\\\" width=\\\"54\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"120\\\" y1=\\\"186\\\" x2=\\\"174\\\" y2=\\\"186\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"126\\\" y=\\\"180.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"199.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"151\\\" y=\\\"142.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"429\\\" y1=\\\"187\\\" x2=\\\"336\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"336\\\" y1=\\\"98\\\" x2=\\\"336\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"243\\\" y1=\\\"187\\\" x2=\\\"336\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M359.8 156 a11.2 11.2 90 0 1 11.2 11.2 V179 h-70 V167.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M371 179 v27.8 a11.2 11.2 90 0 1 -11.2 11.2 H312.2 a11.2 11.2 90 0 1 -11.2 -11.2 V179 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"156\\\" width=\\\"70\\\" height=\\\"62\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"301\\\" y1=\\\"179\\\" x2=\\\"371\\\" y2=\\\"179\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"308\\\" y=\\\"173.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"307\\\" y=\\\"194.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"307\\\" y=\\\"208.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"375\\\" y=\\\"199.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"340\\\" y=\\\"142.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"199.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M674 187 C644 212.33 612 212.33 578 187\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M674 187 C644 161.67 612 161.67 578 187\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M604.8 163 a11.2 11.2 90 0 1 11.2 11.2 V186 h-76 V174.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M616 186 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H551.2 a11.2 11.2 90 0 1 -11.2 -11.2 V186 H76\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"540\\\" y=\\\"163\\\" width=\\\"76\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"540\\\" y1=\\\"186\\\" x2=\\\"616\\\" y2=\\\"186\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"546\\\" y=\\\"180.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"620\\\" y=\\\"198.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"620\\\" y=\\\"181.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"187\\\" x2=\\\"776\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"776\\\" y1=\\\"283\\\" x2=\\\"776\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M808.8 163 a11.2 11.2 90 0 1 11.2 11.2 V186 h-88 V174.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M820 186 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H743.2 a11.2 11.2 90 0 1 -11.2 -11.2 V186 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"732\\\" y=\\\"163\\\" width=\\\"88\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"732\\\" y1=\\\"186\\\" x2=\\\"820\\\" y2=\\\"186\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"739\\\" y=\\\"180.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"738\\\" y=\\\"201.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"713\\\" y=\\\"199.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"757\\\" y=\\\"244.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"776\\\" y1=\\\"283\\\" x2=\\\"885\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M776 98 C775.16 135.09 811.49 164.76 885 187\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M915.8 163 a11.2 11.2 90 0 1 11.2 11.2 V186 h-84 V174.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M927 186 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H854.2 a11.2 11.2 90 0 1 -11.2 -11.2 V186 H84\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"843\\\" y=\\\"163\\\" width=\\\"84\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"843\\\" y1=\\\"186\\\" x2=\\\"927\\\" y2=\\\"186\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"849\\\" y=\\\"180.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"805\\\" y=\\\"268.43\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"803.15\\\" y=\\\"142.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M243 187 C273.67 229 273.67 261 243 283\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M243 187 C212.33 229 212.33 261 243 283\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M269.8 259 a11.2 11.2 90 0 1 11.2 11.2 V282 h-76 V270.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M281 282 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H216.2 a11.2 11.2 90 0 1 -11.2 -11.2 V282 H76\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"205\\\" y=\\\"259\\\" width=\\\"76\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"205\\\" y1=\\\"282\\\" x2=\\\"281\\\" y2=\\\"282\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"211\\\" y=\\\"276.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"246\\\" y=\\\"245.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"245.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"578\\\" y1=\\\"283\\\" x2=\\\"674\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"776\\\" y1=\\\"283\\\" x2=\\\"674\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"187\\\" x2=\\\"674\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M697.8 252 a11.2 11.2 90 0 1 11.2 11.2 V275 h-70 V263.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M709 275 v27.8 a11.2 11.2 90 0 1 -11.2 11.2 H650.2 a11.2 11.2 90 0 1 -11.2 -11.2 V275 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"252\\\" width=\\\"70\\\" height=\\\"62\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"639\\\" y1=\\\"275\\\" x2=\\\"709\\\" y2=\\\"275\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"646\\\" y=\\\"269.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"645\\\" y=\\\"290.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"645\\\" y=\\\"304.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"617\\\" y=\\\"295.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"732\\\" y=\\\"295.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"678\\\" y=\\\"245.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M147 379 C119 404.33 85 404.33 45 379\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M147 379 C119 353.67 85 353.67 45 379\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M71.8 355 a11.2 11.2 90 0 1 11.2 11.2 V378 h-76 V366.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M83 378 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H18.2 a11.2 11.2 90 0 1 -11.2 -11.2 V378 H76\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"7\\\" y=\\\"355\\\" width=\\\"76\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"7\\\" y1=\\\"378\\\" x2=\\\"83\\\" y2=\\\"378\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"13\\\" y=\\\"372.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"93\\\" y=\\\"390.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"93\\\" y=\\\"373.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"379\\\" x2=\\\"243\\\" y2=\\\"379\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"243\\\" y1=\\\"468\\\" x2=\\\"243\\\" y2=\\\"379\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M258.8 355 a11.2 11.2 90 0 1 11.2 11.2 V378 h-54 V366.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M270 378 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H227.2 a11.2 11.2 90 0 1 -11.2 -11.2 V378 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"216\\\" y=\\\"355\\\" width=\\\"54\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"216\\\" y1=\\\"378\\\" x2=\\\"270\\\" y2=\\\"378\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"222\\\" y=\\\"372.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"391.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"429.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RISUS4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"379\\\" x2=\\\"578\\\" y2=\\\"379\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"578\\\" y1=\\\"468\\\" x2=\\\"578\\\" y2=\\\"379\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M593.8 355 a11.2 11.2 90 0 1 11.2 11.2 V378 h-54 V366.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M605 378 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H562.2 a11.2 11.2 90 0 1 -11.2 -11.2 V378 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"551\\\" y=\\\"355\\\" width=\\\"54\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"551\\\" y1=\\\"378\\\" x2=\\\"605\\\" y2=\\\"378\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"557\\\" y=\\\"372.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Risus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"620\\\" y=\\\"391.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"582\\\" y=\\\"429.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ULTRICES4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M674 379 C702 353.67 736 353.67 776 379\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M674 379 C702 404.33 736 404.33 776 379\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M802.8 355 a11.2 11.2 90 0 1 11.2 11.2 V378 h-76 V366.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M814 378 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H749.2 a11.2 11.2 90 0 1 -11.2 -11.2 V378 H76\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"738\\\" y=\\\"355\\\" width=\\\"76\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"738\\\" y1=\\\"378\\\" x2=\\\"814\\\" y2=\\\"378\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"744\\\" y=\\\"372.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ultrices</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"713\\\" y=\\\"373.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"713\\\" y=\\\"390.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"45\\\" y1=\\\"543\\\" x2=\\\"45\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"543\\\" x2=\\\"45\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M147 379 C138.35 425.61 104.35 455.28 45 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M68.8 437 a11.2 11.2 90 0 1 11.2 11.2 V460 h-70 V448.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M80 460 v27.8 a11.2 11.2 90 0 1 -11.2 11.2 H21.2 a11.2 11.2 90 0 1 -11.2 -11.2 V460 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"10\\\" y=\\\"437\\\" width=\\\"70\\\" height=\\\"62\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"10\\\" y1=\\\"460\\\" x2=\\\"80\\\" y2=\\\"460\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"17\\\" y=\\\"454.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"475.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"489.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"511.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"532.77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"93\\\" y=\\\"437.71\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"379\\\" x2=\\\"147\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"543\\\" x2=\\\"147\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M179.8 444 a11.2 11.2 90 0 1 11.2 11.2 V467 h-88 V455.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M191 467 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H114.2 a11.2 11.2 90 0 1 -11.2 -11.2 V467 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"103\\\" y=\\\"444\\\" width=\\\"88\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"103\\\" y1=\\\"467\\\" x2=\\\"191\\\" y2=\\\"467\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"110\\\" y=\\\"461.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"109\\\" y=\\\"482.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"151\\\" y=\\\"437.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"151\\\" y=\\\"504.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M243 468 C266 442.67 297 442.67 336 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M243 468 C266 493.33 297 493.33 336 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M361.8 444 a11.2 11.2 90 0 1 11.2 11.2 V467 h-74 V455.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M373 467 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H310.2 a11.2 11.2 90 0 1 -11.2 -11.2 V467 H74\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"299\\\" y=\\\"444\\\" width=\\\"74\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"299\\\" y1=\\\"467\\\" x2=\\\"373\\\" y2=\\\"467\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"306\\\" y=\\\"461.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"276\\\" y=\\\"462.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"276\\\" y=\\\"479.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EUISMOD4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M578 468 C553.67 493.33 524 493.33 489 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M578 468 C553.67 442.67 524 442.67 489 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M514.8 444 a11.2 11.2 90 0 1 11.2 11.2 V467 h-74 V455.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M526 467 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H463.2 a11.2 11.2 90 0 1 -11.2 -11.2 V467 H74\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"452\\\" y=\\\"444\\\" width=\\\"74\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"452\\\" y1=\\\"467\\\" x2=\\\"526\\\" y2=\\\"467\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"459\\\" y=\\\"461.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Euismod</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"479.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"462.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONVALLIS4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"379\\\" x2=\\\"674\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"543\\\" x2=\\\"674\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M706.8 444 a11.2 11.2 90 0 1 11.2 11.2 V467 h-88 V455.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M718 467 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H641.2 a11.2 11.2 90 0 1 -11.2 -11.2 V467 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"630\\\" y=\\\"444\\\" width=\\\"88\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"630\\\" y1=\\\"467\\\" x2=\\\"718\\\" y2=\\\"467\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"637\\\" y=\\\"461.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Convallis</text>\\n\",\n       \"\\t\\t<text x=\\\"636\\\" y=\\\"482.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vestibulum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"655\\\" y=\\\"437.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"655\\\" y=\\\"504.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RUTRUM4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"885\\\" y1=\\\"468\\\" x2=\\\"776\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"543\\\" x2=\\\"776\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M674 379 C682.65 425.61 716.65 455.28 776 468\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M799.8 437 a11.2 11.2 90 0 1 11.2 11.2 V460 h-70 V448.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M811 460 v27.8 a11.2 11.2 90 0 1 -11.2 11.2 H752.2 a11.2 11.2 90 0 1 -11.2 -11.2 V460 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"741\\\" y=\\\"437\\\" width=\\\"70\\\" height=\\\"62\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"741\\\" y1=\\\"460\\\" x2=\\\"811\\\" y2=\\\"460\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"748\\\" y=\\\"454.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Rutrum</text>\\n\",\n       \"\\t\\t<text x=\\\"747\\\" y=\\\"475.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">faucibus</text>\\n\",\n       \"\\t\\t<text x=\\\"747\\\" y=\\\"489.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">curae</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"831\\\" y=\\\"480.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"703\\\" y=\\\"532.77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"713\\\" y=\\\"437.71\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"147\\\" y1=\\\"543\\\" x2=\\\"243\\\" y2=\\\"543\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"243\\\" y1=\\\"468\\\" x2=\\\"243\\\" y2=\\\"543\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M273.8 519 a11.2 11.2 90 0 1 11.2 11.2 V542 h-84 V530.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M285 542 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H212.2 a11.2 11.2 90 0 1 -11.2 -11.2 V542 H84\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"201\\\" y=\\\"519\\\" width=\\\"84\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"201\\\" y1=\\\"542\\\" x2=\\\"285\\\" y2=\\\"542\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"207\\\" y=\\\"536.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"176\\\" y=\\\"555.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"512.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TINCIDUNT4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"543\\\" x2=\\\"578\\\" y2=\\\"543\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"578\\\" y1=\\\"468\\\" x2=\\\"578\\\" y2=\\\"543\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M608.8 519 a11.2 11.2 90 0 1 11.2 11.2 V542 h-84 V530.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M620 542 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H547.2 a11.2 11.2 90 0 1 -11.2 -11.2 V542 H84\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"536\\\" y=\\\"519\\\" width=\\\"84\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"536\\\" y1=\\\"542\\\" x2=\\\"620\\\" y2=\\\"542\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"542\\\" y=\\\"536.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Tincidunt</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"630\\\" y=\\\"555.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"582\\\" y=\\\"512.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"118\\\" y=\\\"66\\\" width=\\\"58\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"118\\\" y=\\\"91\\\" width=\\\"58\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"118\\\" y=\\\"66\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"118\\\" y1=\\\"91\\\" x2=\\\"176\\\" y2=\\\"91\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"125\\\" y=\\\"83.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"124\\\" y=\\\"105.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"124\\\" y1=\\\"107.6\\\" x2=\\\"155\\\" y2=\\\"107.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"124\\\" y=\\\"119.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"311\\\" y=\\\"66\\\" width=\\\"50\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"311\\\" y=\\\"91\\\" width=\\\"50\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"311\\\" y=\\\"66\\\" width=\\\"50\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"311\\\" y1=\\\"91\\\" x2=\\\"361\\\" y2=\\\"91\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"319\\\" y=\\\"83.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"317\\\" y=\\\"105.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"317\\\" y1=\\\"107.6\\\" x2=\\\"341\\\" y2=\\\"107.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"317\\\" y=\\\"119.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"747\\\" y=\\\"66\\\" width=\\\"58\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"747\\\" y=\\\"91\\\" width=\\\"58\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"747\\\" y=\\\"66\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"747\\\" y1=\\\"91\\\" x2=\\\"805\\\" y2=\\\"91\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"754\\\" y=\\\"83.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"753\\\" y=\\\"105.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"753\\\" y1=\\\"107.6\\\" x2=\\\"784\\\" y2=\\\"107.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"753\\\" y=\\\"119.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"208\\\" y=\\\"141\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"208\\\" y=\\\"166\\\" width=\\\"70\\\" height=\\\"67\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"208\\\" y=\\\"141\\\" width=\\\"70\\\" height=\\\"92\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"208\\\" y1=\\\"166\\\" x2=\\\"278\\\" y2=\\\"166\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"215\\\" y=\\\"158.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"214\\\" y=\\\"180.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"214\\\" y1=\\\"182.6\\\" x2=\\\"262\\\" y2=\\\"182.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"214\\\" y=\\\"194.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"214\\\" y=\\\"208.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"214\\\" y=\\\"222.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"162\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"187\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"162\\\" width=\\\"70\\\" height=\\\"50\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"187\\\" x2=\\\"464\\\" y2=\\\"187\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"400\\\" y=\\\"179.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"400\\\" y=\\\"201.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"400\\\" y1=\\\"203.6\\\" x2=\\\"435\\\" y2=\\\"203.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"141\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"166\\\" width=\\\"70\\\" height=\\\"67\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"141\\\" width=\\\"70\\\" height=\\\"92\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"639\\\" y1=\\\"166\\\" x2=\\\"709\\\" y2=\\\"166\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"646\\\" y=\\\"158.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"180.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"645\\\" y1=\\\"182.6\\\" x2=\\\"693\\\" y2=\\\"182.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"194.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"208.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"222.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"543\\\" y=\\\"258\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"543\\\" y=\\\"283\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"543\\\" y=\\\"258\\\" width=\\\"70\\\" height=\\\"50\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"543\\\" y1=\\\"283\\\" x2=\\\"613\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"549\\\" y=\\\"275.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"549\\\" y=\\\"297.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"549\\\" y1=\\\"299.6\\\" x2=\\\"584\\\" y2=\\\"299.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"751\\\" y=\\\"251\\\" width=\\\"50\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"751\\\" y=\\\"276\\\" width=\\\"50\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"751\\\" y=\\\"251\\\" width=\\\"50\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"751\\\" y1=\\\"276\\\" x2=\\\"801\\\" y2=\\\"276\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"759\\\" y=\\\"268.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"757\\\" y=\\\"290.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"757\\\" y1=\\\"292.6\\\" x2=\\\"781\\\" y2=\\\"292.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"757\\\" y=\\\"304.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"333\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"358\\\" width=\\\"70\\\" height=\\\"67\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"333\\\" width=\\\"70\\\" height=\\\"92\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"112\\\" y1=\\\"358\\\" x2=\\\"182\\\" y2=\\\"358\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"119\\\" y=\\\"350.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"372.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"118\\\" y1=\\\"374.6\\\" x2=\\\"166\\\" y2=\\\"374.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"386.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"400.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"414.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ALIQUET4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"333\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"358\\\" width=\\\"70\\\" height=\\\"67\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"639\\\" y=\\\"333\\\" width=\\\"70\\\" height=\\\"92\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"639\\\" y1=\\\"358\\\" x2=\\\"709\\\" y2=\\\"358\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"646\\\" y=\\\"350.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Aliquet</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"372.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">hendrerit</text>\\n\",\n       \"\\t<line x1=\\\"645\\\" y1=\\\"374.6\\\" x2=\\\"693\\\" y2=\\\"374.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"386.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"400.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">lacus</text>\\n\",\n       \"\\t<text x=\\\"645\\\" y=\\\"414.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">quis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"214\\\" y=\\\"436\\\" width=\\\"58\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"214\\\" y=\\\"461\\\" width=\\\"58\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"214\\\" y=\\\"436\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"214\\\" y1=\\\"461\\\" x2=\\\"272\\\" y2=\\\"461\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"221\\\" y=\\\"453.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"220\\\" y=\\\"475.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"220\\\" y1=\\\"477.6\\\" x2=\\\"251\\\" y2=\\\"477.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"220\\\" y=\\\"489.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MASSA4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"549\\\" y=\\\"436\\\" width=\\\"58\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"549\\\" y=\\\"461\\\" width=\\\"58\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"549\\\" y=\\\"436\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"549\\\" y1=\\\"461\\\" x2=\\\"607\\\" y2=\\\"461\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"556\\\" y=\\\"453.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Massa</text>\\n\",\n       \"\\t<text x=\\\"555\\\" y=\\\"475.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">metus</text>\\n\",\n       \"\\t<line x1=\\\"555\\\" y1=\\\"477.6\\\" x2=\\\"586\\\" y2=\\\"477.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"555\\\" y=\\\"489.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">posuere</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"850\\\" y=\\\"443\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"850\\\" y=\\\"468\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"850\\\" y=\\\"443\\\" width=\\\"70\\\" height=\\\"50\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"850\\\" y1=\\\"468\\\" x2=\\\"920\\\" y2=\\\"468\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"856\\\" y=\\\"460.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"856\\\" y=\\\"482.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"856\\\" y1=\\\"484.6\\\" x2=\\\"891\\\" y2=\\\"484.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GRAVIDA3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"10\\\" y=\\\"518\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"10\\\" y=\\\"543\\\" width=\\\"70\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"10\\\" y=\\\"518\\\" width=\\\"70\\\" height=\\\"50\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"10\\\" y1=\\\"543\\\" x2=\\\"80\\\" y2=\\\"543\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"16\\\" y=\\\"535.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Gravida</text>\\n\",\n       \"\\t<text x=\\\"16\\\" y=\\\"557.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">ornare</text>\\n\",\n       \"\\t<line x1=\\\"16\\\" y1=\\\"559.6\\\" x2=\\\"51\\\" y2=\\\"559.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"511\\\" width=\\\"50\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"536\\\" width=\\\"50\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"511\\\" width=\\\"50\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"536\\\" x2=\\\"172\\\" y2=\\\"536\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"130\\\" y=\\\"528.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"550.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"128\\\" y1=\\\"552.6\\\" x2=\\\"152\\\" y2=\\\"552.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"564.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANTE4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"649\\\" y=\\\"511\\\" width=\\\"50\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"649\\\" y=\\\"536\\\" width=\\\"50\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"649\\\" y=\\\"511\\\" width=\\\"50\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"649\\\" y1=\\\"536\\\" x2=\\\"699\\\" y2=\\\"536\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"657\\\" y=\\\"528.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">Ante</text>\\n\",\n       \"\\t<text x=\\\"655\\\" y=\\\"550.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">vitae</text>\\n\",\n       \"\\t<line x1=\\\"655\\\" y1=\\\"552.6\\\" x2=\\\"679\\\" y2=\\\"552.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"655\\\" y=\\\"564.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">tempor</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ../examples/four_random_layouts --scale 0.8\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Extensions du modèle\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Entité faible (ou identification relative)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Préfixez d'un tiret bas (`_`) une cardinalité 11 pour indiquer que l'entité distinguée est faible.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 35,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"354\\\" height=\\\"112\\\" viewBox=\\\"0 0 354 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"354\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"61\\\" y1=\\\"56\\\" x2=\\\"162\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"56\\\" x2=\\\"162\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"162\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"149\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"188\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"188\\\" y1=\\\"74\\\" x2=\\\"206\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"113\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ŒUVRE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Cote œuvre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"94\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date parution</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"39\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"211\\\" y1=\\\"39\\\" x2=\\\"345\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. exemplaire</text>\\n\",\n       \"\\t<line x1=\\\"219\\\" y1=\\\"59\\\" x2=\\\"327\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">État du livre</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date d’achat</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"ŒUVRE: Cote œuvre, Titre, Date parution\\n\",\n    \"DF, 1N ŒUVRE, _11 EXEMPLAIRE\\n\",\n    \"EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans le diagramme, les identifiants (ou plutôt, discriminateurs) d'une telle entité seront soulignés en pointillés, tandis que le 11 sera par défaut souligné d'un trait plein.\\n\",\n    \"\\n\",\n    \"Notez qu'un discriminateur n'est pas toujours obligatoire :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 36,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"362\\\" height=\\\"112\\\" viewBox=\\\"0 0 362 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"362\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"292\\\" y1=\\\"56\\\" x2=\\\"182\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"71\\\" y1=\\\"56\\\" x2=\\\"182\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"182\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"169\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"208\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"208\\\" y1=\\\"74\\\" x2=\\\"226\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"138\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"133\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Employé</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. employé</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"110\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom employé</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CONJOINT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"231\\\" y=\\\"18\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"231\\\" y=\\\"48\\\" width=\\\"122\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"231\\\" y=\\\"18\\\" width=\\\"122\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"231\\\" y1=\\\"48\\\" x2=\\\"353\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"251\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Conjoint</text>\\n\",\n       \"\\t<text x=\\\"239\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom conjoint</text>\\n\",\n       \"\\t<text x=\\\"239\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom conjoint</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo \\n\",\n    \"Employé: Num. employé, Nom employé, Prénom employé\\n\",\n    \"Df, _11 Conjoint, 01 Employé\\n\",\n    \"Conjoint: _Nom conjoint, Prénom conjoint\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Son absence implique cependant que l'occurrence de l'entité forte qui « renforce » une occurrence de l'entité faible ne peut en renforcer une autre : d'où la cardinalité maximale 1 sur la patte distinguant EMPLOYÉ.\\n\",\n    \"\\n\",\n    \"Mocodo rejettera donc la version « polygame » du MCD précédent (avec 0N à la place de 01) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 37,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.50 - L'entité faible « CONJOINT » devrait avoir un discriminateur.\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Employé: Num. employé, Nom employé, Prénom employé\\n\",\n    \"Df, _11 Conjoint, 0N Employé\\n\",\n    \"Conjoint: _Nom conjoint, Prénom conjoint\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Héritage (généralisation / spécialisation)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'héritage permet de regrouper dans une entité, dite « mère », les attributs communs à plusieurs autres entités, dites « filles », qui se distinguent les unes des autres par des attributs spécifiques.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour définir une spécialisation, insérez une ligne spécifiant :\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\overbrace{\\\\texttt{/}\\\\,\\\\texttt{XT}\\\\,\\\\texttt{\\\\\\\\}}^{\\\\text{sa nature entre barres obliques}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\overbrace{\\\\texttt{<}\\\\,\\\\texttt{-}}^{\\\\text{son type de flèche}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\overbrace{\\\\texttt{mère}}^{\\\\text{une entité}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\overbrace{\\\\texttt{,}}^{\\\\text{une virgule}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\overbrace{\\\\texttt{fille 1, fille 2, fille 3}}^{\\\\text{des entités séparées par des virgules}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\overbrace{\\\\texttt{: discriminateur}}^{\\\\text{optionnellement, un attribut}}\\n\",\n    \"$$ \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 38,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"296\\\" height=\\\"270\\\" viewBox=\\\"0 0 296 270\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"296\\\" height=\\\"270\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance PERSONNE_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"130\\\" y1=\\\"56\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"130 103 136 115 130 111 124 115\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"223\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"130 123.13 105 166.43 155 166.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"118\\\" y=\\\"158\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">XT</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERSONNE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"77\\\" y1=\\\"39\\\" x2=\\\"183\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"86\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Personne</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num SS</text>\\n\",\n       \"\\t<line x1=\\\"85\\\" y1=\\\"59\\\" x2=\\\"131\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prénom</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity HOMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"240\\\" width=\\\"78\\\" height=\\\"12\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"42\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"240\\\" x2=\\\"87\\\" y2=\\\"240\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"231.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Homme</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FEMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"231\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"159\\\" y1=\\\"231\\\" x2=\\\"287\\\" y2=\\\"231\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"222.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Femme</text>\\n\",\n       \"\\t<text x=\\\"167\\\" y=\\\"248.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom de jeune fille</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Personne: num SS, nom, prénom\\n\",\n    \"\\n\",\n    \"/XT\\\\ Personne <- Homme, Femme: sexe\\n\",\n    \"\\n\",\n    \"Homme: \\n\",\n    \":\\n\",\n    \"Femme: nom de jeune fille\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Inscrivez dans le triangle les symboles de votre choix pour prendre une part active aux guerres culturelles de notre temps :\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"| Totalité | Exclusion | Symboles | Exemple de population | Toute personne est : |\\n\",\n    \"|----------|-----------|:--------:|:---------------------:|:---------------------|\\n\",\n    \"| oui        | oui         | `/XT\\\\`  | <big>♂♂♂♂♂♂♂<br>♀♀♀♀♀♀♀♀♀♀</big> | - soit un homme<br>- soit une femme |\\n\",\n    \"| non        | oui         | `/X\\\\`   | <big>♂♂♂♂♂♂♂♂<br>♀♀♀♀♀♀<br>○○○○</big> | - soit un homme<br>- soit une femme<br>- soit aucun des deux |\\n\",\n    \"| oui        | non         | `/T\\\\`   | <big>♂♂♂♂♂♂<br>♀♀♀♀♀♀♀♀<br>⚥⚥⚥⚥</big> | - soit un homme<br>- soit une femme<br>- soit les deux à la fois |\\n\",\n    \"| non        | non         | `/\\\\`    | <big>♂♂♂♂♂<br>♀♀♀♀♀♀<br>○○○○<br>⚥⚥⚥⚥</big> | - soit un homme<br>- soit une femme<br>- soit aucun des deux<br>- soit les deux à la fois |\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Contrainte inter-associations\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour définir une telle contrainte, ajoutez n'importe où une ligne spécifiant :\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\overbrace{\\\\texttt{(}\\\\,\\\\texttt{FOO}\\\\,\\\\texttt{)}}^{\\\\text{son nom entre parenthèses}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\n\",\n    \"    \\\\texttt{-}\\\\,\\\\texttt{>}\\n\",\n    \"    \\\\texttt{boîte 1,}\\n\",\n    \"    \\\\quad\\n\",\n    \"    \\\\texttt{.}\\\\,\\\\texttt{.}\\n\",\n    \"    \\\\texttt{boîte 2,}\\n\",\n    \"    \\\\quad\\n\",\n    \"    \\\\texttt{-}\\\\,\\\\texttt{-}\\n\",\n    \"    \\\\texttt{boîte 3,}\\n\",\n    \"    \\\\quad\\n\",\n    \"    \\\\texttt{boîte 4}\\n\",\n    \"}^{\\\\text{les types de liens et les boîtes qu'elle met en jeu, séparés par des virgules}}\\n\",\n    \"\\\\quad\\n\",\n    \"\\\\overbrace{\\\\texttt{:}\\\\,\\\\,\\\\texttt{horizontale, verticale}}^{\\\\text{optionnellement, ses coordonnées}}\\n\",\n    \"$$ \\n\",\n    \"\\n\",\n    \"**Précisions.**\\n\",\n    \"- Comme leur nom ne l'indique pas, ces contraintes peuvent aussi bien porter sur des entités que des associations.\\n\",\n    \"- Le nom d'une contrainte peut être formé de zéro à trois symboles quelconques.\\n\",\n    \"- Un lien est soit vide (trait invisible), soit formé d'un ou plusieurs symboles `-` (trait plein) ou `.` (trait pointillé), optionnellement précédés d'un symbole `<` (flèche vers la contrainte) et/ou suivis d'un symbole `>` (flèche vers la boîte).\\n\",\n    \"- Au contraire des boîtes (entités et associations), les contraintes ne sont pas... contraintes par la grille sous-jacente : la mise en page du MCD n'en tient absolument pas compte. Celui de l'exemple ci-dessous a donc dû être « aéré » avec des `:` pour leur faire de la place.\\n\",\n    \"- Les clauses de définition des contraintes peuvent apparaître n'importe où. Notez cependant que tout réarrangement automatique les enverra systématiquement à la fin du texte-source.\\n\",\n    \"- Chaque coordonnée du centre de la contrainte peut être exprimée sous la forme :\\n\",\n    \"  - d'une référence à une boîte sur laquelle l'aligner horizontalement ou verticalement (respectivement) ;\\n\",\n    \"  - d'un pourcentage de la largeur ou de la hauteur (respectivement) du MCD.\\n\",\n    \"- En l'absence de coordonnées, la contrainte est placée au barycentre des boîtes qu'elle relie.\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"Voici un exemple concret, adapté de la Fig. 7.37 de _Merise, deuxième génération_ (Dominique Nanci et Bernard Espinasse, 4e éd., 2001) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 39,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"417\\\" height=\\\"276\\\" viewBox=\\\"0 0 417 276\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"417\\\" height=\\\"276\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint I_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<polygon points=\\\"320 151.28 310.25 160.49 312.34 153.59 306.78 149.0\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"263.5\\\" y2=\\\"168.33\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"263.5\\\" y2=\\\"168.33\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"263.5\\\" y2=\\\"168.33\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"229\\\" x2=\\\"263.5\\\" y2=\\\"168.33\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"138\\\" x2=\\\"263.5\\\" y2=\\\"168.33\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"263.5\\\" cy=\\\"168.33\\\" r=\\\"12\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"261\\\" y=\\\"172.53\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">I</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association LOUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M231 109 a14 14 90 0 1 14 14 V137 h-70 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M245 137 v16 a14 14 90 0 1 -14 14 H189 a14 14 90 0 1 -14 -14 V137 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"175\\\" y=\\\"109\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"175\\\" y1=\\\"137\\\" x2=\\\"245\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"182\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Louer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109.84\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"68.99\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association STOCKER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M394 109 a14 14 90 0 1 14 14 V137 h-88 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M408 137 v16 a14 14 90 0 1 -14 14 H334 a14 14 90 0 1 -14 -14 V137 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"320\\\" y=\\\"109\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"320\\\" y1=\\\"137\\\" x2=\\\"408\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stocker</text>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M248 200 a14 14 90 0 1 14 14 V228 h-104 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M262 228 v16 a14 14 90 0 1 -14 14 H172 a14 14 90 0 1 -14 -14 V228 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"158\\\" y=\\\"200\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"158\\\" y1=\\\"228\\\" x2=\\\"262\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"165\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Composer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPOT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"39\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"39\\\" x2=\\\"407\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"337\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Dépôt</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num dépôt</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"59\\\" x2=\\\"398\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">surface</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"120\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"129\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"121\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ARTICLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"221\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"221\\\" x2=\\\"407\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"330\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Article</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. article</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"241\\\" x2=\\\"393\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Article** (<u>réf. article</u>, prix)\\n\",\n       \"- **Commande** (<u>num. commande</u>, date, _#num dépôt_)\\n\",\n       \"- **Composer** (<u>_#num. commande_</u>, <u>_#réf. article_</u>)\\n\",\n       \"- **Dépôt** (<u>num dépôt</u>, surface)\\n\",\n       \"- **Stocker** (<u>_#num dépôt_</u>, <u>_#réf. article_</u>, quantité)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \":::\\n\",\n    \"Dépôt: num dépôt, surface\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Louer, 11 Commande, 0N Dépôt\\n\",\n    \":\\n\",\n    \"Stocker, 1N Dépôt, 1N Article: quantité\\n\",\n    \"\\n\",\n    \"Commande: num. commande, date\\n\",\n    \"Composer, 1N Commande, 0N Article\\n\",\n    \":\\n\",\n    \"Article: réf. article, prix\\n\",\n    \"\\n\",\n    \"(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez que pour Mocodo, ces contraintes sont purement décoratives : le passage au niveau relationnel ou physique n'en tient pas compte.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Agrégat (ou pseudo-entité)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans le MCD ci-dessous, le petit rond et l'enveloppe pointillée indiquent qu'une réservation d'une chambre donnée à une date donnée ne peut être faite que par un seul client :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 40,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"384\\\" height=\\\"197\\\" viewBox=\\\"0 0 384 197\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"384\\\" height=\\\"197\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"167\\\" cy=\\\"113\\\" r=\\\"6\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1\\\" fill=\\\"#c0d4ff55\\\"/>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"149\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L364 13 a7 7 0 0 1 7 7 L371 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.3\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L364 13 a7 7 0 0 1 7 7 L371 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M203 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M217 55 v16 a14 14 90 0 1 -14 14 H131 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"117\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"117\\\" y1=\\\"55\\\" x2=\\\"217\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réserver</text>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"177\\\" y=\\\"106\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"227\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"88\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"56\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"56\\\" x2=\\\"78\\\" y2=\\\"56\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"47.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"76\\\" x2=\\\"57\\\" y2=\\\"76\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"48\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"256\\\" y1=\\\"48\\\" x2=\\\"366\\\" y2=\\\"48\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"39.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"65.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"264\\\" y1=\\\"68\\\" x2=\\\"358\\\" y2=\\\"68\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"82.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"149\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"128\\\" y1=\\\"149\\\" x2=\\\"206\\\" y2=\\\"149\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"137\\\" y=\\\"140.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"136\\\" y=\\\"166.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Id. client</text>\\n\",\n       \"\\t<line x1=\\\"136\\\" y1=\\\"169\\\" x2=\\\"190\\\" y2=\\\"169\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --colors ocean # changement de palette pour faire apparaître un fond semi-transparent \\n\",\n    \"Date: Date\\n\",\n    \"Réserver, /1N Client, 1N Chambre, 0N Date: Durée\\n\",\n    \"Chambre: Num. chambre, Prix\\n\",\n    \"\\n\",\n    \"Client: Id. client\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La syntaxe est minimale : une simple barre oblique `/` avant la cardinalité de l'entité-cible.\\n\",\n    \"\\n\",\n    \"S'il y a au maximum deux entités à agréger, et que l'angle formé par l'association et les entités est plat ou rectangle, une enveloppe de points matérialise la pseudo-entité.\\n\",\n    \"\\n\",\n    \"Sinon, pour des raisons de simplicité du code et de clarté du diagramme, l'enveloppe n'est pas affichée. Cependant, le petit rond subsiste et le reste des traitements est bien sûr inchangé.\\n\",\n    \"\\n\",\n    \"**Remarques.**\\n\",\n    \"- La représentation traditionnelle demanderait à insérer une association DF entre CLIENT et RÉSERVER. Mais permettre l'association d'une entité et d'une association demanderait à apporter au code de Mocodo des changements conséquents, pour un bénéfice qui ne nous saute pas forcément aux yeux.\\n\",\n    \"- Les agrégats sur association binaire sont soit inutiles (sur une DF), soit impossibles (sur une non-DF, ils reviennent à permettre à une même occurrence d'entité de renforcer plusieurs occurrences d'une entité faible sans discriminateur). Mocodo les interdit dans les deux cas.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### CIF à unicité complète\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La notion d'agrégation n'a pas très bonne presse dans les milieux autorisés. Ceux-ci lui préfèrent généralement celle (équivalente) de contrainte d'intégrité fonctionnelle à unicité complète. Pour rentrer dans leurs bonnes grâces (et désactiver du même coup la visualisation de l'enveloppe et du petit rond), il suffit d'expliciter la contrainte correspondante dans le MCD précédent. Mocodo peut le faire pour vous :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 41,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"384\\\" height=\\\"197\\\" viewBox=\\\"0 0 384 197\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"384\\\" height=\\\"197\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"56\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"128 149 116 155 120 149 116 143\\\" fill=\\\"#85956b\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"149\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"56\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"48\\\" cy=\\\"149\\\" r=\\\"13\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"39.5\\\" y=\\\"153.2\\\" fill=\\\"#85956b\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"149\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M203 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M217 55 v16 a14 14 90 0 1 -14 14 H131 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"117\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"117\\\" y1=\\\"55\\\" x2=\\\"217\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réserver</text>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"177\\\" y=\\\"106\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"227\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"88\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"56\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"56\\\" x2=\\\"78\\\" y2=\\\"56\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"47.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"76\\\" x2=\\\"57\\\" y2=\\\"76\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"48\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"256\\\" y1=\\\"48\\\" x2=\\\"366\\\" y2=\\\"48\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"39.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"65.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"264\\\" y1=\\\"68\\\" x2=\\\"358\\\" y2=\\\"68\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"82.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"149\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"128\\\" y1=\\\"149\\\" x2=\\\"206\\\" y2=\\\"149\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"137\\\" y=\\\"140.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"136\\\" y=\\\"166.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Id. client</text>\\n\",\n       \"\\t<line x1=\\\"136\\\" y1=\\\"169\\\" x2=\\\"190\\\" y2=\\\"169\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --seed=12 --colors ocean\\n\",\n      \"Date: Date\\n\",\n      \"Réserver, /1N Client, 1N Chambre, 0N Date: Durée\\n\",\n      \"Chambre: Num. chambre, Prix\\n\",\n      \"\\n\",\n      \"-INVISIBLE_1, XX Client, XX Client\\n\",\n      \"Client: Id. client\\n\",\n      \":\\n\",\n      \"\\n\",\n      \"(CIF) ..Réserver, ->Client, --Chambre, --Date: INVISIBLE_1, INVISIBLE_1\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t create:cifs arrange --seed=12 --colors ocean\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Remarquez que la visibilité de la CIF est assurée par le positionnement de celle-ci sur une boîte invisible introduite à cet effet : si vous rectifiez ce positionnement, vous pouvez bien sûr supprimer cette boîte.\\n\",\n    \"\\n\",\n    \"[Vous avez également le droit](https://www.developpez.net/forums/d2099422/general-developpement/alm/outils/looping/cif-depliees-compactees/) d'alléger la visualisation des CIFs _complètes_ en transformant les traits pleins `\\\"--\\\"` des entités émettrices en traits invisibles `\\\"\\\"`. Là encore, Mocodo peut le faire pour vous :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 42,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"384\\\" height=\\\"197\\\" viewBox=\\\"0 0 384 197\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"384\\\" height=\\\"197\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"56\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"128 149 116 155 120 149 116 143\\\" fill=\\\"#85956b\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"149\\\" x2=\\\"48\\\" y2=\\\"149\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"48\\\" cy=\\\"149\\\" r=\\\"13\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"39.5\\\" y=\\\"153.2\\\" fill=\\\"#85956b\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"167\\\" y1=\\\"149\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"167\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M203 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M217 55 v16 a14 14 90 0 1 -14 14 H131 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"117\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"117\\\" y1=\\\"55\\\" x2=\\\"217\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réserver</text>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"177\\\" y=\\\"106\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"227\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"88\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"56\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"56\\\" x2=\\\"78\\\" y2=\\\"56\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"47.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"76\\\" x2=\\\"57\\\" y2=\\\"76\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"48\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"256\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"256\\\" y1=\\\"48\\\" x2=\\\"366\\\" y2=\\\"48\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"39.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"65.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"264\\\" y1=\\\"68\\\" x2=\\\"358\\\" y2=\\\"68\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"82.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"149\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"128\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"128\\\" y1=\\\"149\\\" x2=\\\"206\\\" y2=\\\"149\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"137\\\" y=\\\"140.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"136\\\" y=\\\"166.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Id. client</text>\\n\",\n       \"\\t<line x1=\\\"136\\\" y1=\\\"169\\\" x2=\\\"190\\\" y2=\\\"169\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --seed=12 --colors ocean\\n\",\n      \"Date: Date\\n\",\n      \"Réserver, /1N Client, 1N Chambre, 0N Date: Durée\\n\",\n      \"Chambre: Num. chambre, Prix\\n\",\n      \"\\n\",\n      \"-INVISIBLE_1, XX Client, XX Client\\n\",\n      \"Client: Id. client\\n\",\n      \":\\n\",\n      \"\\n\",\n      \"(CIF) ..Réserver, ->Client, Chambre, Date: INVISIBLE_1, INVISIBLE_1\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t create:cifs=light arrange --seed=12 --colors ocean\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Limitation.** Au niveau fonctionnel, c'est toujours la barre oblique qui conditionne le traitement des CIF. Par conséquent, les CIF à unicité _incomplète_ ne sont prises en charge qu'au niveau visuel.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Identifiants explicites dans les associations\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo 4.1.1 relaxe par défaut (sauf dans la version en ligne) la contrainte de Merise restreignant aux entités la présence d'identifiants. Si vous l'osez, vous pouvez donc obtenir le même schéma relationnel avec le MCD « allégé » suivant :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 43,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"364\\\" height=\\\"94\\\" viewBox=\\\"0 0 364 94\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"364\\\" height=\\\"94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"47\\\" x2=\\\"166\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"300\\\" y1=\\\"47\\\" x2=\\\"166\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M202 10 a14 14 90 0 1 14 14 V38 h-100 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M216 38 v32 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V38 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"10\\\" width=\\\"100\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"38\\\" x2=\\\"216\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réserver</text>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t\\t<line x1=\\\"123\\\" y1=\\\"59\\\" x2=\\\"154\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"221\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"17\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"47\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"17\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"47\\\" x2=\\\"87\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Id. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"67\\\" x2=\\\"71\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"245\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"245\\\" y=\\\"39\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"245\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"245\\\" y1=\\\"39\\\" x2=\\\"355\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"253\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"253\\\" y1=\\\"59\\\" x2=\\\"347\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"253\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Chambre** (<u>Num. chambre</u>, Prix)\\n\",\n       \"- **Réserver** (<u>Id. client</u>, <u>_#Num. chambre_</u>, <u>Date</u>, Durée)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Client: Id. client\\n\",\n    \"Réserver, 1N Client, 0N Chambre: _Date, Durée\\n\",\n    \"Chambre: Num. chambre, Prix\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'introduction de cette possibilité, surtout destinée à simplifier le plongement des MCD touffus, est discutée [ici](#Par-suppression-de-ces-mêmes-entités).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Conversion d'un MCD\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Passage au relationnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il se fait en deux étapes:\\n\",\n    \"- la création d'une représentation **interne** complète du MLD ;\\n\",\n    \"- la traduction de celle-ci en une représentation **externe** dans le ou les formats de sortie souhaités.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour construire la **représentation interne**, l'algorithme de base réalise la séquence d'opérations suivante :\\n\",\n    \"\\n\",\n    \"1. Pour chaque entité, une relation (table) de même nom et de mêmes attributs est créée. Le ou les identifiants de l'entité constituent la clé primaire de la relation.\\n\",\n    \"2. Toute relation issue d'une entité faible est renforcée, c'est-à-dire que la clé primaire de l'entité qu'elle détermine fonctionnellement vient s'adjoindre à sa clé primaire, au besoin de façon récursive.\\n\",\n    \"3. Les associations sont traitées ainsi :\\n\",\n    \"  1. si toutes les pattes de l'association portent la cardinalité maximale N, une relation de même nom et de mêmes attributs est créée. Sa clé primaire est constituée de l'ensemble des clés primaires des relations issues des entités mises en jeu ;\\n\",\n    \"  2. dans le cas contraire, c'est-à-dire si l'une des pattes de l'association porte la cardinalité (1,1), ou à défaut (0,1), l'entité distinguée se voit adjoindre :\\n\",\n    \"    1. en tant que clés étrangères, l'ensemble des clés primaires des autres entités mises en jeu;\\n\",\n    \"    2. en tant que simples attributs, l'ensemble des attributs de l'association.\\n\",\n    \"\\n\",\n    \"**Remarque.** Un couple de cardinalités non standard, c'est-à-dire distinct de (0,1), (1,1), (0,N) et (1,N), est traité comme (0,1) si son deuxième symbole est un 1, et comme (0,N) sinon. Cela couvre en particulier les cas (\\\\*, 1), (\\\\*,N), (?,?) et (X,X).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour construire la **représentation externe**, Mocodo formate la représentation interne à l'aide d'un gabarit. Près d'une centaine de gabarits sont fournis, qui permettent de produire quatre grandes catégories de résultats :\\n\",\n    \"1. le schéma relationnel dans toutes les combinaisons de formats (HTML, Markdown, texte brut, $\\\\LaTeX$) et d'options (avec ou sans explications, avec ou sans _boilerplate_, avec ou sans visualisation des contraintes d'unicité et d'optionalité) ;\\n\",\n    \"2. le diagramme relationnel au format Mocodo, avec ou sans visualisation des contraintes d'unicité et d'optionalité, ou dans des formats externes, comme DBML ou D2.\\n\",\n    \"3. le DDL en SQL ANSI et dans les principaux dialectes (Microsoft SQL Server, MySQL, Oracle DB, PostgreSQL, SQLite), avec ou sans _boilerplate_ de création de la base ;\\n\",\n    \"4. le graphe des dépendances.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Niveau logique\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Schéma relationnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La transformation `-t mld` opère la conversion d'un MCD (modèle conceptuel de données) en un MLD (modèle logique de données), autrement appelé **schéma relationnel** :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 44,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Client** (<u>Réf. client</u>, Nom, Prénom, Adresse)\\n\",\n       \"- **Commande** (<u>Num. commande</u>, Date, Montant, _#Réf. client_)\\n\",\n       \"- **Inclure** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\\n\",\n       \"- **Produit** (<u>Réf. produit</u>, Libellé, Prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t mld\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Sous Jupyter Notebook, comme pour toutes les opérations de conversion, le tracé du MCD est omis par défaut. Dans le cas très fréquent où l'on a besoin de visualiser simultanément le MCD et le MLD, on peut invoquer l'option `-t` sans arguments (ou encore `--mld`) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 45,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"594\\\" height=\\\"128\\\" viewBox=\\\"0 0 594 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"594\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M448 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M462 63 v16 a14 14 90 0 1 -14 14 H390 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"376\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"376\\\" y1=\\\"63\\\" x2=\\\"462\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"467\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"491\\\" y1=\\\"47\\\" x2=\\\"585\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"499\\\" y1=\\\"67\\\" x2=\\\"574\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Client** (<u>Réf. client</u>, Nom, Prénom, Adresse)\\n\",\n       \"- **Commande** (<u>Num. commande</u>, Date, Montant, _#Réf. client_)\\n\",\n       \"- **Inclure** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\\n\",\n       \"- **Produit** (<u>Réf. produit</u>, Libellé, Prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Diagramme relationnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La plupart des SGBD offrent une représentation hybride (graphique / texte) de la base sous la forme de tables liées par des flèches. Nous l'appelons **diagramme relationnel**. Sous Mocodo :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 46,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2ODAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjgwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY4MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjZmVmZWVjIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gY2xpZW50PC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBJTkNMVVJFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzU2IiB5PSI0NyIgd2lkdGg9IjEzNCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjE3IiB3aWR0aD0iMTM0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM1NiIgeTE9IjQ3IiB4Mj0iNDkwIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjM4NyIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbmNsdXJlPC90ZXh0PgoJPHRleHQgeD0iMzY0IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jTnVtLiBjb21tYW5kZTwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI2NyIgeDI9IjQ4MSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI4MS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jUsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQ0OCIgeTI9Ijg0IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjU0OCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1NDgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTQ4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjU0OCIgeTE9IjQ3IiB4Mj0iNjQyIiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU1OSIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU1NiIgeTE9IjY3IiB4Mj0iNjMxIiB5Mj0iNjciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NTYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTU2IiB5PSI5OCIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDkwIDc4LjUgQzUxOSA3MCA1MDkuMzMgNjEuNSA1NDggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1NDggNjEuNSA1MzYgNjcuNSA1NDAgNjEuNSA1MzYgNTUuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ5MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgo8L3N2Zz4=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp --colors mondrian -t diagram\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le nom du fichier généré avant rendu graphique se termine par `_mld.mcd`. L'extension `.mcd` signifie que Mocodo peut le prendre comme texte-source (bien que ce ne soit pas un schéma conceptuel). Examinons son contenu :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 47,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style>pre { line-height: 125%; }\\n\",\n       \"td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \".output_html .hll { background-color: #ffffcc }\\n\",\n       \".output_html { background: #f8f8f8; }\\n\",\n       \".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\\n\",\n       \".output_html .err { border: 1px solid #FF0000 } /* Error */\\n\",\n       \".output_html .k { color: #008000; font-weight: bold } /* Keyword */\\n\",\n       \".output_html .o { color: #666666 } /* Operator */\\n\",\n       \".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\\n\",\n       \".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\\n\",\n       \".output_html .cp { color: #9C6500 } /* Comment.Preproc */\\n\",\n       \".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\\n\",\n       \".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\\n\",\n       \".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\\n\",\n       \".output_html .gd { color: #A00000 } /* Generic.Deleted */\\n\",\n       \".output_html .ge { font-style: italic } /* Generic.Emph */\\n\",\n       \".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\\n\",\n       \".output_html .gr { color: #E40000 } /* Generic.Error */\\n\",\n       \".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\\n\",\n       \".output_html .gi { color: #008400 } /* Generic.Inserted */\\n\",\n       \".output_html .go { color: #717171 } /* Generic.Output */\\n\",\n       \".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\\n\",\n       \".output_html .gs { font-weight: bold } /* Generic.Strong */\\n\",\n       \".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\\n\",\n       \".output_html .gt { color: #0044DD } /* Generic.Traceback */\\n\",\n       \".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\\n\",\n       \".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\\n\",\n       \".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\\n\",\n       \".output_html .kp { color: #008000 } /* Keyword.Pseudo */\\n\",\n       \".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\\n\",\n       \".output_html .kt { color: #B00040 } /* Keyword.Type */\\n\",\n       \".output_html .m { color: #666666 } /* Literal.Number */\\n\",\n       \".output_html .s { color: #BA2121 } /* Literal.String */\\n\",\n       \".output_html .na { color: #687822 } /* Name.Attribute */\\n\",\n       \".output_html .nb { color: #008000 } /* Name.Builtin */\\n\",\n       \".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\\n\",\n       \".output_html .no { color: #880000 } /* Name.Constant */\\n\",\n       \".output_html .nd { color: #AA22FF } /* Name.Decorator */\\n\",\n       \".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\\n\",\n       \".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\\n\",\n       \".output_html .nf { color: #0000FF } /* Name.Function */\\n\",\n       \".output_html .nl { color: #767600 } /* Name.Label */\\n\",\n       \".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\\n\",\n       \".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\\n\",\n       \".output_html .nv { color: #19177C } /* Name.Variable */\\n\",\n       \".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\\n\",\n       \".output_html .w { color: #bbbbbb } /* Text.Whitespace */\\n\",\n       \".output_html .mb { color: #666666 } /* Literal.Number.Bin */\\n\",\n       \".output_html .mf { color: #666666 } /* Literal.Number.Float */\\n\",\n       \".output_html .mh { color: #666666 } /* Literal.Number.Hex */\\n\",\n       \".output_html .mi { color: #666666 } /* Literal.Number.Integer */\\n\",\n       \".output_html .mo { color: #666666 } /* Literal.Number.Oct */\\n\",\n       \".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\\n\",\n       \".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\\n\",\n       \".output_html .sc { color: #BA2121 } /* Literal.String.Char */\\n\",\n       \".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\\n\",\n       \".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\\n\",\n       \".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\\n\",\n       \".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\\n\",\n       \".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\\n\",\n       \".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\\n\",\n       \".output_html .sx { color: #008000 } /* Literal.String.Other */\\n\",\n       \".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\\n\",\n       \".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\\n\",\n       \".output_html .ss { color: #19177C } /* Literal.String.Symbol */\\n\",\n       \".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\\n\",\n       \".output_html .fm { color: #0000FF } /* Name.Function.Magic */\\n\",\n       \".output_html .vc { color: #19177C } /* Name.Variable.Class */\\n\",\n       \".output_html .vg { color: #19177C } /* Name.Variable.Global */\\n\",\n       \".output_html .vi { color: #19177C } /* Name.Variable.Instance */\\n\",\n       \".output_html .vm { color: #19177C } /* Name.Variable.Magic */\\n\",\n       \".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\\\"highlight\\\"><pre><span></span>%%mocodo\\n\",\n       \":\\n\",\n       \"Client: Réf. client, Nom, Prénom, Adresse\\n\",\n       \":\\n\",\n       \"Commande: Num. commande, Date, Montant, #Réf. client &gt; Client &gt; Réf. client\\n\",\n       \":\\n\",\n       \"Inclure: #Num. commande &gt; Commande &gt; Num. commande, _#Réf. produit &gt; Produit &gt; Réf. produit, Quantité\\n\",\n       \":\\n\",\n       \"Produit: Réf. produit, Libellé, Prix unitaire\\n\",\n       \":\\n\",\n       \"</pre></div>\\n\"\n      ],\n      \"text/latex\": [\n       \"\\\\begin{Verbatim}[commandchars=\\\\\\\\\\\\{\\\\}]\\n\",\n       \"\\\\PYZpc{}\\\\PYZpc{}mocodo\\n\",\n       \":\\n\",\n       \"Client: Réf. client, Nom, Prénom, Adresse\\n\",\n       \":\\n\",\n       \"Commande: Num. commande, Date, Montant, \\\\PYZsh{}Réf. client \\\\PYZgt{} Client \\\\PYZgt{} Réf. client\\n\",\n       \":\\n\",\n       \"Inclure: \\\\PYZsh{}Num. commande \\\\PYZgt{} Commande \\\\PYZgt{} Num. commande, \\\\PYZus{}\\\\PYZsh{}Réf. produit \\\\PYZgt{} Produit \\\\PYZgt{} Réf. produit, Quantité\\n\",\n       \":\\n\",\n       \"Produit: Réf. produit, Libellé, Prix unitaire\\n\",\n       \":\\n\",\n       \"\\\\end{Verbatim}\\n\"\n      ],\n      \"text/plain\": [\n       \"%%mocodo\\n\",\n       \":\\n\",\n       \"Client: Réf. client, Nom, Prénom, Adresse\\n\",\n       \":\\n\",\n       \"Commande: Num. commande, Date, Montant, #Réf. client > Client > Réf. client\\n\",\n       \":\\n\",\n       \"Inclure: #Num. commande > Commande > Num. commande, _#Réf. produit > Produit > Réf. produit, Quantité\\n\",\n       \":\\n\",\n       \"Produit: Réf. produit, Libellé, Prix unitaire\\n\",\n       \":\"\n      ]\n     },\n     \"execution_count\": 47,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Code(\\\"ccp_mld.mcd\\\", language=\\\"text\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La syntaxe d'un MLD est effectivement la même que celle d'un MCD, à ceci près que les associations sont remplacées par des liens allant de l'attribut `a1` de l'entité `E1` à l'attribut `a2` de l'entité `E2`, et notés : `E1: ... a1 > E2 > a2`.\\n\",\n    \"\\n\",\n    \"Les relations sont placées dans le même ordre que les boîtes du MCD d'origine. Vous devrez quelquefois les réarranger (automatiquement ou manuellement) pour obtenir un résultat plus esthétique. Notez que des boîtes invisibles ont été automatiquement insérées une colonne sur deux afin de laisser de la place aux flèches.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Limitation.** Les clés étrangères composites sont actuellement représentées comme si elles étaient séparées (autant de flèches que de parties).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveautés de la version 4.0.**\\n\",\n    \"- Ce qui se notait `E1: ... a1->E2->a2` se note maintenant `E1: ... a1 > E2 > a2`.\\n\",\n    \"- Sous Jupyter Notebook, un seule étape suffit pour visualiser le diagramme relationnel.\\n\",\n    \"- Le nom du fichier intermédiaire se termine par `_mld.mcd` au lieu de `.mld`. L'ancienne extension est abandonnée.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Niveau physique : DDL\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### SQL\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La principale raison de vivre d'un MCD est de se métamorphoser _in fine_ en une chatoyante base de données relationnelles. Cela se fait au moyen d'un sous-ensemble du langage SQL appelé DDL (_Data Definition Language_). Sous Mocodo :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 48,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE Client (\\n\",\n       \"  PRIMARY KEY (Ref_client),\\n\",\n       \"  Ref_client VARCHAR(8) NOT NULL,\\n\",\n       \"  Nom        VARCHAR(255),\\n\",\n       \"  Prenom     VARCHAR(255),\\n\",\n       \"  Adresse    VARCHAR(255)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Commande (\\n\",\n       \"  PRIMARY KEY (Num_commande),\\n\",\n       \"  Num_commande VARCHAR(8) NOT NULL,\\n\",\n       \"  Date         DATE,\\n\",\n       \"  Montant      DECIMAL(10,2),\\n\",\n       \"  Ref_client   VARCHAR(8) NOT NULL\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Inclure (\\n\",\n       \"  PRIMARY KEY (Num_commande, Ref_produit),\\n\",\n       \"  Num_commande VARCHAR(8) NOT NULL,\\n\",\n       \"  Ref_produit  VARCHAR(8) NOT NULL,\\n\",\n       \"  Quantite     INTEGER\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE Produit (\\n\",\n       \"  PRIMARY KEY (Ref_produit),\\n\",\n       \"  Ref_produit   VARCHAR(8) NOT NULL,\\n\",\n       \"  Libelle       VARCHAR(50),\\n\",\n       \"  Prix_unitaire DECIMAL(10,2)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"ALTER TABLE Commande ADD FOREIGN KEY (Ref_client) REFERENCES Client (Ref_client);\\n\",\n       \"\\n\",\n       \"ALTER TABLE Inclure ADD FOREIGN KEY (Ref_produit) REFERENCES Produit (Ref_produit);\\n\",\n       \"ALTER TABLE Inclure ADD FOREIGN KEY (Num_commande) REFERENCES Commande (Num_commande);\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t sql\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez le `NOT NULL` des clés primaires. Il s'agit d'une redondance, mais aussi d'une bonne pratique. Non seulement parce qu'_explicit is better than implicit_ : elle peut se révéler utile, par exemple pour désactiver les contraintes de clé primaire pendant une maintenance tout en continuant à interdire le remplissage avec des `NULL`. Si cela vous gêne, nous montrons en annexe comment l'éliminer.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Principales nouveautés de la version 4.0.**\\n\",\n    \"- Génération automatique des contraintes `UNIQUE`, `NOT NULL` et `NULL` appropriées.\\n\",\n    \"- Les libellés sont convertis en ASCII, et toute suite de caractères qui ne sont ni des lettres, ni des chiffres, ni des tirets bas sont remplacés par un unique tiret bas. Cela simplifie la référence aux tables et aux champs, et évite de noyer le DDL sous un essaim de délimiteurs (qui plus est spécifiques à chaque dialecte). Ainsi, « Réf. client » se trouvera transformé en `Ref_client`.\\n\",\n    \"- Vos choix de casse (minuscules, MAJUSCULES, _snake_case_, _camelCase_, _PascalCase_, etc.) sont respectés.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Inférence de type\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Avec l'option de réécriture `-t create:types` Mocodo essaiera d'inférer des libellés des attributs tout type manquant. La langue définie avec l'option `--language` est prioritaire, mais l'anglais prend la relève en cas d'échec.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 49,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --select rw\\n\",\n      \"Customer: Customer ID [VARCHAR(8)], Last Name [VARCHAR(255)], First Name [VARCHAR(255)], Address [VARCHAR(30)]\\n\",\n      \"Make Order, 0N Customer, 11 Order\\n\",\n      \"Order: Order Number [VARCHAR(8)], Date [DATE], Amount [DECIMAL(10,2)]\\n\",\n      \"INCLUDE, 1N Order, 0N Product: Quantity [INTEGER]\\n\",\n      \"Product: Product ID [VARCHAR(8)], Description [TEXT], Unit Price [DECIMAL(10,2)]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t create:types --select rw\\n\",\n    \"Customer: Customer ID, Last Name, First Name, Address\\n\",\n    \"Make Order, 0N Customer, 11 Order\\n\",\n    \"Order: Order Number, Date, Amount\\n\",\n    \"INCLUDE, 1N Order, 0N Product: Quantity\\n\",\n    \"Product: Product ID, Description, Unit Price\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il va de soi que les types inférés devront être systématiquement contrôlés, et parfois corrigés ou complétés. Une discussion sur StackOverflow, [Common MySQL fields and their appropriate data types](https://stackoverflow.com/questions/354763/common-mysql-fields-and-their-appropriate-data-types), a servi de point de départ. La liste des types utilisée est [celle de Wikipedia](https://en.wikibooks.org/wiki/Structured_Query_Language/Data_Types). Consultez les correspondances spécifiées dans `mocodo/resources/default_datatypes_fr.tsv`, etc. pour plus de détails, et n'hésitez pas à [ouvrir le débat](https://github.com/laowantong/mocodo/issues/new) si vous avez des corrections ou des suggestions.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Si vous préférez tout typer à la main, vous pouvez au moins créer les « cases » à remplir :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 50,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --select rw\\n\",\n      \"Customer: Customer ID [], Last Name [], First Name [], Address []\\n\",\n      \"Make Order, 0N Customer, 11 Order\\n\",\n      \"Order: Order Number [], Date [], Amount []\\n\",\n      \"INCLUDE, 1N Order, 0N Product: Quantity []\\n\",\n      \"Product: Product ID [], Description [], Unit Price []\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t create:types=[] --select rw\\n\",\n    \"Customer: Customer ID, Last Name, First Name, Address\\n\",\n    \"Make Order, 0N Customer, 11 Order\\n\",\n    \"Order: Order Number, Date, Amount\\n\",\n    \"INCLUDE, 1N Order, 0N Product: Quantity\\n\",\n    \"Product: Product ID, Description, Unit Price\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Dialectes de SQL\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'argument `sql` peut être remplacé par un nom de dialecte parmi `mysql`, `oracle`, `postgresql`, `sqlite` et (nouveauté de la version 4) `mssql`. Quelques transformations seront alors appliquées au code-source généré. Du fait de l'uniformisation de la syntaxe apportée par la version 4, elles sont assez minimes.\\n\",\n    \"\\n\",\n    \"Notez les points suivants :\\n\",\n    \"- Mocodo ne touche pas aux types spécifiés par l'utilisateur. Une traduction inter-dialectes automatique est envisageable dans le futur, mais c'est un problème qui n'a en réalité aucune solution satisfaisante.\\n\",\n    \"- Mocodo protège les noms de tables ou de colonnes qui se trouveraient faire partie des mots réservés par le dialecte-cible. Par exemple, ci-dessous, les noms `USER` et `MEMBER` sont réservés en MySQL. Les listes viennent du site [modern-sql.com](https://modern-sql.com) de Markus Winand, et plus précisément de la page https://modern-sql.com/reserved-words-empirical-list.\\n\",\n    \"- Avec la sous-sous-option `b`, un _boilerplate_ de création de la base est ajouté en préambule.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 51,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl_mysql.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE DATABASE IF NOT EXISTS `MCD`\\n\",\n       \"  CHARACTER SET utf8mb4\\n\",\n       \"  COLLATE utf8mb4_general_ci\\n\",\n       \";\\n\",\n       \"USE `MCD`;\\n\",\n       \"\\n\",\n       \"CREATE TABLE `USER` (\\n\",\n       \"  PRIMARY KEY (username),\\n\",\n       \"  username VARCHAR(42) NOT NULL,\\n\",\n       \"  mail     VARCHAR(42),\\n\",\n       \"  `member` VARCHAR(42)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mysql:b\\n\",\n    \"USER: username, mail, member\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Notes sur les règles de passage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Génération de contraintes d'optionalité et d'unicité\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Avec la sous-sous-option `c`, Mocodo peut faire apparaître dès le niveau logique certaines contraintes du niveau physique. Les notations sont les suivantes :\\n\",\n    \"\\n\",\n    \"| Contrainte | niveau logique | niveau physique |\\n\",\n    \"|---|:--|:--|\\n\",\n    \"| non-optionalité | attribut! | `NOT NULL` |\\n\",\n    \"| optionalité | attribut? | `NULL` |\\n\",\n    \"| unicité | attribut $^{u1\\\\ u2...}$ | `UNIQUE` |\\n\",\n    \"\\n\",\n    \"Par exemple, ci-dessous, la clé étrangère _#Réf_client_ est maintenant marquée comme **non optionnelle** :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 52,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Client** (<u>Réf. client</u>, Nom, Prénom, Adresse)\\n\",\n       \"- **Commande** (<u>Num. commande</u>, Date, Montant, _#Réf. client!_)\\n\",\n       \"- **Inclure** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\\n\",\n       \"- **Produit** (<u>Réf. produit</u>, Libellé, Prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t mld:c\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La clé étrangère _#id entreprise_ est marquée comme **optionnelle** :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 53,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"408\\\" height=\\\"128\\\" viewBox=\\\"0 0 408 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"408\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ENVOYER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"68\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"338\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M234 35 a14 14 90 0 1 14 14 V63 h-92 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M248 63 v16 a14 14 90 0 1 -14 14 H170 a14 14 90 0 1 -14 -14 V63 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"35\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"63\\\" x2=\\\"248\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"164\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Envoyer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTREPRISE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"127\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entreprise</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. entreprise</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"101\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">activité</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PARTICIPANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"47\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"277\\\" y1=\\\"47\\\" x2=\\\"399\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Participant</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. inscrit</text>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"67\\\" x2=\\\"343\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Entreprise** (<u>id. entreprise</u>, raison, activité, adresse)\\n\",\n       \"- **Participant** (<u>id. inscrit</u>, nom, adresse, _#id. entreprise?_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"Entreprise: id. entreprise, raison, activité, adresse\\n\",\n    \"Envoyer, 0N Entreprise, 01 Participant\\n\",\n    \"Participant: id. inscrit, nom, adresse\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La clé étrangère _#id employé_ est marquée comme **unique** :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 54,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"426\\\" height=\\\"94\\\" viewBox=\\\"0 0 426 94\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"426\\\" height=\\\"94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"340\\\" y1=\\\"47\\\" x2=\\\"188\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"61\\\" y1=\\\"47\\\" x2=\\\"188\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M220 18 a14 14 90 0 1 14 14 V46 h-92 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M234 46 v16 a14 14 90 0 1 -14 14 H156 a14 14 90 0 1 -14 -14 V46 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"142\\\" y=\\\"18\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"142\\\" y1=\\\"46\\\" x2=\\\"234\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"150\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"240\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"113\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. employé</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"89\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"154\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"39\\\" width=\\\"154\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"154\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"263\\\" y1=\\\"39\\\" x2=\\\"417\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. département</text>\\n\",\n       \"\\t<line x1=\\\"271\\\" y1=\\\"59\\\" x2=\\\"370\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **DÉPARTEMENT** (<u>id. département</u>, nom département, _#id. employé!_ <sup>u1</sup>)\\n\",\n       \"- **EMPLOYÉ** (<u>id. employé</u>, nom employé)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"EMPLOYÉ: id. employé, nom employé\\n\",\n    \"DIRIGER, 11 DÉPARTEMENT, 01 EMPLOYÉ\\n\",\n    \"DÉPARTEMENT: id. département, nom département\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Ajout manuel de contraintes d'optionalité et d'unicité\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les contraintes `NOT NULL` ou `NULL` spécifiées dans les types peuvent également faire l'objet d'une visualisation au niveau relationnel :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 55,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Personne** (<u>id. personne</u>, nom!, prénom, nom de jeune fille?)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mld:c\\n\",\n    \"Personne: id. personne [VARCHAR(8)], nom [VARCHAR(255) NOT NULL], prénom [VARCHAR(255)], nom de jeune fille [VARCHAR(255) NULL]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour les contraintes d'unicité, qui peuvent s'appliquer à _plusieurs groupes_ d'attributs potentiellement _non disjoints_, la notation est un peu plus complexe. Voici un exemple [proposé par Fabien Duchateau](https://github.com/laowantong/mocodo/issues/79) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 56,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"122\\\" height=\\\"142\\\" viewBox=\\\"0 0 122 142\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"122\\\" height=\\\"142\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"33\\\" y=\\\"35\\\" width=\\\"80\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"24\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"33\\\" y1=\\\"35\\\" x2=\\\"33\\\" y2=\\\"133\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"124\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"35\\\" x2=\\\"113\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Réf. client</text>\\n\",\n       \"\\t<text x=\\\"14\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"38\\\" y1=\\\"56\\\" x2=\\\"107\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"16\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"16\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"107.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Adresse</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"107.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\"/>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"125.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Mail</text>\\n\",\n       \"\\t<text x=\\\"16\\\" y=\\\"125.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">2</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **CLIENT** (<u>Réf. client</u>, Nom <sup>u1</sup>, Prénom <sup>u1</sup>, Adresse, Mail <sup>u2</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c --shapes trebuchet # changement de police de caractères pour mieux distinguer les 1 des I\\n\",\n    \"CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"C'est l'occasion d'introduire quelques définitions :\\n\",\n    \"\\n\",\n    \"- On appelle **identifiant candidat** d'une entité tout sous-ensemble minimal d'attributs dont chaque occurrence est unique.\\n\",\n    \"- Parmi ces sous-ensembles, l'un est élu **identifiant** (tout court), souligné, et appelé à devenir clé primaire lors du passage au relationnel.\\n\",\n    \"- Les candidats malheureux sont appelés **identifiants alternatifs**.\\n\",\n    \"\\n\",\n    \"Ainsi, dans l'exemple précédent, l'ensemble des identifiants candidats de CLIENT est constitué de :\\n\",\n    \"\\n\",\n    \"- l'identifiant proprement dit _Réf. client_ ;\\n\",\n    \"- l'identifiant alternatif (_Nom_, _Prénom_) (dont on supposera pour les besoins de la cause qu'il assure l'unicité) ;\\n\",\n    \"- l'identifiant alternatif _Mail_.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Par défaut, dès la première déclaration d'un identifiant alternatif, Mocodo fait apparaître une gouttière à gauche des attributs de **toutes** les entités. Y sont portés :\\n\",\n    \"\\n\",\n    \"- un symbole « ID » (resp. « id ») pour l'identifiant fort (resp. faible).\\n\",\n    \"- des chiffres de 1 à 9 correspondant aux numéros des identifiants alternatifs.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La notation de Mocodo permet de faire de n'importe quels sous-ensembles d'attributs des identifiants alternatifs. Ci-dessous, le premier identifiant alternatif est le triplet (_bar_, _biz_, _quux_), le second (_biz_, _buz_, _quux_) et le troisième (_qux_, _quux_) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 57,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"102\\\" height=\\\"160\\\" viewBox=\\\"0 0 102 160\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"102\\\" height=\\\"160\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity FOO -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"51\\\" y=\\\"35\\\" width=\\\"42\\\" height=\\\"116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"42\\\" height=\\\"116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"51\\\" y1=\\\"35\\\" x2=\\\"51\\\" y2=\\\"151\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"142\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"35\\\" x2=\\\"93\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"37\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">FOO</text>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"23\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"56\\\" y1=\\\"56\\\" x2=\\\"78\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"25\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1 2</text>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"107.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">buz</text>\\n\",\n       \"\\t<text x=\\\"25\\\" y=\\\"107.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">2</text>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"125.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">qux</text>\\n\",\n       \"\\t<text x=\\\"25\\\" y=\\\"125.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">3</text>\\n\",\n       \"\\t<text x=\\\"56\\\" y=\\\"143.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">quux</text>\\n\",\n       \"\\t<text x=\\\"14\\\" y=\\\"143.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1 2 3</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **FOO** (<u>foo</u>, bar <sup>u1</sup>, biz <sup>u1 u2</sup>, buz <sup>u2</sup>, qux <sup>u3</sup>, quux <sup>u1 u2 u3</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE FOO (\\n\",\n       \"  PRIMARY KEY (foo),\\n\",\n       \"  foo  VARCHAR(42) NOT NULL,\\n\",\n       \"  bar  VARCHAR(42),\\n\",\n       \"  biz  VARCHAR(42),\\n\",\n       \"  buz  VARCHAR(42),\\n\",\n       \"  qux  VARCHAR(42),\\n\",\n       \"  quux VARCHAR(42),\\n\",\n       \"  UNIQUE (bar, biz, quux),\\n\",\n       \"  UNIQUE (biz, buz, quux),\\n\",\n       \"  UNIQUE (qux, quux)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t markdown:c sql --shapes trebuchet\\n\",\n    \"FOO: foo, 1_bar, 12_biz, 2_buz, 3_qux, 123_quux\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Examinons le cas exceptionnel où l'identifiant à souligner a un attribut commun avec un identifiant alternatif. Ce dernier devant être distinct et minimal, cela implique que l'identifiant est composite.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 58,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"364\\\" height=\\\"106\\\" viewBox=\\\"0 0 364 106\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"364\\\" height=\\\"106\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_1_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"45\\\" y=\\\"35\\\" width=\\\"62\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"36\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"45\\\" y1=\\\"35\\\" x2=\\\"45\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"88\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"35\\\" x2=\\\"107\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"32\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Entité 1</text>\\n\",\n       \"\\t<text x=\\\"50\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"14\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1 ID</text>\\n\",\n       \"\\t<line x1=\\\"50\\\" y1=\\\"56\\\" x2=\\\"72\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"50\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"50\\\" y1=\\\"74\\\" x2=\\\"72\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"50\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_2_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"139\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"163\\\" y=\\\"35\\\" width=\\\"62\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"139\\\" y=\\\"35\\\" width=\\\"24\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"163\\\" y1=\\\"35\\\" x2=\\\"163\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"139\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"88\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"139\\\" y1=\\\"35\\\" x2=\\\"225\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Entité 2</text>\\n\",\n       \"\\t<text x=\\\"168\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"144\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"168\\\" y1=\\\"56\\\" x2=\\\"190\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"168\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"\\t<text x=\\\"168\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_3_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"257\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"293\\\" y=\\\"35\\\" width=\\\"62\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"257\\\" y=\\\"35\\\" width=\\\"36\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"293\\\" y1=\\\"35\\\" x2=\\\"293\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"257\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"88\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"257\\\" y1=\\\"35\\\" x2=\\\"355\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"280\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Entité 3</text>\\n\",\n       \"\\t<text x=\\\"298\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"268\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"298\\\" y1=\\\"56\\\" x2=\\\"320\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"298\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"262\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1 ID</text>\\n\",\n       \"\\t<line x1=\\\"298\\\" y1=\\\"74\\\" x2=\\\"320\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"298\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"270\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --shapes trebuchet\\n\",\n    \"Entité 1_: 1_foo, _bar, 1_biz\\n\",\n    \"Entité 2_: foo, 1_bar, 1_biz\\n\",\n    \"Entité 3_: foo, 01_bar, 1_biz\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"- Si l'attribut commun est en tête de liste (ici, _foo_, entité 1), rien ne change, on écrit `1_foo`.\\n\",\n    \"- S'il n'est pas en tête de liste (ici, _bar_, entité 2), l'écriture `1_bar` dénote déjà l'appartenance à un identifiant alternatif. Elle ne peut dénoter simultanément l'appartenance à l'identifiant à souligner.\\n\",\n    \"- C'est pourquoi on doit donc expliciter l'appartenance à l'identifiant à souligner qui, comme on l'a vu, est numéroté `0` (entité 3).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Un sous-cas demande encore réflexion : celui où le premier attribut ne fait pas partie de l'identifiant à souligner (entité 4). Si l'on veut alors que ce premier attribut appartienne à une clé alternative, il faut expliciter le `0` (entité 5).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 59,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"222\\\" height=\\\"106\\\" viewBox=\\\"0 0 222 106\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"222\\\" height=\\\"106\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_40 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"33\\\" y=\\\"35\\\" width=\\\"62\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"35\\\" width=\\\"24\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"33\\\" y1=\\\"35\\\" x2=\\\"33\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"88\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"35\\\" x2=\\\"95\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Entité 4</text>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\"/>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"14\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"38\\\" y1=\\\"74\\\" x2=\\\"60\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_50 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"127\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"151\\\" y=\\\"35\\\" width=\\\"62\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"127\\\" y=\\\"35\\\" width=\\\"24\\\" height=\\\"62\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"151\\\" y1=\\\"35\\\" x2=\\\"151\\\" y2=\\\"97\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.25\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"127\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"88\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"127\\\" y1=\\\"35\\\" x2=\\\"213\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"144\\\" y=\\\"27.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">Entité 5</text>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">foo</text>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"53.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">bar</text>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"71.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"156\\\" y1=\\\"74\\\" x2=\\\"178\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">biz</text>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"89.6\\\" fill=\\\"#000000\\\" font-family=\\\"Trebuchet MS\\\" font-size=\\\"14\\\">1</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --shapes trebuchet\\n\",\n    \"Entité 40: _foo, _bar, biz\\n\",\n    \"Entité 50: 01_foo, _bar, 1_biz\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"En résumé, on explicite le `0`, soit pour **empêcher le soulignement du premier attribut**, soit pour **forcer le soulignement d'un attribut suivant**.\\n\",\n    \"\\n\",\n    \"Cela devrait vous rappeler quelque chose… Remplacez `0` par `_` dans la phrase précédente et vous retrouverez la règle que vous avez appris à connaître et à aimer : on explicite le `_`, soit pour empêcher le soulignement du premier attribut, soit pour forcer le soulignement d'un attribut suivant.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Gestion des entités faibles (identification relative)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans ce joli exemple dû à Idris NEUMANN, [_Initiation à la conception de bases de données relationnelles avec MERISE_](http://ineumann.developpez.com/tutoriels/merise/initiation-merise/#LIV-A), les renforcements successifs aboutissent à faire entrer l'identifiant de RUE dans celui de APPARTEMENT, alors même que ces entités sont séparées par non moins de trois associations :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 60,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"952\\\" height=\\\"94\\\" viewBox=\\\"0 0 952 94\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"952\\\" height=\\\"94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"366\\\" y1=\\\"47\\\" x2=\\\"224\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"76\\\" y1=\\\"47\\\" x2=\\\"224\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M262 18 a14 14 90 0 1 14 14 V46 h-104 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M276 46 v16 a14 14 90 0 1 -14 14 H186 a14 14 90 0 1 -14 -14 V46 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"172\\\" y=\\\"18\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"172\\\" y1=\\\"46\\\" x2=\\\"276\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"179\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Composer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"281\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"148\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"148\\\" y1=\\\"65\\\" x2=\\\"166\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association APPARTENIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"656\\\" y1=\\\"47\\\" x2=\\\"514\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"366\\\" y1=\\\"47\\\" x2=\\\"514\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M558 18 a14 14 90 0 1 14 14 V46 h-116 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M572 46 v16 a14 14 90 0 1 -14 14 H470 a14 14 90 0 1 -14 -14 V46 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"456\\\" y=\\\"18\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"456\\\" y1=\\\"46\\\" x2=\\\"572\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"463\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Appartenir</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"577\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"432\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"432\\\" y1=\\\"65\\\" x2=\\\"450\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SE_SITUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"906\\\" y1=\\\"47\\\" x2=\\\"790\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"656\\\" y1=\\\"47\\\" x2=\\\"790\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M826 18 a14 14 90 0 1 14 14 V46 h-100 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M840 46 v16 a14 14 90 0 1 -14 14 H754 a14 14 90 0 1 -14 -14 V46 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"740\\\" y=\\\"18\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"740\\\" y1=\\\"46\\\" x2=\\\"840\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"747\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Se situer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"845\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"716\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"716\\\" y1=\\\"65\\\" x2=\\\"734\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity APPARTEMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"134\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"143\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Appartement</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num appart.</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"92\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nb pièces</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"305\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"305\\\" y=\\\"39\\\" width=\\\"122\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"305\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"305\\\" y1=\\\"39\\\" x2=\\\"427\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"340\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étage</text>\\n\",\n       \"\\t<text x=\\\"313\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num étage</text>\\n\",\n       \"\\t<line x1=\\\"313\\\" y1=\\\"59\\\" x2=\\\"378\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"313\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nb appartements</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity IMMEUBLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"601\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"601\\\" y=\\\"39\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"601\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"601\\\" y1=\\\"39\\\" x2=\\\"711\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"613\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Immeuble</text>\\n\",\n       \"\\t<text x=\\\"609\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num immeuble</text>\\n\",\n       \"\\t<line x1=\\\"609\\\" y1=\\\"59\\\" x2=\\\"702\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"609\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nb étages</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RUE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"869\\\" y=\\\"9\\\" width=\\\"74\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"869\\\" y=\\\"39\\\" width=\\\"74\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"869\\\" y=\\\"9\\\" width=\\\"74\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"869\\\" y1=\\\"39\\\" x2=\\\"943\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"888\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Rue</text>\\n\",\n       \"\\t<text x=\\\"877\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">code rue</text>\\n\",\n       \"\\t<line x1=\\\"877\\\" y1=\\\"59\\\" x2=\\\"934\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"877\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom rue</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Appartement** (<u>_#code rue_</u>, <u>_#num immeuble_</u>, <u>_#num étage_</u>, <u>num appart.</u>, nb pièces)\\n\",\n       \"- **Étage** (<u>_#code rue_</u>, <u>_#num immeuble_</u>, <u>num étage</u>, nb appartements)\\n\",\n       \"- **Immeuble** (<u>_#code rue_</u>, <u>num immeuble</u>, nb étages)\\n\",\n       \"- **Rue** (<u>code rue</u>, nom rue)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Appartement: num appart., nb pièces\\n\",\n    \"Composer, 0N Étage, _11 Appartement\\n\",\n    \"Étage: num étage, nb appartements\\n\",\n    \"Appartenir, 1N Immeuble, _11 Étage\\n\",\n    \"Immeuble: num immeuble, nb étages\\n\",\n    \"Se situer, 0N Rue, _11 Immeuble\\n\",\n    \"Rue: code rue, nom rue\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le résultat apparaît plus clairement sur le diagramme relationnel :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 61,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2OTAiIGhlaWdodD0iMTQ2IiB2aWV3Qm94PSIwIDAgNjkwIDE0NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY5MCIgaGVpZ2h0PSIxNDYiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBBUFBBUlRFTUVOVCAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9IjEzNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI2M2MjgxYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSIxMzQiIGhlaWdodD0iOTgiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSIxMzQiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM4IiB5MT0iMzkiIHgyPSIxNzIiIHkyPSIzOSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDciIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QXBwYXJ0ZW1lbnQ8L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iNTYuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I2NvZGUgcnVlPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNTkiIHgyPSIxMTIiIHkyPSI1OSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSI3My4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jbnVtIGltbWV1YmxlPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNzYiIHgyPSIxNDgiIHkyPSI3NiIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jbnVtIMOpdGFnZTwvdGV4dD4KCTxsaW5lIHgxPSI0NiIgeTE9IjkzIiB4Mj0iMTIwIiB5Mj0iOTMiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0NiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gYXBwYXJ0LjwvdGV4dD4KCTxsaW5lIHgxPSI0NiIgeTE9IjExMCIgeDI9IjEyMSIgeTI9IjExMCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjQ2IiB5PSIxMjQiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIHBpw6hjZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEVUQUdFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjIzMCIgeT0iMTgiIHdpZHRoPSIxMjIiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMjMwIiB5PSI0OCIgd2lkdGg9IjEyMiIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIyMzAiIHk9IjE4IiB3aWR0aD0iMTIyIiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIyMzAiIHkxPSI0OCIgeDI9IjM1MiIgeTI9IjQ4IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIyNjUiIHk9IjM5LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+w4l0YWdlPC90ZXh0PgoJPHRleHQgeD0iMjM4IiB5PSI2NS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jY29kZSBydWU8L3RleHQ+Cgk8bGluZSB4MT0iMjM4IiB5MT0iNjgiIHgyPSIzMDQiIHkyPSI2OCIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIzOCIgeT0iODIuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I251bSBpbW1ldWJsZTwvdGV4dD4KCTxsaW5lIHgxPSIyMzgiIHkxPSI4NSIgeDI9IjM0MCIgeTI9Ijg1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMjM4IiB5PSI5OS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5udW0gw6l0YWdlPC90ZXh0PgoJPGxpbmUgeDE9IjIzOCIgeTE9IjEwMiIgeDI9IjMwMyIgeTI9IjEwMiIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjIzOCIgeT0iMTE2IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5uYiBhcHBhcnRlbWVudHM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElNTUVVQkxFIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjQxMCIgeT0iMjYiIHdpZHRoPSIxMTAiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNDEwIiB5PSI1NiIgd2lkdGg9IjExMCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI0MTAiIHk9IjI2IiB3aWR0aD0iMTEwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjQxMCIgeTE9IjU2IiB4Mj0iNTIwIiB5Mj0iNTYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQyMiIgeT0iNDcuMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5JbW1ldWJsZTwvdGV4dD4KCTx0ZXh0IHg9IjQxOCIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+I2NvZGUgcnVlPC90ZXh0PgoJPGxpbmUgeDE9IjQxOCIgeTE9Ijc2IiB4Mj0iNDg0IiB5Mj0iNzYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0MTgiIHk9IjkwLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm51bSBpbW1ldWJsZTwvdGV4dD4KCTxsaW5lIHgxPSI0MTgiIHkxPSI5MyIgeDI9IjUxMSIgeTI9IjkzIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDE4IiB5PSIxMDciIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5iIMOpdGFnZXM8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IFJVRSAtLT4KPGc+Cgk8Zz4KCQk8cmVjdCB4PSI1NzgiIHk9IjM1IiB3aWR0aD0iNzQiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTc4IiB5PSI2NSIgd2lkdGg9Ijc0IiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjU3OCIgeT0iMzUiIHdpZHRoPSI3NCIgaGVpZ2h0PSI3NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSI1NzgiIHkxPSI2NSIgeDI9IjY1MiIgeTI9IjY1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI1OTciIHk9IjU2LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+UnVlPC90ZXh0PgoJPHRleHQgeD0iNTg2IiB5PSI4Mi4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5jb2RlIHJ1ZTwvdGV4dD4KCTxsaW5lIHgxPSI1ODYiIHkxPSI4NSIgeDI9IjY0MyIgeTI9Ijg1IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNTg2IiB5PSI5OS4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5ub20gcnVlPC90ZXh0Pgo8L2c+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoQVBQQVJURU1FTlQpIHRvICZxdW90O2NvZGUgcnVlJnF1b3Q7IChFVEFHRSkgLS0+CjxwYXRoIGQ9Ik0xNzIgNTMuNSBDMjAxIDU4IDE5MS4zMyA2Mi41IDIzMCA2Mi41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjIzMCA2Mi41IDIxOCA2OC41IDIyMiA2Mi41IDIxOCA1Ni41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMTcyIiBjeT0iNTMuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEFQUEFSVEVNRU5UKSB0byAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEVUQUdFKSAtLT4KPHBhdGggZD0iTTE3MiA3MC41IEMyMDEgNzUgMTkxLjMzIDc5LjUgMjMwIDc5LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjMwIDc5LjUgMjE4IDg1LjUgMjIyIDc5LjUgMjE4IDczLjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzIiIGN5PSI3MC41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O251bSDDqXRhZ2UmcXVvdDsgKEFQUEFSVEVNRU5UKSB0byAmcXVvdDtudW0gw6l0YWdlJnF1b3Q7IChFVEFHRSkgLS0+CjxwYXRoIGQ9Ik0xNzIgODcuNSBDMjAxIDkyIDE5MS4zMyA5Ni41IDIzMCA5Ni41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjIzMCA5Ni41IDIxOCAxMDIuNSAyMjIgOTYuNSAyMTggOTAuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjE3MiIgY3k9Ijg3LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7Y29kZSBydWUmcXVvdDsgKEVUQUdFKSB0byAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoSU1NRVVCTEUpIC0tPgo8cGF0aCBkPSJNMzUyIDYyLjUgQzM4MSA2Ni41IDM3MS4zMyA3MC41IDQxMCA3MC41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjQxMCA3MC41IDM5OCA3Ni41IDQwMiA3MC41IDM5OCA2NC41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMzUyIiBjeT0iNjIuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKEVUQUdFKSB0byAmcXVvdDtudW0gaW1tZXVibGUmcXVvdDsgKElNTUVVQkxFKSAtLT4KPHBhdGggZD0iTTM1MiA3OS41IEMzODEgODMuNSAzNzEuMzMgODcuNSA0MTAgODcuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI0MTAgODcuNSAzOTggOTMuNSA0MDIgODcuNSAzOTggODEuNSIgZmlsbD0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjM1MiIgY3k9Ijc5LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzA2MDEwMCIvPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7Y29kZSBydWUmcXVvdDsgKElNTUVVQkxFKSB0byAmcXVvdDtjb2RlIHJ1ZSZxdW90OyAoUlVFKSAtLT4KPHBhdGggZD0iTTUyMCA3MC41IEM1NDkgNzUgNTM5LjMzIDc5LjUgNTc4IDc5LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iNTc4IDc5LjUgNTY2IDg1LjUgNTcwIDc5LjUgNTY2IDczLjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSI1MjAiIGN5PSI3MC41IiByPSIxLjUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwNjAxMDAiLz4KPC9zdmc+\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t diagram --colors mondrian\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Une phase préliminaire de l'algorithme de passage au relationnel consiste à « renforcer » les entités faibles de façon à traiter uniquement des identifiants forts dans la suite. Cela permet la gestion des renforcements en cascade comme ci-dessus, ainsi que la détection des problèmes de renforcement cyclique :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 62,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"168\\\" height=\\\"194\\\" viewBox=\\\"0 0 168 194\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"168\\\" height=\\\"194\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PICK -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"128\\\" y1=\\\"47\\\" x2=\\\"39\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"39\\\" y1=\\\"147\\\" x2=\\\"39\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M52 18 a14 14 90 0 1 14 14 V46 h-54 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M66 46 v16 a14 14 90 0 1 -14 14 H26 a14 14 90 0 1 -14 -14 V46 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"12\\\" y=\\\"18\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"12\\\" y1=\\\"46\\\" x2=\\\"66\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"20\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Pick</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"73\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"44\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"44\\\" y1=\\\"103\\\" x2=\\\"62\\\" y2=\\\"103\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ZONE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"39\\\" y1=\\\"147\\\" x2=\\\"128\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"128\\\" y1=\\\"47\\\" x2=\\\"128\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M144 118 a14 14 90 0 1 14 14 V146 h-60 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M158 146 v16 a14 14 90 0 1 -14 14 H112 a14 14 90 0 1 -14 -14 V146 H60\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"98\\\" y=\\\"118\\\" width=\\\"60\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"98\\\" y1=\\\"146\\\" x2=\\\"158\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"106\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Zone</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"74\\\" y=\\\"163\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"133\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"133\\\" y1=\\\"103\\\" x2=\\\"151\\\" y2=\\\"103\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity LAND -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"97\\\" y=\\\"9\\\" width=\\\"62\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"97\\\" y=\\\"39\\\" width=\\\"62\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"97\\\" y=\\\"9\\\" width=\\\"62\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"97\\\" y1=\\\"39\\\" x2=\\\"159\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"106\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Land</text>\\n\",\n       \"\\t<text x=\\\"105\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">true</text>\\n\",\n       \"\\t<line x1=\\\"105\\\" y1=\\\"59\\\" x2=\\\"132\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"105\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">hold</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PEER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"139\\\" width=\\\"60\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"60\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"139\\\" x2=\\\"69\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Peer</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">foot</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"159\\\" x2=\\\"44\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">city</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Pick, 0N Land, _11 Peer\\n\",\n    \"Land: true, hold\\n\",\n    \"\\n\",\n    \"Peer: foot, city\\n\",\n    \"Zone, 1N Peer, _11 Land\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 63,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.17 - Cycle d'entités faibles dans \\\"Land\\\", \\\"Peer\\\".\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Gestion de l'héritage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La bonne gestion d'un héritage est primordiale, tant du point de vue de la préservation du patrimoine, que de l'optimisation des ressources financières, de la minimisation des conflits familiaux et du respect des dernières volontés du défunt. Je blague.\\n\",\n    \"\\n\",\n    \"Adaptons ici un exemple d'un [cours de Stéphane Crozat](https://stph.scenari-community.org/bdd/rel3.pdf). Nous reprenons sa terminologie et donnons en parallèle celle introduite par Martin Fowler dans _Patterns of Enterprise Application Architecture_, Addison-Wesley (2003).\\n\",\n    \"\\n\",\n    \"Ci-dessous, l'héritage est considéré comme _total_ (tout document est soit un ouvrage, soit une thèse, soit les deux). Crozat passe en revue trois mécanismes possibles pour le passage au relationnel.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"---\\n\",\n    \"\\n\",\n    \"L'**héritage par référence** (en anglais, [_Class Table Inheritance_](http://martinfowler.com/eaaCatalog/classTableInheritance.html) ou _Table Per Type Inheritance_) se note en Mocodo par une flèche simple allant vers les filles. Une référence à la table-mère sera ajoutée dans chaque table-fille comme clé étrangère. L'intérêt de cette solution est en raison directe du nombre d'attributs non identifiants de l'entité-mère.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 64,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"212\\\" viewBox=\\\"0 0 310 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance DOCUMENT_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"169\\\" y1=\\\"56\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"115 165 127 159 123 165 127 171\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"223 165 211 171 215 165 211 159\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"169 136.13 144 179.43 194 179.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"163\\\" y=\\\"171\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">T</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DOCUMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"39\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"108\\\" y1=\\\"39\\\" x2=\\\"230\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DOCUMENT</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cote</text>\\n\",\n       \"\\t<line x1=\\\"116\\\" y1=\\\"59\\\" x2=\\\"145\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">auteur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OUVRAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"165\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"165\\\" x2=\\\"115\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">OUVRAGE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"182.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">éditeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THESE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"157\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"157\\\" x2=\\\"301\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THÈSE</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">discipline</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">université</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **DOCUMENT** (<u>cote</u>, titre, auteur)\\n\",\n       \"- **OUVRAGE** (<u>_#cote_</u>, éditeur)\\n\",\n       \"- **THÈSE** (<u>_#cote_</u>, discipline, université)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"DOCUMENT: cote, titre, auteur\\n\",\n    \"    \\n\",\n    \"OUVRAGE: éditeur\\n\",\n    \"/T\\\\ DOCUMENT -> OUVRAGE, THÈSE\\n\",\n    \"THÈSE: discipline, université\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"---\\n\",\n    \"\\n\",\n    \"L'**héritage par absorption dans les tables-filles** (en anglais, [_Concrete Table Inheritance_](http://martinfowler.com/eaaCatalog/concreteTableInheritance.html) ou _Table Per Concrete Inheritance_) se note en doublant la flèche :\\n\",\n    \"\\n\",\n    \"1. les attributs de la table-mère sont reproduits dans chacune des filles. Pour chaque document qui est à la fois un ouvrage et une thèse, il y aura donc duplication des triplets (<u>cote</u>, titre, auteur).\\n\",\n    \"2. la table-mère disparaît. Pour éviter de perdre les informations sur les documents qui ne seraient ni des ouvrages, ni des thèses, Mocodo lève une erreur si l'héritage n'est pas total (T ou XT).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 65,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"212\\\" viewBox=\\\"0 0 310 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance DOCUMENT_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"170\\\" y1=\\\"56\\\" x2=\\\"170\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"168\\\" y1=\\\"56\\\" x2=\\\"168\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"115 165 127 159 123 165 127 171\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"223 165 211 171 215 165 211 159\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"169 136.13 144 179.43 194 179.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"163\\\" y=\\\"171\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">T</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DOCUMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"39\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"108\\\" y1=\\\"39\\\" x2=\\\"230\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DOCUMENT</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cote</text>\\n\",\n       \"\\t<line x1=\\\"116\\\" y1=\\\"59\\\" x2=\\\"145\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">auteur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OUVRAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"165\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"165\\\" x2=\\\"115\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">OUVRAGE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"182.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">éditeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THESE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"157\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"157\\\" x2=\\\"301\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THÈSE</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">discipline</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">université</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **OUVRAGE** (<u>cote</u>, titre, auteur, éditeur)\\n\",\n       \"- **THÈSE** (<u>cote</u>, titre, auteur, discipline, université)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"DOCUMENT: cote, titre, auteur\\n\",\n    \"    \\n\",\n    \"OUVRAGE: éditeur\\n\",\n    \"/T\\\\ DOCUMENT => OUVRAGE, THÈSE\\n\",\n    \"THÈSE: discipline, université\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"---\\n\",\n    \"\\n\",\n    \"L'**héritage par absorption dans la table-mère** (en anglais, [_Single Table Inheritance_](http://martinfowler.com/eaaCatalog/singleTableInheritance.html) ou _Table Per Hierarchy Inheritance_) se note par une flèche simple allant vers la mère. Les tables-filles disparaissent, et leurs attributs migrent dans la mère avec une contrainte d'optionalité (point d'interrogation en relationnel, `NULL` en SQL).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 66,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"212\\\" viewBox=\\\"0 0 310 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance DOCUMENT_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"169\\\" y1=\\\"56\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"169 103 175 115 169 111 163 115\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"165\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"169 136.13 144 179.43 194 179.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"163\\\" y=\\\"171\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">X</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DOCUMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"39\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"108\\\" y1=\\\"39\\\" x2=\\\"230\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DOCUMENT</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cote</text>\\n\",\n       \"\\t<line x1=\\\"116\\\" y1=\\\"59\\\" x2=\\\"145\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">auteur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OUVRAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"165\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"165\\\" x2=\\\"115\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">OUVRAGE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"182.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">éditeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THESE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"157\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"157\\\" x2=\\\"301\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THÈSE</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">discipline</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">université</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **DOCUMENT** (<u>cote</u>, titre, auteur, discriminateur?, éditeur?, discipline?, université?)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE DOCUMENT (\\n\",\n       \"  PRIMARY KEY (cote),\\n\",\n       \"  cote           VARCHAR(42) NOT NULL,\\n\",\n       \"  titre          VARCHAR(42),\\n\",\n       \"  auteur         VARCHAR(42),\\n\",\n       \"  discriminateur ENUM ('OUVRAGE', 'THÈSE') NULL,\\n\",\n       \"  editeur        VARCHAR(42) NULL,\\n\",\n       \"  discipline     VARCHAR(42) NULL,\\n\",\n       \"  universite     VARCHAR(42) NULL\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c sql\\n\",\n    \"DOCUMENT: cote, titre, auteur\\n\",\n    \"\\n\",\n    \"OUVRAGE: éditeur\\n\",\n    \"/X\\\\ DOCUMENT <- OUVRAGE, THÈSE: discriminateur [ENUM ('OUVRAGE', 'THÈSE')]\\n\",\n    \"THÈSE: discipline, université\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ci-dessus, nous avons donné comme « attribut » au triangle d'héritage un « discriminateur » de type `ENUM`. Cela ajoute à la table un champ optionnel ou non (selon que l'héritage est partiel ou total) permettant de déterminer à quel type concret d'une occurrence on a affaire.\\n\",\n    \"\\n\",\n    \"C'est par défaut un `UNSIGNED INT`, qui pourra prendre les valeurs :\\n\",\n    \"- 1 = OUVRAGE, 2 = THÈSE, pour l'héritage exclusif ;\\n\",\n    \"- 1 ($2^0$) = OUVRAGE, 2 ($2^1$) = THÈSE, 3 ($2^0 | 2^1$) = OUVRAGE + THÈSE, pour l'héritage non exclusif.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alternativement à l'emploi d'un discriminateur, Mocodo peut ajouter un drapeau booléen par table-fille. Cela se note en doublant la flèche :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 67,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"212\\\" viewBox=\\\"0 0 310 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance DOCUMENT_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"169\\\" y1=\\\"56\\\" x2=\\\"169\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"169 103 175 115 169 111 163 115\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"166\\\" x2=\\\"169\\\" y2=\\\"166\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"164\\\" x2=\\\"169\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"166\\\" x2=\\\"169\\\" y2=\\\"166\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"164\\\" x2=\\\"169\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"169 136.13 144 179.43 194 179.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"163\\\" y=\\\"171\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">T</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DOCUMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"39\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"108\\\" y=\\\"9\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"108\\\" y1=\\\"39\\\" x2=\\\"230\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DOCUMENT</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cote</text>\\n\",\n       \"\\t<line x1=\\\"116\\\" y1=\\\"59\\\" x2=\\\"145\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">auteur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OUVRAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"165\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"135\\\" width=\\\"106\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"165\\\" x2=\\\"115\\\" y2=\\\"165\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">OUVRAGE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"182.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">éditeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THESE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"157\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"127\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"157\\\" x2=\\\"301\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THÈSE</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">discipline</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">université</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **DOCUMENT** (<u>cote</u>, titre, auteur, est ouvrage!, éditeur?, est these!, discipline?, université?)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE DOCUMENT (\\n\",\n       \"  PRIMARY KEY (cote),\\n\",\n       \"  cote        VARCHAR(42) NOT NULL,\\n\",\n       \"  titre       VARCHAR(42),\\n\",\n       \"  auteur      VARCHAR(42),\\n\",\n       \"  est_ouvrage BOOLEAN NOT NULL,\\n\",\n       \"  editeur     VARCHAR(42) NULL,\\n\",\n       \"  est_these   BOOLEAN NOT NULL,\\n\",\n       \"  discipline  VARCHAR(42) NULL,\\n\",\n       \"  universite  VARCHAR(42) NULL\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c sql\\n\",\n    \"DOCUMENT: cote, titre, auteur\\n\",\n    \"\\n\",\n    \"OUVRAGE: éditeur\\n\",\n    \"/T\\\\ DOCUMENT <= OUVRAGE, THÈSE\\n\",\n    \"THÈSE: discipline, université\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Gestion de l'agrégation\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Un agrégat simple autour d'une association dont toutes les cardinalités maximales sont N se traduit en relationnel comme la même association non agrégée, mais avec une clé primaire réduite :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 68,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"404\\\" height=\\\"213\\\" viewBox=\\\"0 0 404 213\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"404\\\" height=\\\"213\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"180\\\" cy=\\\"113\\\" r=\\\"6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF55\\\"/>\\n\",\n       \"\\t<line x1=\\\"180\\\" y1=\\\"157\\\" x2=\\\"180\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"331\\\" y1=\\\"56\\\" x2=\\\"180\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"56\\\" x2=\\\"180\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L384 13 a7 7 0 0 1 7 7 L391 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.3\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L384 13 a7 7 0 0 1 7 7 L391 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M223 27 a14 14 90 0 1 14 14 V55 h-114 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M237 55 v16 a14 14 90 0 1 -14 14 H137 a14 14 90 0 1 -14 -14 V55 H114\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"123\\\" y=\\\"27\\\" width=\\\"114\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"123\\\" y1=\\\"55\\\" x2=\\\"237\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"130\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">RÉSERVER</text>\\n\",\n       \"\\t\\t<text x=\\\"130\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"190\\\" y=\\\"106\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"94\\\" y=\\\"77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"66\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"56\\\" width=\\\"66\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"26\\\" width=\\\"66\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"56\\\" x2=\\\"84\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DATE</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"76\\\" x2=\\\"54\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"276\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"276\\\" y=\\\"48\\\" width=\\\"110\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"276\\\" y=\\\"18\\\" width=\\\"110\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"276\\\" y1=\\\"48\\\" x2=\\\"386\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CHAMBRE</text>\\n\",\n       \"\\t<text x=\\\"284\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"284\\\" y1=\\\"68\\\" x2=\\\"373\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"284\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"119\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"149\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"119\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"138\\\" y1=\\\"149\\\" x2=\\\"222\\\" y2=\\\"149\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"140.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"166.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. client</text>\\n\",\n       \"\\t<line x1=\\\"146\\\" y1=\\\"169\\\" x2=\\\"199\\\" y2=\\\"169\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"183.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom client</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **CHAMBRE** (<u>num. chambre</u>, prix)\\n\",\n       \"- **CLIENT** (<u>id. client</u>, nom client)\\n\",\n       \"- **RÉSERVER** (<u>_#num. chambre_</u>, <u>date</u>, _#id. client!_, durée)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"DATE: date\\n\",\n    \"RÉSERVER, /1N CLIENT, 1N CHAMBRE, 0N DATE: durée\\n\",\n    \"CHAMBRE: num. chambre, prix\\n\",\n    \"\\n\",\n    \"CLIENT: id. client, nom client\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Un agrégat simple autour d'une association dont la cardinalité maximale « de sortie » est 1 se traduit en relationnel comme la même association non agrégée, mais avec une contrainte d'unicité sur la clé étrangère. Ci-dessous, au lieu d'avoir simplement _num résa_ $\\\\implies$ (_num voilier_, _num semaine_), on a donc en plus (_num voilier_, _num semaine_) $\\\\implies$ _num résa_ :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 69,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"378\\\" height=\\\"240\\\" viewBox=\\\"0 0 378 240\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"378\\\" height=\\\"240\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association OFFRIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"184\\\" cy=\\\"122\\\" r=\\\"6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF55\\\"/>\\n\",\n       \"\\t<line x1=\\\"184\\\" y1=\\\"175\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L358 13 a7 7 0 0 1 7 7 L365 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.3\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L358 13 a7 7 0 0 1 7 7 L365 92 a7 7 0 0 1 -7 7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M209 27 a14 14 90 0 1 14 14 V55 h-78 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M223 55 v16 a14 14 90 0 1 -14 14 H159 a14 14 90 0 1 -14 -14 V55 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"145\\\" y=\\\"27\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"145\\\" y1=\\\"55\\\" x2=\\\"223\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"153\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Offrir</text>\\n\",\n       \"\\t\\t<text x=\\\"152\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"115\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"116\\\" y=\\\"77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"233\\\" y=\\\"77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity VOILIER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"48\\\" width=\\\"88\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"88\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"48\\\" x2=\\\"106\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"29\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Voilier</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num voilier</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"68\\\" x2=\\\"97\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">longueur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SEMAINE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"262\\\" y=\\\"18\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"262\\\" y=\\\"48\\\" width=\\\"98\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"262\\\" y=\\\"18\\\" width=\\\"98\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"262\\\" y1=\\\"48\\\" x2=\\\"360\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"274\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Semaine</text>\\n\",\n       \"\\t<text x=\\\"270\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num semaine</text>\\n\",\n       \"\\t<line x1=\\\"270\\\" y1=\\\"68\\\" x2=\\\"352\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"270\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date début</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESERVATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"119\\\" y=\\\"128\\\" width=\\\"130\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"119\\\" y=\\\"158\\\" width=\\\"130\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"119\\\" y=\\\"128\\\" width=\\\"130\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"119\\\" y1=\\\"158\\\" x2=\\\"249\\\" y2=\\\"158\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"149.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réservation</text>\\n\",\n       \"\\t<text x=\\\"127\\\" y=\\\"175.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num résa</text>\\n\",\n       \"\\t<line x1=\\\"127\\\" y1=\\\"178\\\" x2=\\\"185\\\" y2=\\\"178\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"127\\\" y=\\\"192.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">arrhes</text>\\n\",\n       \"\\t<text x=\\\"127\\\" y=\\\"209\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date résa</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Réservation** (<u>num résa</u>, arrhes, date résa, _#num voilier!_ <sup>u1</sup>, _#num semaine!_ <sup>u1</sup>, tarif)\\n\",\n       \"- **Semaine** (<u>num semaine</u>, date début)\\n\",\n       \"- **Voilier** (<u>num voilier</u>, longueur)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"Voilier: num voilier, longueur\\n\",\n    \"Offrir, /11 Réservation, 0N Voilier, 0N Semaine: tarif\\n\",\n    \"Semaine: num semaine, date début\\n\",\n    \"\\n\",\n    \"Réservation: num résa, arrhes, date résa\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le cas des agrégats multiples, plus rare, est étudié en annexe.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Ajustement des règles de passage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Supprimer ou maintenir une table facultative\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le passage au relationnel supprime automatiquement les tables réduites à une clé primaire, pourvu qu'aucun composant de celle-ci ne soit clé étrangère. Si l'on souhaite maintenir certaines de ces tables, on préfixe d'un `+` l'entité concernée. Ainsi, ci-dessous, Date est supprimée, mais pas Thème.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 70,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Aborder** (<u>_#thème_</u>, <u>_#id. formation_</u>)\\n\",\n       \"  - Le champ _thème_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Thème_.\\n\",\n       \"  - Le champ _id. formation_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Formation_.\\n\",\n       \"\\n\",\n       \"- **Animateur** (<u>num. animateur</u>, nom animateur)\\n\",\n       \"  - Le champ _num. animateur_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Animateur_.\\n\",\n       \"  - Le champ _nom animateur_ était déjà un simple attribut de l'entité _Animateur_.\\n\",\n       \"\\n\",\n       \"- **Formation** (<u>id. formation</u>, durée)\\n\",\n       \"  - Le champ _id. formation_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Formation_.\\n\",\n       \"  - Le champ _durée_ était déjà un simple attribut de l'entité _Formation_.\\n\",\n       \"\\n\",\n       \"- **Intervenir** (<u>_#num. animateur_</u>, <u>_#id. formation_</u>, <u>date</u>, nb heures)\\n\",\n       \"  - Le champ _num. animateur_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Animateur_.\\n\",\n       \"  - Le champ _id. formation_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Formation_.\\n\",\n       \"  - Le champ _date_ fait partie de la clé primaire de la table. Sa table d'origine (_Date_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\\n\",\n       \"  - Le champ _nb heures_ était déjà un simple attribut de l'association _Intervenir_.\\n\",\n       \"\\n\",\n       \"- **Thème** (<u>thème</u>)\\n\",\n       \"  - Le champ _thème_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Thème_.\\n\",\n       \"<br>\\n\",\n       \"----\\n\",\n       \"\\n\",\n       \"\\n\",\n       \"**NB.** La table _Date_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"638\\\" height=\\\"169\\\" viewBox=\\\"0 0 638 169\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"638\\\" height=\\\"169\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association INTERVENIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"47\\\" x2=\\\"208\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"349\\\" y1=\\\"47\\\" x2=\\\"208\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"208\\\" y1=\\\"130\\\" x2=\\\"208\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M250 18 a14 14 90 0 1 14 14 V46 h-112 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M264 46 v16 a14 14 90 0 1 -14 14 H166 a14 14 90 0 1 -14 -14 V46 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"18\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"152\\\" y1=\\\"46\\\" x2=\\\"264\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"159\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Intervenir</text>\\n\",\n       \"\\t\\t<text x=\\\"159\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nb heures</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"269\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"213\\\" y=\\\"92\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ABORDER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"592\\\" y1=\\\"47\\\" x2=\\\"480\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"349\\\" y1=\\\"47\\\" x2=\\\"480\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M512 18 a14 14 90 0 1 14 14 V46 h-92 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M526 46 v16 a14 14 90 0 1 -14 14 H448 a14 14 90 0 1 -14 -14 V46 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"434\\\" y=\\\"18\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"434\\\" y1=\\\"46\\\" x2=\\\"526\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"441\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Aborder</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"531\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"410\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ANIMATEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"123\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Animateur</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. animateur</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"115\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom animateur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FORMATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"293\\\" y=\\\"9\\\" width=\\\"112\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"293\\\" y=\\\"39\\\" width=\\\"112\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"293\\\" y=\\\"9\\\" width=\\\"112\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"293\\\" y1=\\\"39\\\" x2=\\\"405\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"302\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Formation</text>\\n\",\n       \"\\t<text x=\\\"301\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. formation</text>\\n\",\n       \"\\t<line x1=\\\"301\\\" y1=\\\"59\\\" x2=\\\"382\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"301\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THEME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"555\\\" y=\\\"17\\\" width=\\\"74\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"555\\\" y=\\\"47\\\" width=\\\"74\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"555\\\" y=\\\"17\\\" width=\\\"74\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"555\\\" y1=\\\"47\\\" x2=\\\"629\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"564\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Thème</text>\\n\",\n       \"\\t<text x=\\\"563\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">thème</text>\\n\",\n       \"\\t<line x1=\\\"563\\\" y1=\\\"67\\\" x2=\\\"603\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"100\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"130\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"100\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"178\\\" y1=\\\"130\\\" x2=\\\"238\\\" y2=\\\"130\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"187\\\" y=\\\"121.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"147.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"186\\\" y1=\\\"150\\\" x2=\\\"214\\\" y2=\\\"150\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select mld mcd -t mld:e\\n\",\n    \"Animateur: num. animateur, nom animateur\\n\",\n    \"Intervenir, 1N Animateur, 1N Formation, 1N Date: nb heures\\n\",\n    \"Formation: id. formation, durée\\n\",\n    \"Aborder, 1N Thème, 1N Formation\\n\",\n    \"+Thème: thème\\n\",\n    \"\\n\",\n    \"Date: date\\n\",\n    \":\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez l'explication de la suppression (en NB) et celle de la perte du caractère étranger de l'attribut _date_ (dans la table Intervenir). Pour une discussion sur cette problématique, cf. [issue #66](https://github.com/laowantong/mocodo/issues/66).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Forcer une table pour éviter un champ optionnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Une association de dépendance fonctionnelle ne donne normalement pas lieu à une création de table. Pour reprendre un exemple vu plus haut :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 71,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"408\\\" height=\\\"128\\\" viewBox=\\\"0 0 408 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"408\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ENVOYER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"68\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"338\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M234 35 a14 14 90 0 1 14 14 V63 h-92 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M248 63 v16 a14 14 90 0 1 -14 14 H170 a14 14 90 0 1 -14 -14 V63 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"35\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"63\\\" x2=\\\"248\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"164\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Envoyer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTREPRISE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"127\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entreprise</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. entreprise</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"101\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">activité</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PARTICIPANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"47\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"277\\\" y1=\\\"47\\\" x2=\\\"399\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Participant</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. inscrit</text>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"67\\\" x2=\\\"343\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Entreprise** (<u>id. entreprise</u>, raison, activité, adresse)\\n\",\n       \"- **Participant** (<u>id. inscrit</u>, nom, adresse, _#id. entreprise?_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c\\n\",\n    \"Entreprise: id. entreprise, raison, activité, adresse\\n\",\n    \"Envoyer, 0N Entreprise, 01 Participant\\n\",\n    \"Participant: id. inscrit, nom, adresse\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans le cas où les particuliers sont beaucoup plus nombreux que les employés d'entreprise, la clé étrangère _#id. entreprise_ est presque toujours à `NULL`. C'est une perte d'espace de stockage. On peut <s>entourer l'association de crochets droits</s> préfixer d'un `+` (à partir de la version 4) l'association pour forcer sa conversion en table. Mocodo produit alors une visualisation intermédiaire entre entité et association :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 72,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"408\\\" height=\\\"128\\\" viewBox=\\\"0 0 408 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"408\\\" height=\\\"128\\\" fill=\\\"#fefeec\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ENVOYER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"68\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"338\\\" y1=\\\"64\\\" x2=\\\"202\\\" y2=\\\"64\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"146\\\" y=\\\"25\\\" width=\\\"112\\\" height=\\\"78\\\" fill=\\\"#fced5f55\\\" rx=\\\"7\\\" stroke=\\\"#06010055\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M234 35 a14 14 90 0 1 14 14 V63 h-92 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#081a84\\\" stroke=\\\"#081a84\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M248 63 v16 a14 14 90 0 1 -14 14 H170 a14 14 90 0 1 -14 -14 V63 H92\\\" fill=\\\"#fefeec\\\" stroke=\\\"#fefeec\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"35\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"63\\\" x2=\\\"248\\\" y2=\\\"63\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"164\\\" y=\\\"56.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Envoyer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"80\\\" fill=\\\"#060100\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTREPRISE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"80\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"127\\\" y2=\\\"39\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entreprise</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. entreprise</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"101\\\" y2=\\\"59\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">activité</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PARTICIPANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"47\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"277\\\" y=\\\"17\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"277\\\" y1=\\\"47\\\" x2=\\\"399\\\" y2=\\\"47\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"38.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Participant</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"64.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. inscrit</text>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"67\\\" x2=\\\"343\\\" y2=\\\"67\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"81.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"285\\\" y=\\\"98\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Entreprise** (<u>id. entreprise</u>, raison, activité, adresse)\\n\",\n       \"- **Envoyer** (<u>_#id. inscrit_</u>, _#id. entreprise!_)\\n\",\n       \"- **Participant** (<u>id. inscrit</u>, nom, adresse)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --select all -t mld:c --colors mondrian\\n\",\n    \"Entreprise: id. entreprise, raison, activité, adresse\\n\",\n    \"+Envoyer, 0N Entreprise, 01 Participant\\n\",\n    \"Participant: id. inscrit, nom, adresse\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cela permet du même coup d'éviter un champ optionnel, dont la gestion peut être délicate (notamment sous Microsoft SQL Server qui, au mépris du standard SQL, ne semble pas convaincu qu'une colonne `UNIQUE` peut contenir plus d'un `NULL` !).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Préciser le rôle d'une clé étrangère\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ce MCD modélise la soutenance de stage des étudiants, ainsi que la visite d'amitié et de contrôle dont les honore leur enseignant responsable :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 73,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"412\\\" height=\\\"212\\\" viewBox=\\\"0 0 412 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"412\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association SOUTENIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"187\\\" y1=\\\"56\\\" x2=\\\"58\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"156\\\" x2=\\\"58\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M93 27 a14 14 90 0 1 14 14 V55 h-98 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M107 55 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V55 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"27\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"55\\\" x2=\\\"107\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Soutenir</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">note stage</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"113\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"63\\\" y=\\\"118\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REPONDRE_DE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"156\\\" x2=\\\"187\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"187\\\" y1=\\\"56\\\" x2=\\\"187\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"342\\\" y1=\\\"156\\\" x2=\\\"187\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M238 127 a14 14 90 0 1 14 14 V155 h-130 V141 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M252 155 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V155 H130\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"127\\\" width=\\\"130\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"155\\\" x2=\\\"252\\\" y2=\\\"155\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"130\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Répondre de</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"93\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"192\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"257\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETUDIANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"136\\\" y=\\\"9\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"136\\\" y=\\\"39\\\" width=\\\"102\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"136\\\" y=\\\"9\\\" width=\\\"102\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"136\\\" y1=\\\"39\\\" x2=\\\"238\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étudiant</text>\\n\",\n       \"\\t<text x=\\\"144\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. étudiant</text>\\n\",\n       \"\\t<line x1=\\\"144\\\" y1=\\\"59\\\" x2=\\\"230\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"144\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"144\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">coordonnées</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"126\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"156\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"126\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"28\\\" y1=\\\"156\\\" x2=\\\"88\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"37\\\" y=\\\"147.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"36\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"36\\\" y1=\\\"176\\\" x2=\\\"64\\\" y2=\\\"176\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENSEIGNANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"281\\\" y=\\\"109\\\" width=\\\"122\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"281\\\" y=\\\"139\\\" width=\\\"122\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"281\\\" y=\\\"109\\\" width=\\\"122\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"281\\\" y1=\\\"139\\\" x2=\\\"403\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"290\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Enseignant</text>\\n\",\n       \"\\t<text x=\\\"289\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. enseignant</text>\\n\",\n       \"\\t<line x1=\\\"289\\\" y1=\\\"159\\\" x2=\\\"390\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"289\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"289\\\" y=\\\"190\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">coordonnées</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Enseignant** (<u>num. enseignant</u>, nom, coordonnées)\\n\",\n       \"- **Étudiant** (<u>num. étudiant</u>, nom, coordonnées, date 1, note stage, date 2, _#num. enseignant_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Soutenir, 01 Étudiant, 0N Date: note stage\\n\",\n    \"Étudiant: num. étudiant, nom, coordonnées\\n\",\n    \"\\n\",\n    \"Date: date\\n\",\n    \"Répondre de, 0N Date, 11 Étudiant, 0N Enseignant\\n\",\n    \"Enseignant: num. enseignant, nom, coordonnées\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Force est de constater que la table Étudiant laisse quelque peu à désirer du point de vue sémantique :\\n\",\n    \"\\n\",\n    \"- on ne sait pas à quoi correspondent les attributs _date 1_ et _date 2_ : ils ne peuvent en tout cas certainement pas être laissés en l'état ;\\n\",\n    \"- ensuite, on pourrait avoir envie d'expliciter la raison pour laquelle un enseignant apparaît parmi les attributs d'un étudiant.\\n\",\n    \"\\n\",\n    \"Ces précisions peuvent être apportées en insérant, entre la cardinalité et l'entité des pattes appropriées, une note entre crochets, appelée **rôle**. Ces rôles seront utilisés pour compléter le nom des clés étrangères correspondantes. Cela permet de réintroduire la sémantique perdue lors de la disparition des associations de dépendance fonctionnelle par lesquelles elle ont migré :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 74,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Enseignant** (<u>num. enseignant</u>, nom, coordonnées)\\n\",\n       \"- **Étudiant** (<u>num. étudiant</u>, nom, coordonnées, date soutenance, note stage, date visite resp, _#num. ens. resp._)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mld\\n\",\n    \"Soutenir, 01 Étudiant, 0N [soutenance] Date: note stage\\n\",\n    \"Étudiant: num. étudiant, nom, coordonnées\\n\",\n    \"\\n\",\n    \"Date: date\\n\",\n    \"Répondre de, 0N [+ visite resp] Date, 11 Étudiant, 0N [-num. ens. resp.] Enseignant\\n\",\n    \"Enseignant: num. enseignant, nom, coordonnées\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La composition du rôle est entièrement paramétrable :\\n\",\n    \"\\n\",\n    \"- _date soutenance_ : par défaut, le rôle est concaténé à la clé, avec un séparateur dépendant du gabarit (espace par défaut, tiret bas pour SQL).\\n\",\n    \"- _date visite resp._ : `+` en préfixe supprime le séparateur.\\n\",\n    \"- _num. ens. resp._ : `-` en préfixe supprime le nom de la clé et le remplace par le rôle.\\n\",\n    \"\\n\",\n    \"Pour ne pas surcharger le dessin, le rôle n'est pas affiché à côté du lien, mais il apparaît au survol de la cardinalité.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Correction de la version 4.0.** Dans une association réflexive hiérarchique, c'est désormais le rôle porté par la patte `*N` qui sert à rétablir la sémantique. Auparavant c'était l'inverse, en contradiction avec le traitement des associations binaires et n-aires : si vous avez utilisé des rôles dans une association réflexive avant la version 4.0.0, vous devez donc les permutez pour que Mocodo les traite correctement. Reprenons la filiation patrilinéaire :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 75,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"267\\\" height=\\\"112\\\" viewBox=\\\"0 0 267 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"267\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association ENGENDRER -->\\n\",\n       \"<g class=\\\"page_0_bed143a6 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M53 56 C84.67 24 131 24 192 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M53 56 C84 88 130.33 88 192 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M244 27 a14 14 90 0 1 14 14 V55 h-132 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M258 55 v16 a14 14 90 0 1 -14 14 H140 a14 14 90 0 1 -14 -14 V55 H132\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"126\\\" y=\\\"27\\\" width=\\\"132\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"126\\\" y1=\\\"55\\\" x2=\\\"258\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"134\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ENGENDRER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"49\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_bed143a6(evt,'père')\\\" onmouseout=\\\"hide_bed143a6(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"71\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_bed143a6(evt,'fils')\\\" onmouseout=\\\"hide_bed143a6(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity HOMME -->\\n\",\n       \"<g class=\\\"page_0_bed143a6 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"97\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">HOMME</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. SS</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"67\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prénom</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_bed143a6(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 67) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_bed143a6\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_bed143a6\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_bed143a6(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_bed143a6\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_bed143a6\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_bed143a6\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_bed143a6\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_bed143a6\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_bed143a6\\\" text-anchor=\\\"middle\\\" x=\\\"133\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_bed143a6\\\" x=\\\"0\\\" y=\\\"72\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_bed143a6\\\" text-anchor=\\\"middle\\\" x=\\\"133\\\" y=\\\"96\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **HOMME** (<u>num. SS</u>, nom, prénom, _#num. SS père_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"HOMME: num. SS, nom, prénom\\n\",\n    \"ENGENDRER, 0N [père] HOMME, 01 [fils] HOMME\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Orienter la migration dans les DF à double sens\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Lorsque toutes les cardinalités d'une dépendance fonctionnelle sont 11 (ou toutes 01), le sens de migration est spécifié à coût zéro en référençant l'entité réceptrice en tête de la liste des entités énumérées dans la clause de définition de l'association :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 76,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **AUTHENTICATION** (<u>email</u>, password hash, salt)\\n\",\n       \"- **USER** (<u>user id</u>, name, pseudo, _#email_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMzgyIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjM4MiIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBVU0VSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM4IiB5PSI5IiB3aWR0aD0iNjgiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjM5IiB3aWR0aD0iNjgiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI2OCIgaGVpZ2h0PSIxMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzgiIHkxPSIzOSIgeDI9IjEwNiIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSI0NyIgeT0iMzAuMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5VU0VSPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnVzZXIgaWQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9Ijg5IiB5Mj0iNTkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI0NiIgeT0iNzMuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+bmFtZTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5wc2V1ZG88L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iMTA3IiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij4jZW1haWw8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IEFVVEhFTlRJQ0FUSU9OIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjE2NCIgeT0iMTciIHdpZHRoPSIxODAiIGhlaWdodD0iMzAiIGZpbGw9IiNjNjI4MWIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY0IiB5PSI0NyIgd2lkdGg9IjE4MCIgaGVpZ2h0PSI2NCIgZmlsbD0iI2ZjZWQ1ZiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIxNjQiIHk9IjE3IiB3aWR0aD0iMTgwIiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjE2NCIgeTE9IjQ3IiB4Mj0iMzQ0IiB5Mj0iNDciIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjE3MiIgeT0iMzguMyIgZmlsbD0iI2ZlZmVlYyIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5BVVRIRU5USUNBVElPTjwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iNjQuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+ZW1haWw8L3RleHQ+Cgk8bGluZSB4MT0iMTcyIiB5MT0iNjciIHgyPSIyMDUiIHkyPSI2NyIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE3MiIgeT0iODEuMSIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+cGFzc3dvcmQgaGFzaDwvdGV4dD4KCTx0ZXh0IHg9IjE3MiIgeT0iOTgiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnNhbHQ8L3RleHQ+CjwvZz4KCjwhLS0gTGluayBmcm9tICZxdW90O2VtYWlsJnF1b3Q7IChVU0VSKSB0byAmcXVvdDtlbWFpbCZxdW90OyAoQVVUSEVOVElDQVRJT04pIC0tPgo8cGF0aCBkPSJNMTA2IDEwNC41IEMxMzUgODMgMTI1LjMzIDYxLjUgMTY0IDYxLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTY0IDYxLjUgMTUyIDY3LjUgMTU2IDYxLjUgMTUyIDU1LjUiIGZpbGw9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxMDYiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cjwvc3ZnPg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE AUTHENTICATION (\\n\",\n       \"  PRIMARY KEY (email),\\n\",\n       \"  email         VARCHAR(255) NOT NULL,\\n\",\n       \"  password_hash BINARY(64),\\n\",\n       \"  salt          BINARY(16)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE USER (\\n\",\n       \"  PRIMARY KEY (user_id),\\n\",\n       \"  user_id VARCHAR(8) NOT NULL,\\n\",\n       \"  name    VARCHAR(100),\\n\",\n       \"  pseudo  VARCHAR(100),\\n\",\n       \"  email   VARCHAR(255) NOT NULL,\\n\",\n       \"  UNIQUE (email)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"ALTER TABLE USER ADD FOREIGN KEY (email) REFERENCES AUTHENTICATION (email);\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mld diagram sql --colors mondrian\\n\",\n    \"USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]\\n\",\n    \"DF, 11 USER, 11 AUTHENTICATION\\n\",\n    \"AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans la version avec identification relative, c'est l'entité faible qui doit être placée en tête :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 77,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **AUTHENTICATION** (<u>_#user id_</u>, <u>email</u>, password hash, salt)\\n\",\n       \"- **USER** (<u>user id</u>, name, pseudo)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSIzODIiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMzgyIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjM4MiIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNmZWZlZWMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBVU0VSIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjM4IiB5PSIxNyIgd2lkdGg9IjY4IiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSI0NyIgd2lkdGg9IjY4IiBoZWlnaHQ9IjY0IiBmaWxsPSIjZmNlZDVmIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM4IiB5PSIxNyIgd2lkdGg9IjY4IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjM4IiB5MT0iNDciIHgyPSIxMDYiIHkyPSI0NyIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iNDciIHk9IjM4LjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+VVNFUjwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI2NC4xIiBmaWxsPSIjMDYwMTAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij51c2VyIGlkPC90ZXh0PgoJPGxpbmUgeDE9IjQ2IiB5MT0iNjciIHgyPSI4OSIgeTI9IjY3IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjgxLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPm5hbWU8L3RleHQ+Cgk8dGV4dCB4PSI0NiIgeT0iOTgiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnBzZXVkbzwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQVVUSEVOVElDQVRJT04gLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTY0IiB5PSI5IiB3aWR0aD0iMTgwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjYzYyODFiIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE2NCIgeT0iMzkiIHdpZHRoPSIxODAiIGhlaWdodD0iODAiIGZpbGw9IiNmY2VkNWYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTY0IiB5PSI5IiB3aWR0aD0iMTgwIiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNjQiIHkxPSIzOSIgeDI9IjM0NCIgeTI9IjM5IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxNzIiIHk9IjMwLjMiIGZpbGw9IiNmZWZlZWMiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+QVVUSEVOVElDQVRJT048L3RleHQ+Cgk8dGV4dCB4PSIxNzIiIHk9IjU2LjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPiN1c2VyIGlkPC90ZXh0PgoJPGxpbmUgeDE9IjE3MiIgeTE9IjU5IiB4Mj0iMjI0IiB5Mj0iNTkiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzIiIHk9IjczLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPmVtYWlsPC90ZXh0PgoJPGxpbmUgeDE9IjE3MiIgeTE9Ijc2IiB4Mj0iMjA1IiB5Mj0iNzYiIHN0cm9rZT0iIzA2MDEwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSIxNzIiIHk9IjkwLjEiIGZpbGw9IiMwNjAxMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPnBhc3N3b3JkIGhhc2g8L3RleHQ+Cgk8dGV4dCB4PSIxNzIiIHk9IjEwNyIgZmlsbD0iIzA2MDEwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+c2FsdDwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7dXNlciBpZCZxdW90OyAoQVVUSEVOVElDQVRJT04pIHRvICZxdW90O3VzZXIgaWQmcXVvdDsgKFVTRVIpIC0tPgo8cGF0aCBkPSJNMTY0IDUzLjUgQzEzNSA1Ny41IDE0NC42NyA2MS41IDEwNiA2MS41IiBmaWxsPSJub25lIiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMSIvPgo8cG9seWdvbiBwb2ludHM9IjEwNiA2MS41IDExOCA1NS41IDExNCA2MS41IDExOCA2Ny41IiBmaWxsPSIjMDYwMTAwIiBzdHJva2Utd2lkdGg9IjAiLz4KPGNpcmNsZSBjeD0iMTY0IiBjeT0iNTMuNSIgcj0iMS41IiBzdHJva2U9IiMwNjAxMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDYwMTAwIi8+Cjwvc3ZnPg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE AUTHENTICATION (\\n\",\n       \"  PRIMARY KEY (user_id, email),\\n\",\n       \"  user_id       VARCHAR(8) NOT NULL,\\n\",\n       \"  email         VARCHAR(255) NOT NULL,\\n\",\n       \"  password_hash BINARY(64),\\n\",\n       \"  salt          BINARY(16)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE USER (\\n\",\n       \"  PRIMARY KEY (user_id),\\n\",\n       \"  user_id VARCHAR(8) NOT NULL,\\n\",\n       \"  name    VARCHAR(100),\\n\",\n       \"  pseudo  VARCHAR(100)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"ALTER TABLE AUTHENTICATION ADD FOREIGN KEY (user_id) REFERENCES USER (user_id);\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mld diagram sql --colors mondrian\\n\",\n    \"USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]\\n\",\n    \"DF, _11 AUTHENTICATION, 11 USER\\n\",\n    \"AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les traitements alternatifs (fusion en une seule table ou migration dans les deux sens) ne sont pas pris en charge par Mocodo. La dernière pratique ressortit à la phase d'optimisation et de dénormalisation de la base, qui est en dehors de sa juridiction. La seule chose que vous pouvez faire, à des fins d'illustration, est de reprendre le MLD généré pour y ajouter à la main la migration inverse. Notez cependant que les schémas logique et physique générés seront alors dépourvus de toute clé étrangère (et nécessiteront donc également d'être retouchés à la main).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 78,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"382\\\" height=\\\"128\\\" viewBox=\\\"0 0 382 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"382\\\" height=\\\"128\\\" fill=\\\"#fefeec\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity USER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"38\\\" y=\\\"9\\\" width=\\\"68\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"38\\\" y=\\\"39\\\" width=\\\"68\\\" height=\\\"80\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"38\\\" y=\\\"9\\\" width=\\\"68\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"38\\\" y1=\\\"39\\\" x2=\\\"106\\\" y2=\\\"39\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"47\\\" y=\\\"30.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">USER</text>\\n\",\n       \"\\t<text x=\\\"46\\\" y=\\\"56.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">user id</text>\\n\",\n       \"\\t<line x1=\\\"46\\\" y1=\\\"59\\\" x2=\\\"89\\\" y2=\\\"59\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"46\\\" y=\\\"73.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">name</text>\\n\",\n       \"\\t<text x=\\\"46\\\" y=\\\"90.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">pseudo</text>\\n\",\n       \"\\t<text x=\\\"46\\\" y=\\\"107\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">#email</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AUTHENTICATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"164\\\" y=\\\"9\\\" width=\\\"180\\\" height=\\\"30\\\" fill=\\\"#c6281b\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"164\\\" y=\\\"39\\\" width=\\\"180\\\" height=\\\"80\\\" fill=\\\"#fced5f\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"164\\\" y=\\\"9\\\" width=\\\"180\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"164\\\" y1=\\\"39\\\" x2=\\\"344\\\" y2=\\\"39\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"30.3\\\" fill=\\\"#fefeec\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">AUTHENTICATION</text>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"56.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">email</text>\\n\",\n       \"\\t<line x1=\\\"172\\\" y1=\\\"59\\\" x2=\\\"205\\\" y2=\\\"59\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"73.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">password hash</text>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"90.1\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">salt</text>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"107\\\" fill=\\\"#060100\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">#user id</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Link from &quot;email&quot; (USER) to &quot;email&quot; (AUTHENTICATION) -->\\n\",\n       \"<path d=\\\"M106 104.5 C135 79 125.33 53.5 164 53.5\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"<polygon points=\\\"164 53.5 152 59.5 156 53.5 152 47.5\\\" fill=\\\"#060100\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"<circle cx=\\\"106\\\" cy=\\\"104.5\\\" r=\\\"1.5\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" fill=\\\"#060100\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Link from &quot;user id&quot; (AUTHENTICATION) to &quot;user id&quot; (USER) -->\\n\",\n       \"<path d=\\\"M164 104.5 C135 79 144.67 53.5 106 53.5\\\" fill=\\\"none\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"<polygon points=\\\"106 53.5 118 47.5 114 53.5 118 59.5\\\" fill=\\\"#060100\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"<circle cx=\\\"164\\\" cy=\\\"104.5\\\" r=\\\"1.5\\\" stroke=\\\"#060100\\\" stroke-width=\\\"1.5\\\" fill=\\\"#060100\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **AUTHENTICATION** (<u>email</u>, password hash, salt, user id)\\n\",\n       \"- **USER** (<u>user id</u>, name, pseudo, email)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE AUTHENTICATION (\\n\",\n       \"  PRIMARY KEY (email),\\n\",\n       \"  email         VARCHAR(255) NOT NULL,\\n\",\n       \"  password_hash BINARY(64),\\n\",\n       \"  salt          BINARY(16),\\n\",\n       \"  user_id       VARCHAR(42)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"CREATE TABLE USER (\\n\",\n       \"  PRIMARY KEY (user_id),\\n\",\n       \"  user_id VARCHAR(8) NOT NULL,\\n\",\n       \"  name    VARCHAR(100),\\n\",\n       \"  pseudo  VARCHAR(100),\\n\",\n       \"  email   VARCHAR(42)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t mld sql --colors mondrian --select all\\n\",\n    \":\\n\",\n    \"USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)], #email > AUTHENTICATION > email\\n\",\n    \":\\n\",\n    \"AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)], #user id > USER > user id\\n\",\n    \":\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Autres sorties relationnelles\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Graphe des dépendances\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La table A **dépend** de la table B lorsque A possède une clé étrangère qui est clé primaire de B. Cette notion est utile dans le cas où l'on doit importer une base de données à partir d'un ensemble de fichiers CSV (ou autres). Si l'on veut éviter de perdre le bénéfice du contrôles de clés étrangères (en faisant, p. ex. sous MySQL, `SET FOREIGN_KEY_CHECKS = 0`), il conviendra de lire ces fichiers dans un [ordre topologique](https://fr.wikipedia.org/wiki/Tri_topologique) quelconque. Mocodo peut générer un graphe des dépendances qui met cet ordre en évidence :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 79,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_dependencies.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjE5MnB0IiBoZWlnaHQ9IjE4OHB0Igogdmlld0JveD0iMC4wMCAwLjAwIDE5MS43NSAxODguMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTg0KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTg0IDE4Ny43NSwtMTg0IDE4Ny43NSw0IC00LDQiLz4KPCEtLSBDbGllbnQgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+Q2xpZW50PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI3Ny41LC0xODAgMTguNzUsLTE4MCAxOC43NSwtMTQ0IDc3LjUsLTE0NCA3Ny41LC0xODAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDguMTIiIHk9Ii0xNTcuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q2xpZW50PC90ZXh0Pgo8L2c+CjwhLS0gQ29tbWFuZGUgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+Q29tbWFuZGU8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9Ijk2LjI1LC0xMDggMCwtMTA4IDAsLTcyIDk2LjI1LC03MiA5Ni4yNSwtMTA4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQ4LjEyIiB5PSItODUuMzMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q29tbWFuZGU8L3RleHQ+CjwvZz4KPCEtLSBDbGllbnQmIzQ1OyZndDtDb21tYW5kZSAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5DbGllbnQmIzQ1OyZndDtDb21tYW5kZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik00OC4xMiwtMTQzLjdDNDguMTIsLTEzNi40MSA0OC4xMiwtMTI3LjczIDQ4LjEyLC0xMTkuNTQiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTEuNjMsLTExOS42MiA0OC4xMywtMTA5LjYyIDQ0LjYzLC0xMTkuNjIgNTEuNjMsLTExOS42MiIvPgo8L2c+CjwhLS0gSW5jbHVyZSAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5JbmNsdXJlPC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxMzEuMjUsLTM2IDY1LC0zNiA2NSwwIDEzMS4yNSwwIDEzMS4yNSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTguMTIiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5JbmNsdXJlPC90ZXh0Pgo8L2c+CjwhLS0gQ29tbWFuZGUmIzQ1OyZndDtJbmNsdXJlIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPkNvbW1hbmRlJiM0NTsmZ3Q7SW5jbHVyZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik02MC40OCwtNzEuN0M2Ni4xOCwtNjMuNzMgNzMuMDUsLTU0LjEgNzkuMzYsLTQ1LjI2Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjgyLjA2LC00Ny41MSA4NS4wMywtMzcuMzQgNzYuMzcsLTQzLjQ0IDgyLjA2LC00Ny41MSIvPgo8L2c+CjwhLS0gUHJvZHVpdCAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5Qcm9kdWl0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNzUsLTEwOCAxMTQuNSwtMTA4IDExNC41LC03MiAxODMuNzUsLTcyIDE4My43NSwtMTA4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE0OS4xMiIgeT0iLTg1LjMzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlByb2R1aXQ8L3RleHQ+CjwvZz4KPCEtLSBQcm9kdWl0JiM0NTsmZ3Q7SW5jbHVyZSAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5Qcm9kdWl0JiM0NTsmZ3Q7SW5jbHVyZTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMzYuNTIsLTcxLjdDMTMwLjcxLC02My43MyAxMjMuNywtNTQuMSAxMTcuMjYsLTQ1LjI2Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjEyMC4yLC00My4zNSAxMTEuNDgsLTM3LjMzIDExNC41NCwtNDcuNDcgMTIwLjIsLTQzLjM1Ii8+CjwvZz4KPC9nPgo8L3N2Zz4K\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t dependencies --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Même si un tel graphe n'est pas forcément [sans circuits](https://fr.wikipedia.org/wiki/Graphe_orienté_acyclique), remplir les tables dans le sens de lecture des langues latines minimisera le recours à la désactivation des contraintes de clés étrangères.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Diagramme relationnel / DDL BDML\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"D'après [son site officiel](https://dbml.dbdiagram.io) :\\n\",\n    \"\\n\",\n    \"> DBML (_Database Markup Language_) est un DSL (langage dédié) open-source conçu pour définir et documenter les schémas et structures de base de données. Il vise la simplicité, la cohérence et la lisibilité.\\n\",\n    \"\\n\",\n    \"Mocodo parle maintenant DBML :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 80,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_ddl.dbml\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```dbml\\n\",\n       \"Table \\\"Client\\\" {\\n\",\n       \"  \\\"Réf. client\\\" VARCHAR(8) [pk, NOT NULL]\\n\",\n       \"  \\\"Nom\\\"         VARCHAR(255)\\n\",\n       \"  \\\"Prénom\\\"      VARCHAR(255)\\n\",\n       \"  \\\"Adresse\\\"     VARCHAR(255)\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"Table \\\"Commande\\\" {\\n\",\n       \"  \\\"Num. commande\\\" VARCHAR(8) [pk, NOT NULL]\\n\",\n       \"  \\\"Date\\\"          DATE\\n\",\n       \"  \\\"Montant\\\"       DECIMAL(10,2)\\n\",\n       \"  \\\"Réf. client\\\"   VARCHAR(8) [NOT NULL]\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"Table \\\"Inclure\\\" {\\n\",\n       \"  \\\"Num. commande\\\" VARCHAR(8) [NOT NULL]\\n\",\n       \"  \\\"Réf. produit\\\"  VARCHAR(8) [NOT NULL]\\n\",\n       \"  \\\"Quantité\\\"      INTEGER\\n\",\n       \"  Indexes {\\n\",\n       \"    (\\\"Num. commande\\\", \\\"Réf. produit\\\") [pk]\\n\",\n       \"  }\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"Table \\\"Produit\\\" {\\n\",\n       \"  \\\"Réf. produit\\\"  VARCHAR(8) [pk, NOT NULL]\\n\",\n       \"  \\\"Libellé\\\"       VARCHAR(50)\\n\",\n       \"  \\\"Prix unitaire\\\" DECIMAL(10,2)\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"Ref:\\\"Commande\\\".\\\"Réf. client\\\" > \\\"Client\\\".\\\"Réf. client\\\"\\n\",\n       \"Ref:\\\"Inclure\\\".\\\"Num. commande\\\" > \\\"Commande\\\".\\\"Num. commande\\\"\\n\",\n       \"Ref:\\\"Inclure\\\".\\\"Réf. produit\\\" > \\\"Produit\\\".\\\"Réf. produit\\\"\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t dbml --title CCP\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"À notre connaissance, il n'existe pas actuellement d'API publique de rendu des diagrammes DBML. Pour les visualiser, copiez-collez la sortie sur [Dbdiagram.io](https://dbdiagram.io/d/651077feffbf5169f065359b), ou installez un [plugin VS-Code](https://marketplace.visualstudio.com/items?itemName=nicolas-liger.dbml-viewer) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 81,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"1281.965\\\" height=\\\"174.5\\\"><style>@font-face{font-family:'Open Sans'}</style><svg x=\\\"251.392\\\" y=\\\"27.5\\\" width=\\\"67\\\" height=\\\"147\\\"><path d=\\\"M4 22h15q10 0 10 10v79q0 10 10 10h15-15q-10 0-10-10V32q0-10-10-10H4m10-4v8m40 91-10 4 10 4\\\" fill=\\\"none\\\" stroke=\\\"#9B9CA4\\\"/><text x=\\\"7\\\" y=\\\"19\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">1</text><text x=\\\"43.289\\\" y=\\\"118\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">*</text></svg><svg x=\\\"603.446\\\" y=\\\"27.5\\\" width=\\\"67\\\" height=\\\"48\\\"><path d=\\\"M4 22h50H4m10-4v8m40-8-10 4 10 4\\\" fill=\\\"none\\\" stroke=\\\"#9B9CA4\\\"/><text x=\\\"7\\\" y=\\\"19\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">1</text><text x=\\\"43.289\\\" y=\\\"19\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">*</text></svg><svg x=\\\"955.5\\\" y=\\\"27.5\\\" width=\\\"67\\\" height=\\\"81\\\"><path d=\\\"M4 55h15q10 0 10-10V32q0-10 10-10h15-15q-10 0-10 10v13q0 10-10 10H4m0-4 10 4-10 4m40-41v8\\\" fill=\\\"none\\\" stroke=\\\"#9B9CA4\\\"/><text x=\\\"7\\\" y=\\\"52\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">*</text><text x=\\\"42.995\\\" y=\\\"19\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:14px;font-weight:400;fill:transparent\\\">1</text></svg><svg><path fill=\\\"#222\\\" d=\\\"M0 0h255.392v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#fff\\\">CLIENT</text></svg><svg y=\\\"33\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h255.392v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#d7d7d9\\\">Réf. client</text><path fill=\\\"#D7D7D9\\\" d=\\\"M85.43 10.734a2.953 2.953 0 1 1-1.101 5.695l-.869.868h-.656v.984h-.984v.985H79.85v-1.97l2.752-2.75a2.953 2.953 0 0 1 2.826-3.81zm0-.984a3.937 3.937 0 0 0-3.901 4.477l-2.518 2.518a.493.493 0 0 0-.144.348v2.665c0 .272.22.492.492.492h2.953c.272 0 .492-.22.492-.492v-.492h.492c.272 0 .493-.22.493-.493v-.41l.82-.823a3.937 3.937 0 1 0 .82-7.79zm0 2.953a.984.984 0 1 0 1.968 0 .984.984 0 0 0-1.969 0z\\\"/><path fill=\\\"#666\\\" d=\\\"M223.392 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M232.203 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.942v-9h1.162l4.732 7.535h.041a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.011-.856V10.5h.953v9zM241.392 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.028.527.036.819.011.287.017.58.017.88V19.5h-.941v-9h1.162l4.731 7.535h.042a158.366 158.366 0 0 1-.065-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.953v9z\\\"/><text x=\\\"139.367\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#999\\\">VARCHAR(8)</text></svg><svg y=\\\"66\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h255.392v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Nom</text><text x=\\\"157.414\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">VARCHAR(255)</text></svg><svg y=\\\"99\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h255.392v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Prénom</text><text x=\\\"157.414\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">VARCHAR(255)</text></svg><svg y=\\\"132\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h255.392v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Adresse</text><text x=\\\"157.414\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">VARCHAR(255)</text></svg><svg x=\\\"305.392\\\"><path fill=\\\"#222\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#fff\\\">COMMANDE</text></svg><svg x=\\\"305.392\\\" y=\\\"33\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#d7d7d9\\\">Num. commande</text><path fill=\\\"#D7D7D9\\\" d=\\\"M132.09 10.734a2.953 2.953 0 1 1-1.1 5.695l-.868.868h-.656v.984h-.985v.985h-1.968v-1.97l2.751-2.75a2.953 2.953 0 0 1 2.827-3.81zm0-.984a3.937 3.937 0 0 0-3.9 4.477l-2.518 2.518a.493.493 0 0 0-.144.348v2.665c0 .272.22.492.493.492h2.953c.271 0 .492-.22.492-.492v-.492h.492c.272 0 .492-.22.492-.493v-.41l.822-.823a3.937 3.937 0 1 0 .82-7.79zm0 2.953a.984.984 0 1 0 1.97 0 .984.984 0 0 0-1.97 0z\\\"/><path fill=\\\"#666\\\" d=\\\"M270.054 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M278.865 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.027.527.035.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.012-.856V10.5h.954v9zM288.054 19.5h-1.168l-4.75-7.56h-.047l.041.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a158.366 158.366 0 0 1-.066-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.954v9z\\\"/><text x=\\\"186.028\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#999\\\">VARCHAR(8)</text></svg><svg x=\\\"305.392\\\" y=\\\"66\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Date</text><text x=\\\"260.017\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">DATE</text></svg><svg x=\\\"305.392\\\" y=\\\"99\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Montant</text><text x=\\\"203.548\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">DECIMAL(10,2)</text></svg><svg x=\\\"305.392\\\" y=\\\"132\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Réf. client</text><path fill=\\\"#666\\\" d=\\\"M270.054 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M278.865 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.027.527.035.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.012-.856V10.5h.954v9zM288.054 19.5h-1.168l-4.75-7.56h-.047l.041.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a158.366 158.366 0 0 1-.066-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.954v9z\\\"/><text x=\\\"190.941\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">VARCHAR(8)</text></svg><svg x=\\\"657.446\\\"><path fill=\\\"#222\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#fff\\\">INCLURE</text></svg><svg x=\\\"657.446\\\" y=\\\"33\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#d7d7d9\\\">Num. commande</text><path fill=\\\"#D7D7D9\\\" d=\\\"M132.09 10.734a2.953 2.953 0 1 1-1.1 5.695l-.868.868h-.656v.984h-.985v.985h-1.968v-1.97l2.751-2.75a2.953 2.953 0 0 1 2.827-3.81zm0-.984a3.937 3.937 0 0 0-3.9 4.477l-2.518 2.518a.493.493 0 0 0-.144.348v2.665c0 .272.22.492.493.492h2.953c.271 0 .492-.22.492-.492v-.492h.492c.272 0 .492-.22.492-.493v-.41l.822-.823a3.937 3.937 0 1 0 .82-7.79zm0 2.953a.984.984 0 1 0 1.97 0 .984.984 0 0 0-1.97 0z\\\"/><path fill=\\\"#666\\\" d=\\\"M270.054 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M278.865 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.027.527.035.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.012-.856V10.5h.954v9zM288.054 19.5h-1.168l-4.75-7.56h-.047l.041.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a158.366 158.366 0 0 1-.066-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.954v9z\\\"/><text x=\\\"186.028\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#999\\\">VARCHAR(8)</text></svg><svg x=\\\"657.446\\\" y=\\\"66\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#d7d7d9\\\">Réf. produit</text><path fill=\\\"#D7D7D9\\\" d=\\\"M97.502 10.734a2.953 2.953 0 1 1-1.1 5.695l-.868.868h-.657v.984h-.984v.985h-1.969v-1.97l2.752-2.75a2.953 2.953 0 0 1 2.826-3.81zm0-.984a3.937 3.937 0 0 0-3.9 4.477l-2.518 2.518a.493.493 0 0 0-.144.348v2.665c0 .272.22.492.492.492h2.953c.272 0 .492-.22.492-.492v-.492h.493c.271 0 .492-.22.492-.493v-.41l.821-.823a3.937 3.937 0 1 0 .82-7.79zm0 2.953a.984.984 0 1 0 1.97 0 .984.984 0 0 0-1.97 0z\\\"/><path fill=\\\"#666\\\" d=\\\"M270.054 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M278.865 19.5h-1.168l-4.75-7.56h-.047l.042.69c.016.254.027.527.035.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.012-.856V10.5h.954v9zM288.054 19.5h-1.168l-4.75-7.56h-.047l.041.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.941v-9h1.162l4.731 7.535h.042a158.366 158.366 0 0 1-.066-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.954v9z\\\"/><text x=\\\"186.028\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#999\\\">VARCHAR(8)</text></svg><svg x=\\\"657.446\\\" y=\\\"99\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h302.054v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Quantité</text><text x=\\\"239.552\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">INTEGER</text></svg><svg x=\\\"1009.5\\\"><path fill=\\\"#222\\\" d=\\\"M0 0h267.465v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#fff\\\">PRODUIT</text></svg><svg x=\\\"1009.5\\\" y=\\\"33\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h267.465v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#d7d7d9\\\">Réf. produit</text><path fill=\\\"#D7D7D9\\\" d=\\\"M97.502 10.734a2.953 2.953 0 1 1-1.1 5.695l-.868.868h-.657v.984h-.984v.985h-1.969v-1.97l2.752-2.75a2.953 2.953 0 0 1 2.826-3.81zm0-.984a3.937 3.937 0 0 0-3.9 4.477l-2.518 2.518a.493.493 0 0 0-.144.348v2.665c0 .272.22.492.492.492h2.953c.272 0 .492-.22.492-.492v-.492h.493c.271 0 .492-.22.492-.493v-.41l.821-.823a3.937 3.937 0 1 0 .82-7.79zm0 2.953a.984.984 0 1 0 1.97 0 .984.984 0 0 0-1.97 0z\\\"/><path fill=\\\"#666\\\" d=\\\"M235.465 7h20s2 0 2 2v12s0 2-2 2h-20s-2 0-2-2V9s0-2 2-2\\\"/><path fill=\\\"#D7D7D9\\\" d=\\\"M244.277 19.5h-1.168l-4.75-7.56h-.047c.011.202.025.431.041.69.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.942v-9h1.162l4.732 7.535h.042a157.13 157.13 0 0 1-.066-1.465 33.296 33.296 0 0 1-.012-.856V10.5h.954v9zM253.465 19.5h-1.168l-4.749-7.56h-.048l.042.69c.016.254.028.527.036.819.012.287.018.58.018.88V19.5h-.942v-9h1.162l4.732 7.535h.041a158.366 158.366 0 0 1-.065-1.465 33.065 33.065 0 0 1-.012-.856V10.5h.953v9z\\\"/><text x=\\\"151.44\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;font-weight:700;fill:#999\\\">VARCHAR(8)</text></svg><svg x=\\\"1009.5\\\" y=\\\"66\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h267.465v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Libellé</text><text x=\\\"176.92\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">VARCHAR(50)</text></svg><svg x=\\\"1009.5\\\" y=\\\"99\\\"><path fill=\\\"#37383F\\\" d=\\\"M0 0h267.465v33H0z\\\"/><text x=\\\"10\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#d7d7d9\\\">Prix unitaire</text><text x=\\\"168.96\\\" y=\\\"19.75\\\" style=\\\"font-family:&quot;Open Sans&quot;,sans-serif;font-size:13px;fill:#999\\\">DECIMAL(10,2)</text></svg></svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"execution_count\": 81,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.SVG(\\\"../examples/dbml.svg\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Diagramme relationnel D2\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"[D2](https://d2lang.com) est un langage de description de diagrammes de différents types. La prise en charge des diagrammes relationnels est minimale, mais le projet est jeune (actuellement en version 0.6.1, open source depuis novembre 2022). Son point fort est TALA, son algorithme de plongement **propriétaire**, que vous pouvez tester [ici](https://play.d2lang.com/?script=1JVBb9owFMfv-RRPOW0HOKBWmqg0KaLZlgkS5oZKVVVVHjWTt8QOjjmgivv4Js3n8BebYljjBDBh7NJj5Pzfe3-_n99zvTsvjDvXKApitw_PDoAuqg_5PHmU-HtCHAA3xVLQ6SIhbh9uPTT44qF3F7338Fy1oA_3maApFsvHX2R5BTMuCP3Byo-HVRmD8RTwEjPZeRKcSiNS7_KyEcqIpLUJJcyWOoxiCCfD4cpZOY47iEbj6MZHFkNCFbMuZFS9TAlMeZrxXBWmuw-nmdsTDzN5RsD5AjNJpSrcPgRh7H_2kfZ2rdZjD8X-yA9tDWOLtAtPqsiwkCQlTFoqaV522agD0rJTugx_NB5Gd2p9LjP7cpM0S_hSO6_lPdHWvXGnV6-EPGwQ-RRNUBjYCNGpMsF_EmuS9lj8exRdSs6nVBWydi2nMiVVATO-EIySBlbjQP0e-C0fzAksJbQci6rYVV70NiSNUfTVP4ry0UbsA2lH9BejVzRBkDzjLC9zWUdbjSW3BMndkoT8bxO1Rm-FJc2AIPMFzZsM3ESDQK1j66NujWKzHwLTnDMtxc273g0MqXoRVpeHGxIj79YLhkPr_P8vC-3srpblmgu4a9QFnY9QjVnzxFhw3UOLTKu3j7r-01G53ltWvVHV7kDWytqW2vdXNYG7tXvc5N2MhPqJqajVYy21kaUiV6sq4nfOnaqK_dPC1p9qJrR3Z2ra-zvsYPuEjvs03ktb_mqSlgb_BAAA__8%3D&layout=tala&theme=5&sketch=0&). Celui-ci requérant une licence payante, si vous déférez le rendu, c'est le plongement par défaut (Dagre, celui de Mermaid) qui sera utilisé.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 82,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_ddl.d2\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```d2\\n\",\n       \"\\\"Client\\\": { shape: sql_table\\n\",\n       \"  \\\"Réf. client\\\": VARCHAR(8) {constraint: PK}\\n\",\n       \"  \\\"Nom\\\":         VARCHAR(255) \\n\",\n       \"  \\\"Prénom\\\":      VARCHAR(255) \\n\",\n       \"  \\\"Adresse\\\":     VARCHAR(255) \\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Commande\\\": { shape: sql_table\\n\",\n       \"  \\\"Num. commande\\\": VARCHAR(8) {constraint: PK}\\n\",\n       \"  \\\"Date\\\":          DATE \\n\",\n       \"  \\\"Montant\\\":       DECIMAL(10,2) \\n\",\n       \"  \\\"Réf. client\\\":   VARCHAR(8) {constraint: [FK; NOT NULL]}\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Inclure\\\": { shape: sql_table\\n\",\n       \"  \\\"Num. commande\\\": VARCHAR(8) {constraint: [PK; FK]}\\n\",\n       \"  \\\"Réf. produit\\\":  VARCHAR(8) {constraint: [PK; FK]}\\n\",\n       \"  \\\"Quantité\\\":      INTEGER \\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Produit\\\": { shape: sql_table\\n\",\n       \"  \\\"Réf. produit\\\":  VARCHAR(8) {constraint: PK}\\n\",\n       \"  \\\"Libellé\\\":       VARCHAR(50) \\n\",\n       \"  \\\"Prix unitaire\\\": DECIMAL(10,2) \\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Commande\\\".\\\"Réf. client\\\" -> \\\"Client\\\".\\\"Réf. client\\\"\\n\",\n       \"\\\"Inclure\\\".\\\"Num. commande\\\" -> \\\"Commande\\\".\\\"Num. commande\\\"\\n\",\n       \"\\\"Inclure\\\".\\\"Réf. produit\\\" -> \\\"Produit\\\".\\\"Réf. produit\\\"\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t d2\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 83,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_ddl.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIGQyVmVyc2lvbj0idjAuNi4zIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0IiB2aWV3Qm94PSIwIDAgMTAyNyA5MDYiPjxzdmcgaWQ9ImQyLXN2ZyIgY2xhc3M9ImQyLTE1NjM3MTc5MTEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiIgdmlld0JveD0iLTEwMSAtMTAxIDEwMjcgOTA2Ij48cmVjdCB4PSItMTAxLjAwMDAwMCIgeT0iLTEwMS4wMDAwMDAiIHdpZHRoPSIxMDI3LjAwMDAwMCIgaGVpZ2h0PSI5MDYuMDAwMDAwIiByeD0iMC4wMDAwMDAiIGNsYXNzPSIgZmlsbC1ONyIgc3Ryb2tlLXdpZHRoPSIwIiAvPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbCi5kMi0xNTYzNzE3OTExIC50ZXh0IHsKCWZvbnQtZmFtaWx5OiAiZDItMTU2MzcxNzkxMS1mb250LXJlZ3VsYXIiOwp9CkBmb250LWZhY2UgewoJZm9udC1mYW1pbHk6IGQyLTE1NjM3MTc5MTEtZm9udC1yZWd1bGFyOwoJc3JjOiB1cmwoImRhdGE6YXBwbGljYXRpb24vZm9udC13b2ZmO2Jhc2U2NCxkMDlHUmdBQkFBQUFBQkZZQUFvQUFBQUFHaVFBQWd1RkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQlBVeTh5QUFBQTlBQUFBR0FBQUFCZ1hkL1ZvMk50WVhBQUFBRlVBQUFBd2dBQUFRd0Z3QWQyWjJ4NVpnQUFBaGdBQUFwZEFBQU9LT2haMmp4b1pXRmtBQUFNZUFBQUFEWUFBQUEyRzRVZTMyaG9aV0VBQUF5d0FBQUFKQUFBQUNRS2hBWDFhRzEwZUFBQUROUUFBQUMyQUFBQXpGMjNDeUJzYjJOaEFBQU5qQUFBQUdnQUFBQm9XWlpkR20xaGVIQUFBQTMwQUFBQUlBQUFBQ0FBU3dEMmJtRnRaUUFBRGhRQUFBTWpBQUFJRkFiRFZVMXdiM04wQUFBUk9BQUFBQjBBQUFBZy85RUFNZ0FEQWdrQmtBQUZBQUFDaWdKWUFBQUFTd0tLQWxnQUFBRmVBRElCSXdBQUFnc0ZBd01FQXdJQ0JHQUFBdmNBQUFBREFBQUFBQUFBQUFCQlJFSlBBRUFBSVAvL0F1Ny9CZ0FBQTlnQkVTQUFBWjhBQUFBQUFlWUNsQUFBQUNBQUEzaWNoTTFMSzRSaEhNYmg2eld2Y1JybjgvbkJZSVl4cEpTTmhheGtKOW5icUNrTEtlVkxpV1R0OEZFc3JTVTdmeG4yYzIvdXpWVS9aQW95bE9TL3B5eko1WktxbXJwdE8zYnRPM1RzMUxtR1M5ZHV2RWNncVRUVjFyODZjT1RFbVlZTFYzOHEzaFJsOFIxZjhSa2Y4Um92OFJ4UDhSZ1BjUjkzY1J0N3pYN3JaZW8yYmFoWlZWRzFabDJiZ2x5N29nNmR1blRyVWRLclQ3OEJnNFlNR3pGcXpMZ0prNlpNbXpGcnpyeGt3YUlsWmN0VytBRUFBUC8vQVFBQS8vOUhIQzRmQUFCNG5IU1dmV3diOWYzSFA5K3ZIVi9UT0UwdTl2bnN4STd0dTlZWHgwNmMrT3c3SjNiT2laK1Nwa21jMkVrYkp5UjlJRzJTcHUydlRYKzBhaHRhb1phMmdnTG1TU0JXdXJJaEFkdlltSkNBQ2UyUElhaTY4VENHRUF4RUs4UWZGUnFEalNqVFJpSG42YzVPR3RENHkxSDA5ZWZoL1hsOTN2NUFHZVFBY0JBL0Fob29oeXFvQVFxQUo1M2tKaWZIc1lUSWl5SkxhMFFPa1VRT2ZTTG5FZG9jMEFxQ3RqWDJSZXpZcVZObzlDUitaSGxmKzVucDZUY21qeDZWNzd2eHVleEg3M3dPR0RRQTJJYnpVQTRrZ0lIZ09aZUxZM1U2allFM3NCeEx2R2wvdzE3anFOWldPVDYrUG5rOUovMGppdjV2YWtyYzM5YTJYeDdEK2VXRFY2OENBQ0FJRkpad0hiNElOb0F5eHVVS0JnU0I5NXRvd3VWaUdaMk9NcHBNdkY4UWFaME9aVEozYmVrN2s0M2NabTJxalRWS0U3eC9YUEwxMnB1NVhmcWh4K2YyUHA1cGRRaFdwdXRJSm5NczFzQUVtdndBZ0dFTUFBZHdIdFlwZGZJazd6ZFJSaDNMOFg0aEdIQ3g3TmpUajE5Njh0R1JMWWNQSHo2OEJlZWZ1L2prcnhQM0xpemNyZFkyQm9DdTR6eFVxSnBSVG9xbldNcEpqYUhqOGtmZmZJTmFjVDcxVHZkWDNhdHYzMWYxdVBXV1ZGL2V2SW56cWVzcCtlUFZmbDM0SWpoK3JGK2wzU0FiNUVtZER0MjI5V3pmd1BsdGlRbHJzeVhtaiswS0hwcGxPdzMzZm1pZkxiWE0xd3UxRzd1T1pCWWVwR3ArbVpULzd2U1Vhc0grbGJxVmFmTWtTenJKc1N4cUhSNlcvNHp6OHBmSXNId1FCZVUzVjJxSDUzRmVtYW55Zml5ckRLZ1VKNHJ6b0MvK24wYzhZV0ExQkRXVzFTQnk4dTB2SjE0L2hQUHl5Mmp6VFhrdkdybjczUlVkM3NKNUtDdmxwc2F5eUk3enl5OTN3MG91ZkNmT0svUG1TZDVnTXRHOElJZ0dwY0tBSUxLRWh0VndyTWxFa1dOVEovVzBYcXVuOUF1N0I5WnB0SUVGY1NHZzFSQTRMLytNU1RKTWtrR1R5d2ZSckhmTzg2ajhLelQ4cUdmT0t6KzJtcU1KNThGUXpFSHpMbGRRMFdBbDh0WXZ1N1VhSXIzMXEyNnRWb2szZGQ0L0YwRFo1WVBveVhPdE13SDVPY0RxbkhiamkxRDFBeklWZkhTY1gxRHhZVlJBVVYvbVZIZjNxVXoyWkUvUHlXeDRXOHZlMGRHOUxhUDY0U2RtWng4YkducHNkdmFKNGMzeFk1bmo5OTkvUEhNc0RxdGNWcWd6TXBhNFZNRmtTWElWelZkN0QwaG45KzNidFRXN2Jlc2t6bThjNlptZWtyOURQVjJwYmxHTkVTaU00OFA0SWxSQ0k4Q203OVZVeHJpNFpyeTJadUxXSnZXdDFvZzA0OGR0M2ZzaXhlcmJaMUwwU05ERVZGWlgrZHZpSjRhVmdvZFB4Sy9uNHV0SEg5cFI3R1V5bjlON3ZHWGFUbDM1YWg4T25JY05RSy9wUStGa2JTdHZ4MmZDZzRsbkppOGRQZENmeWZRZndIbDJLTkUzUWNxZklVcitBdVdpblYyQkloOVdBUFFkemdPaFJHT0RUb29sUDd1Q1ByMkNlMU9wNVplS2I3WVZsbkF6eml0ZXBrNkc1TW1pVHdqcW56b2Rpc2ZucEt3NzZmR20zSVBTWHIyd01JdnVrdTlNajd0YzQybDBXajQxdXlBQVVnZWh3WG1vQk9BMWExalV2UGRlYnJhbXpxQ3RzWkt6SSsvaXZIeXBmWGQ3Kys1MnRHdjVZSkVOOUZ1MENMV3dFWUJtRkRURWdMckFCS2NLVHBHc1lvYWNzc3JxVXIvV01mVEFUMGhQUTJPdnpjSGMzcDRiVEJBYVpzakVTdXl4blg3OTVxN0JFZEllWWgzR05wTjcvN2o4UWJ1MU1jYll6MVZGZk81TmdDRlRXRUxmNHF0Z0tMa0d4eElzeVZORU1WZVJ4K0xvQ2Nwa1FtNW1zME5EeERMWW1XN1l2aXU4UFJWSmg1UDJUdFlSMVR0dGZuejF0VkViZC9aUTlvaVVuQjRidkoxeEZLeDBVZGZtd2hMNkRWcFVadkRqM3FRQVZOTTVFK21hazFxU2xrYktaL01tdVd5Y2FUZHRkQTdxSS9PRG1ma0lRd3NHczI4a2xKMjJHVVdiVStIRVYxaENINjMwVU5STURjNEYrUld4eE9CcW92K01Id2p2RkJzbGh6YWJJRFRXUGt0bnhONVd6MFZkS2YzZHg5S0hwZnJhN0t2TG9UYXJPeG1YcmJRdkc5cDJPMkMxL2oraFJUQ0QvWHNkS0VBNlYvSFhPRldwRU4yMVY0cE9pUk83RVpaZktkdVdZc04xTm52NlRhU050dkZEK283NTlPQzh0REJUYVNudnY0MGlCV005Y3ZYMnAxV2Q2Z0ZRRkw5Zi9DMWxnMkl3VU5LSlpTalY5M2ZFWXNuTmRHTjFUWjAxTVQyTmZpNlY5ZmR1S3llaStzbit1RHdCVUNoQUVnQmV4QzloRjdRQWdBNWFGNG96eUJTVzRLLzRLbFFWVlZMUkxoWCtYTE03czZGY1N4QVY2MHo2dGlEZXMveUlnVVJJMG1xVjd3SGdyOUVpT05VdFZFQldTbHFoa1ZSYUpsWS9Nd2xDNCtqemhLSlZyZ0h2bHMwWmI3T1F5SGg5UWdMZFNMRytWcTg3c0hOQ2ZndTVFOUlXK1hMcG81Z0RmWWdXUzQ1VnlyRVNYVmNNeXc3NCs3c3ozcFpONFUxcXNKVkFyazN5WlNqTjZKOW9FYXFnN24vNjZxcUZvYXJ3ZERRNkhZN3NpVWIzUktMOS9WRnBZS0RFVjJRK016Z2ZTVXhuaDJkbWhyUFRvTzRJajc1Rml5VytibFZuMU9sWXhzWFJsR0h0amlpVk90T2V5VjNoN1NFbXp1Q2o2b3BFTnpxbHQvR0xJV3ZEdVVPWkkxSjk3Y2pUU1BlREhWRTBtRVNMcFd1aW1LVzBJVVVCTEQxdUcxMnROMWJaNHhaMFk3UlpXTitqMWZvbHVYVHZXQXRMNkRSYVZCeWJabHljcUdJWkRMaEtkbjFyM3hRWHArdXgwc0JmQXBPczI1SHd0TFE0K1RvbTFwaExOdzFZR3l5Q285bFQzMUxISnByY2FUMW5GUzNPSnJ1Rm9kZFhPb1B1Y05wQkJ3em1SaXR0b3lvcW5XSXpGMnRRODVzTFN5aUpEeWh1cmZMRkJrV1JWNkZkNWV5TGdZNmV2dlhKMDZlZGpaWDErbXFqVHovV2d5cWxzdlBuNC9KaVUydTVWaUlxMUZoYkNrdm9IWFJENGVGN3JKS2xsZjYwdnlmcmFYR0ZHVVVYcGsrL2N3SUY1QThURXVkQk9ibTJyNkVGRUd3QVFDK2dHMkFCNEVXT3Awc21MUElFelpadVNvTFk4Tk9IYzEwVjVrcHRoYWtpdlBYaFM3bnV5dG9OMmtxelBpWi9QbWRvTkJvYkRYTmYvK3VReVV0Ukh2cVF1bCtxRjJncXNVdUpEQVQ0MFRyMTk4cGJXRUp2NEh1Z1lrV0JRQW1UdGV4OXMyUC8vaDNiOSsvZkhrb2tRcUZrVXYvODVhZWVmZmFweTgvSFRsMjRjT0xFaFF1bjFQN1RBT2hsZkZLOWp4UWJDd3FDeUpNOGxYN28vNzFkdGRFekNmUkJjQjFkdlh3bFVaejlSZ0QwT3I1SElaOFBTcmlFSTdjS3FtTG9QTld3NDJ3cTB0R1FzUG9heHFYY252Z2RmYlVoeSs5YWR6eDRCeSttbWh3K2IzQjZKSExpWEJwcnV3R0JwYkNFL29CUGxsejFGazlxWklPVFlvbGI2L1czdmlsbmc2MHZGQjdxbFp3K201ZEMwWCtUZExOTnpBa2R1L1NDVTdBMnBlT3hYcVBCaXZqdTMrczNlRWFUeVozS0dRMGFjQmVXMEZWOEQ5akJDMjFxTG5WekZjKys1Ykk2Z2lvU3ExbDdpMmhLZ0t2T2ZqTXlLYkppUFN1MFpQanNUbXVEMGVaMzhCT2tnMjBQZXNQdVJGa28yWkp1ZHZGcGZkT2d2N0dydFZwcjZmRzM5cnAzOURyRHZpcHR0YmZENHh0b1FqTzJUdFlYQy9sY2ZsYStFbTExQjF3MWxwUTNtQ3pxM0ZWWWdsZGdYcmwvMTA3NFRndkxXc3dzcTJmcmJDeHJxMk9WdDc3Q1ZyZ0M4MUFEUUhPQ3dPa1lkczFYNGtaUEM4STZiR1kzV2h5YlVyOW9NVVFia00xYVp3ODBkZTRzK2ZVZ0tzZWZLRGNFclVxaGJCQmxOTkVmU0ttVXhMZTN0Ylcvc1B2YW1UUFhwOHpicjgzUFg5c09DRnlGUWJoVytnNm5LcVhNalRMcWN1cDdYa3FsWGlpOU5rOWRQM1BtV3RGMzRHbDBZK1ZHejJUUURia1dVT0dQdUJkRS9KTFNLN21tY0xQZGJqYmI3YmpYWmpIWDE1c3ROZ0JVdUlvNzRBRk5wUkpEdzRuMGhzYjcybkdIK3hrUi9nc0FBUC8vQVFBQS8vL0szeE16QUFBQUFBRUFBQUFDQzRWRk9ObTFYdzg4OVFBREErZ0FBQUFBMkYyZ29RQUFBQURkWmk4Mi9qcisyd2h2QThnQUFBQURBQUlBQUFBQUFBQUFBUUFBQTlqKzd3QUFDSmorT3Y0NkNHOEFBUUFBQUFBQUFBQUFBQUFBQUFBQUFETjRuQ3pMTVVvRFVSUkc0ZlAvVTlocEd5R0VnRUVJU2w3ekVFUXNSS3dzaE51STF3V0lDeEViN2UzZGgvVzRBbmRnS2I0bW1HcUVJZFVwRHA5ZnVhTUh6K2w4UnZVRDZUMVNQNlFmcVg0aHRVUDZrdFEzNlMvU3o2VGZxRDdaOXBUMGhLbWZ1SFVIK3FONlNhaG41U09LZmxscHdZdzFWd3hFZDA3NGdQQnMvS0Y3UXU5TUZVdzg1MW9mN0k2bWNhekdqUm9MTmZiVldMTGhnZzFGaFZEaGtEVUJ3eWNNL1Q4QUFBRC8vd0VBQVAvLzF5VXBHQUFBQUFBQUxBQXNBRkFBZ0FDZUFMUUF5QUQ2QVJJQkhnRTRBVWdCZWdHY0Fjd0I3Z0l3QWxnQ2FnS09BcW9DNGdNV0EwUURkZ09xQTh3RDJBUDBCQ1lFU0FSMEJLZ0V5QVVJQlM0RlVBVjhCWWdGcmdYR0JmQUdKQVo2QnBBR3NBYktCdVFHOEFjR0J4UUFBUUFBQURNQWpBQU1BR1lBQndBQkFBQUFBQUFBQUFBQUFBQUFBQVFBQTNpY25KVGRUaHRYRklVL0I5dHRWRFVYRllySURUcVhiWldNM1FpaUJLNU1DWXBWaEZPUDB4K3BxalI0eGo5aVBEUHlERkNxUGtDdit4WjlpMXoxT2ZvUVZhK3JzN3dOTnFvVWdSQ3d6cHk5OTFsbnI3VVBzTW0vYkZDclB3VCthdjVndU1aMmM4L3dBeDQxbnhyZTRManh0K0g2U2t5RHVQR2I0U1pmTnZxR1ArSjkvUS9ESDdOVC85bndRN2JxUjRZLzRYbDkwL0NuRzQ1L0REOWloL2NMWElPWC9HNjR4aGFGNFFkczhwUGhEUjVqTld0MUh0TTIzT0F6dGcwMzJRWUdUS2xJbVpJeHhqRml5cGh6NWlTVWhDVE1tVElpSWNiUnBVTktwYThaa1pCai9MOWZJMElxNWtTcU9LSENrUktTRWxFeXNZcS9LaXZuclU0Y2FUVzN2UTRWRXlKT2xYRkdSSVlqWjB4T1JzS1o2bFJVRk96Um9rWEpVSHdMS2tvQ1NxYWtCT1RNR2RPaXh4SEhESmd3cGNSeHBFcWVXVWpPaUlwTElwM3ZMTUozWmtoQ1JtbXN6c21JeGRPSlg2THNMc2M0ZWhTS1hhMTh2RmJoS1k3dmxPMjU1WXI5aWtDL2JvWForcmxMTmhFWDZtZXFycVRhdVpTQ0UrMzZjenQ4SzF5eGg3dFhmOWFaZkxoSHNmNVhxbnpLdWZTUHBWUW1KaG5PYmRFaGxJTkM5d1RIZ2RaZFFuWGtlN29NZUVPUGR3eTA3dENuVDRjVEJuUjVyZHdlZlJ4ZjArT0VRMlYwaFJkN1IzTE1DVC9pK0lhdVluenR4UHF6VUN6aEZ3cHpkeW1PYzkxalJxR2VlK2FCN3Byb2huZFgyTTlRdnVhT1VqbER6WkdQZE5JdjA1eEZqTTBWaFJqTzFNdWxOMHJyWDJ5T21Pa3VYdHViZlQ4TkZ6Wjd5eW0rSXRjTWU3Y3VPSG5sRm93K3BHcHd5ek9YK2dtSWlNazVWY1NRbkJrdEtxN0UreTBSNTZRNER0VzlONXFTaXM1MWpqL25TaTVKbUlsQmwweDE1aFQ2RzVsdlF1TStYUE85czdja1ZyNW5lblo5cS91YzR0U3JHNDNlcVh2THZkQzZuS3dvMERKVjh4VTNEY1UxTSs4bm1xbFYvcUZ5UzcxdU9jL29rMGoxVkRlNC9RNDhKNkRORHJ2c005RTVRKzFjMkJ2UjFqdlI1aFg3NnNFWmlhSkdjblZpRlhZSmVNRXV1N3ppeFZyTkRvY2MwR1AvRGh3WFdUME9lSDFyWjEyblpSVm5kZjRVbTdiNE9wNWRyMTdlVzYvUDcrRExMelJSTnk5alg5cjRibDlZdFJ2L254QXg4MXpjMXVxZDNCT0Mvd0FBQVAvL0FRQUEvLzhIVzB3d0FIaWNZbUJtQUlQLzV4aU1HTEFBQUFBQUFQLy9BUUFBLy84dkFRSURBQUFBIik7Cn1dXT48L3N0eWxlPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbLnNoYXBlIHsKICBzaGFwZS1yZW5kZXJpbmc6IGdlb21ldHJpY1ByZWNpc2lvbjsKICBzdHJva2UtbGluZWpvaW46IHJvdW5kOwp9Ci5jb25uZWN0aW9uIHsKICBzdHJva2UtbGluZWNhcDogcm91bmQ7CiAgc3Ryb2tlLWxpbmVqb2luOiByb3VuZDsKfQouYmxlbmQgewogIG1peC1ibGVuZC1tb2RlOiBtdWx0aXBseTsKICBvcGFjaXR5OiAwLjU7Cn0KCgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjF7ZmlsbDojMEEwRjI1O30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1OMntmaWxsOiM2NzZDN0U7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLU4ze2ZpbGw6Izk0OTlBQjt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjR7ZmlsbDojQ0ZEMkREO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1ONXtmaWxsOiNERUUxRUI7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLU42e2ZpbGw6I0VFRjFGODt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtTjd7ZmlsbDojRkZGRkZGO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1CMXtmaWxsOiMwRDMyQjI7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLUIye2ZpbGw6IzBEMzJCMjt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtQjN7ZmlsbDojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1CNHtmaWxsOiNFM0U5RkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5maWxsLUI1e2ZpbGw6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmZpbGwtQjZ7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTJ7ZmlsbDojNEE2RkYzO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTR7ZmlsbDojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQTV7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQjR7ZmlsbDojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuZmlsbC1BQjV7ZmlsbDojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4xe3N0cm9rZTojMEEwRjI1O30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4ye3N0cm9rZTojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU4ze3N0cm9rZTojOTQ5OUFCO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU40e3N0cm9rZTojQ0ZEMkREO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU41e3N0cm9rZTojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU42e3N0cm9rZTojRUVGMUY4O30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLU43e3N0cm9rZTojRkZGRkZGO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIxe3N0cm9rZTojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIye3N0cm9rZTojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUIze3N0cm9rZTojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI0e3N0cm9rZTojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI1e3N0cm9rZTojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUI2e3N0cm9rZTojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUFBMntzdHJva2U6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLnN0cm9rZS1BQTR7c3Ryb2tlOiNFREYwRkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5zdHJva2UtQUE1e3N0cm9rZTojRjdGOEZFO30KCQkuZDItMTU2MzcxNzkxMSAuc3Ryb2tlLUFCNHtzdHJva2U6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLnN0cm9rZS1BQjV7c3Ryb2tlOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU4xe2JhY2tncm91bmQtY29sb3I6IzBBMEYyNTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItTjJ7YmFja2dyb3VuZC1jb2xvcjojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1OM3tiYWNrZ3JvdW5kLWNvbG9yOiM5NDk5QUI7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU40e2JhY2tncm91bmQtY29sb3I6I0NGRDJERDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItTjV7YmFja2dyb3VuZC1jb2xvcjojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1ONntiYWNrZ3JvdW5kLWNvbG9yOiNFRUYxRjg7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLU43e2JhY2tncm91bmQtY29sb3I6I0ZGRkZGRjt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQjF7YmFja2dyb3VuZC1jb2xvcjojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1CMntiYWNrZ3JvdW5kLWNvbG9yOiMwRDMyQjI7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLUIze2JhY2tncm91bmQtY29sb3I6I0UzRTlGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQjR7YmFja2dyb3VuZC1jb2xvcjojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuYmFja2dyb3VuZC1jb2xvci1CNXtiYWNrZ3JvdW5kLWNvbG9yOiNFREYwRkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5iYWNrZ3JvdW5kLWNvbG9yLUI2e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUEye2JhY2tncm91bmQtY29sb3I6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUE0e2JhY2tncm91bmQtY29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUE1e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUI0e2JhY2tncm91bmQtY29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmJhY2tncm91bmQtY29sb3ItQUI1e2JhY2tncm91bmQtY29sb3I6I0Y3RjhGRTt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU4xe2NvbG9yOiMwQTBGMjU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1OMntjb2xvcjojNjc2QzdFO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItTjN7Y29sb3I6Izk0OTlBQjt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU40e2NvbG9yOiNDRkQyREQ7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1ONXtjb2xvcjojREVFMUVCO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItTjZ7Y29sb3I6I0VFRjFGODt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLU43e2NvbG9yOiNGRkZGRkY7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1CMXtjb2xvcjojMEQzMkIyO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQjJ7Y29sb3I6IzBEMzJCMjt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUIze2NvbG9yOiNFM0U5RkQ7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1CNHtjb2xvcjojRTNFOUZEO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQjV7Y29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUI2e2NvbG9yOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1BQTJ7Y29sb3I6IzRBNkZGMzt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUFBNHtjb2xvcjojRURGMEZEO30KCQkuZDItMTU2MzcxNzkxMSAuY29sb3ItQUE1e2NvbG9yOiNGN0Y4RkU7fQoJCS5kMi0xNTYzNzE3OTExIC5jb2xvci1BQjR7Y29sb3I6I0VERjBGRDt9CgkJLmQyLTE1NjM3MTc5MTEgLmNvbG9yLUFCNXtjb2xvcjojRjdGOEZFO30uYXBwZW5kaXggdGV4dC50ZXh0e2ZpbGw6IzBBMEYyNX0ubWR7LS1jb2xvci1mZy1kZWZhdWx0OiMwQTBGMjU7LS1jb2xvci1mZy1tdXRlZDojNjc2QzdFOy0tY29sb3ItZmctc3VidGxlOiM5NDk5QUI7LS1jb2xvci1jYW52YXMtZGVmYXVsdDojRkZGRkZGOy0tY29sb3ItY2FudmFzLXN1YnRsZTojRUVGMUY4Oy0tY29sb3ItYm9yZGVyLWRlZmF1bHQ6IzBEMzJCMjstLWNvbG9yLWJvcmRlci1tdXRlZDojMEQzMkIyOy0tY29sb3ItbmV1dHJhbC1tdXRlZDojRUVGMUY4Oy0tY29sb3ItYWNjZW50LWZnOiMwRDMyQjI7LS1jb2xvci1hY2NlbnQtZW1waGFzaXM6IzBEMzJCMjstLWNvbG9yLWF0dGVudGlvbi1zdWJ0bGU6IzY3NkM3RTstLWNvbG9yLWRhbmdlci1mZzpyZWQ7fS5za2V0Y2gtb3ZlcmxheS1CMXtmaWxsOnVybCgjc3RyZWFrcy1kYXJrZXIpO21peC1ibGVuZC1tb2RlOmxpZ2h0ZW59LnNrZXRjaC1vdmVybGF5LUIye2ZpbGw6dXJsKCNzdHJlYWtzLWRhcmtlcik7bWl4LWJsZW5kLW1vZGU6bGlnaHRlbn0uc2tldGNoLW92ZXJsYXktQjN7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUI0e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1CNXtmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktQjZ7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUFBMntmaWxsOnVybCgjc3RyZWFrcy1kYXJrKTttaXgtYmxlbmQtbW9kZTpvdmVybGF5fS5za2V0Y2gtb3ZlcmxheS1BQTR7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LUFBNXtmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktQUI0e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1BQjV7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LnNrZXRjaC1vdmVybGF5LU4xe2ZpbGw6dXJsKCNzdHJlYWtzLWRhcmtlcik7bWl4LWJsZW5kLW1vZGU6bGlnaHRlbn0uc2tldGNoLW92ZXJsYXktTjJ7ZmlsbDp1cmwoI3N0cmVha3MtZGFyayk7bWl4LWJsZW5kLW1vZGU6b3ZlcmxheX0uc2tldGNoLW92ZXJsYXktTjN7ZmlsbDp1cmwoI3N0cmVha3Mtbm9ybWFsKTttaXgtYmxlbmQtbW9kZTpjb2xvci1idXJufS5za2V0Y2gtb3ZlcmxheS1ONHtmaWxsOnVybCgjc3RyZWFrcy1ub3JtYWwpO21peC1ibGVuZC1tb2RlOmNvbG9yLWJ1cm59LnNrZXRjaC1vdmVybGF5LU41e2ZpbGw6dXJsKCNzdHJlYWtzLWJyaWdodCk7bWl4LWJsZW5kLW1vZGU6ZGFya2VufS5za2V0Y2gtb3ZlcmxheS1ONntmaWxsOnVybCgjc3RyZWFrcy1icmlnaHQpO21peC1ibGVuZC1tb2RlOmRhcmtlbn0uc2tldGNoLW92ZXJsYXktTjd7ZmlsbDp1cmwoI3N0cmVha3MtYnJpZ2h0KTttaXgtYmxlbmQtbW9kZTpkYXJrZW59LmxpZ2h0LWNvZGV7ZGlzcGxheTogYmxvY2t9LmRhcmstY29kZXtkaXNwbGF5OiBub25lfV1dPjwvc3R5bGU+PGcgaWQ9IkNsaWVudCI+PGcgY2xhc3M9InNoYXBlIiA+PHJlY3QgeD0iNzUuMDAwMDAwIiB5PSI1MjQuMDAwMDAwIiB3aWR0aD0iMzAwLjAwMDAwMCIgaGVpZ2h0PSIxODAuMDAwMDAwIiBjbGFzcz0ic2hhcGUgc3Ryb2tlLU4xIGZpbGwtTjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MjsiIC8+PHJlY3QgeD0iNzUuMDAwMDAwIiB5PSI1MjQuMDAwMDAwIiB3aWR0aD0iMzAwLjAwMDAwMCIgaGVpZ2h0PSIzNi4wMDAwMDAiIGNsYXNzPSJjbGFzc19oZWFkZXIgZmlsbC1OMSIgLz48dGV4dCB4PSI4NS4wMDAwMDAiIHk9IjU0OS43NTAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjciIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjRweCI+Q2xpZW50PC90ZXh0Pjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNTgzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+PHRleHQgeD0iMTkxLjAwMDAwMCIgeT0iNTgzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5WQVJDSEFSKDgpPC90ZXh0Pjx0ZXh0IHg9IjM2NS4wMDAwMDAiIHk9IjU4My4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4Ij5QSzwvdGV4dD48bGluZSB4MT0iNzUuMDAwMDAwIiB4Mj0iMzc1LjAwMDAwMCIgeTE9IjU5Ni4wMDAwMDAiIHkyPSI1OTYuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Ob208L3RleHQ+PHRleHQgeD0iMTkxLjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5WQVJDSEFSKDI1NSk8L3RleHQ+PHRleHQgeD0iMzY1LjAwMDAwMCIgeT0iNjE5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9Ijc1LjAwMDAwMCIgeDI9IjM3NS4wMDAwMDAiIHkxPSI2MzIuMDAwMDAwIiB5Mj0iNjMyLjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSI4NS4wMDAwMDAiIHk9IjY1NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UHLDqW5vbTwvdGV4dD48dGV4dCB4PSIxOTEuMDAwMDAwIiB5PSI2NTUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoMjU1KTwvdGV4dD48dGV4dCB4PSIzNjUuMDAwMDAwIiB5PSI2NTUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCIgLz48bGluZSB4MT0iNzUuMDAwMDAwIiB4Mj0iMzc1LjAwMDAwMCIgeTE9IjY2OC4wMDAwMDAiIHkyPSI2NjguMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9Ijg1LjAwMDAwMCIgeT0iNjkxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5BZHJlc3NlPC90ZXh0Pjx0ZXh0IHg9IjE5MS4wMDAwMDAiIHk9IjY5MS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUigyNTUpPC90ZXh0Pjx0ZXh0IHg9IjM2NS4wMDAwMDAiIHk9IjY5MS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSI3NS4wMDAwMDAiIHgyPSIzNzUuMDAwMDAwIiB5MT0iNzA0LjAwMDAwMCIgeTI9IjcwNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iQ29tbWFuZGUiPjxnIGNsYXNzPSJzaGFwZSIgPjxyZWN0IHg9IjAuMDAwMDAwIiB5PSIyNDQuMDAwMDAwIiB3aWR0aD0iNDUwLjAwMDAwMCIgaGVpZ2h0PSIxODAuMDAwMDAwIiBjbGFzcz0ic2hhcGUgc3Ryb2tlLU4xIGZpbGwtTjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MjsiIC8+PHJlY3QgeD0iMC4wMDAwMDAiIHk9IjI0NC4wMDAwMDAiIHdpZHRoPSI0NTAuMDAwMDAwIiBoZWlnaHQ9IjM2LjAwMDAwMCIgY2xhc3M9ImNsYXNzX2hlYWRlciBmaWxsLU4xIiAvPjx0ZXh0IHg9IjEwLjAwMDAwMCIgeT0iMjY5Ljc1MDAwMCIgY2xhc3M9InRleHQgZmlsbC1ONyIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyNHB4Ij5Db21tYW5kZTwvdGV4dD48dGV4dCB4PSIxMC4wMDAwMDAiIHk9IjMwMy4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+TnVtLiBjb21tYW5kZTwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSIzMDMuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iMzAzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiPlBLPC90ZXh0PjxsaW5lIHgxPSIwLjAwMDAwMCIgeDI9IjQ1MC4wMDAwMDAiIHkxPSIzMTYuMDAwMDAwIiB5Mj0iMzE2LjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSIxMC4wMDAwMDAiIHk9IjMzOS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+RGF0ZTwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSIzMzkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPkRBVEU8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iMzM5LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9IjAuMDAwMDAwIiB4Mj0iNDUwLjAwMDAwMCIgeTE9IjM1Mi4wMDAwMDAiIHkyPSIzNTIuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9IjEwLjAwMDAwMCIgeT0iMzc1LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Nb250YW50PC90ZXh0Pjx0ZXh0IHg9IjE3NC4wMDAwMDAiIHk9IjM3NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+REVDSU1BTCgxMCwyKTwvdGV4dD48dGV4dCB4PSI0NDAuMDAwMDAwIiB5PSIzNzUuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCIgLz48bGluZSB4MT0iMC4wMDAwMDAiIHgyPSI0NTAuMDAwMDAwIiB5MT0iMzg4LjAwMDAwMCIgeTI9IjM4OC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iMTAuMDAwMDAwIiB5PSI0MTEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUIyIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlLDqWYuIGNsaWVudDwvdGV4dD48dGV4dCB4PSIxNzQuMDAwMDAwIiB5PSI0MTEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNDQwLjAwMDAwMCIgeT0iNDExLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiPkZLLCBOT1QgTlVMTDwvdGV4dD48bGluZSB4MT0iMC4wMDAwMDAiIHgyPSI0NTAuMDAwMDAwIiB5MT0iNDI0LjAwMDAwMCIgeTI9IjQyNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iSW5jbHVyZSI+PGcgY2xhc3M9InNoYXBlIiA+PHJlY3QgeD0iMjYyLjAwMDAwMCIgeT0iMC4wMDAwMDAiIHdpZHRoPSIzNjguMDAwMDAwIiBoZWlnaHQ9IjE0NC4wMDAwMDAiIGNsYXNzPSJzaGFwZSBzdHJva2UtTjEgZmlsbC1ONyIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgLz48cmVjdCB4PSIyNjIuMDAwMDAwIiB5PSIwLjAwMDAwMCIgd2lkdGg9IjM2OC4wMDAwMDAiIGhlaWdodD0iMzYuMDAwMDAwIiBjbGFzcz0iY2xhc3NfaGVhZGVyIGZpbGwtTjEiIC8+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iMjUuNzUwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU43IiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjI0cHgiPkluY2x1cmU8L3RleHQ+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUIyIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPk51bS4gY29tbWFuZGU8L3RleHQ+PHRleHQgeD0iNDM2LjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoOCk8L3RleHQ+PHRleHQgeD0iNjIwLjAwMDAwMCIgeT0iNTkuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCI+UEssIEZLPC90ZXh0PjxsaW5lIHgxPSIyNjIuMDAwMDAwIiB4Mj0iNjMwLjAwMDAwMCIgeTE9IjcyLjAwMDAwMCIgeTI9IjcyLjAwMDAwMCIgY2xhc3M9IiBzdHJva2UtTjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6MiIgLz48dGV4dCB4PSIyNzIuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UsOpZi4gcHJvZHVpdDwvdGV4dD48dGV4dCB4PSI0MzYuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUig4KTwvdGV4dD48dGV4dCB4PSI2MjAuMDAwMDAwIiB5PSI5NS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4Ij5QSywgRks8L3RleHQ+PGxpbmUgeDE9IjI2Mi4wMDAwMDAiIHgyPSI2MzAuMDAwMDAwIiB5MT0iMTA4LjAwMDAwMCIgeTI9IjEwOC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iMjcyLjAwMDAwMCIgeT0iMTMxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5RdWFudGl0w6k8L3RleHQ+PHRleHQgeD0iNDM2LjAwMDAwMCIgeT0iMTMxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1OMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5JTlRFR0VSPC90ZXh0Pjx0ZXh0IHg9IjYyMC4wMDAwMDAiIHk9IjEzMS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSIyNjIuMDAwMDAwIiB4Mj0iNjMwLjAwMDAwMCIgeTE9IjE0NC4wMDAwMDAiIHkyPSIxNDQuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjwvZz48L2c+PGcgaWQ9IlByb2R1aXQiPjxnIGNsYXNzPSJzaGFwZSIgPjxyZWN0IHg9IjUxMC4wMDAwMDAiIHk9IjI2Mi4wMDAwMDAiIHdpZHRoPSIzMTUuMDAwMDAwIiBoZWlnaHQ9IjE0NC4wMDAwMDAiIGNsYXNzPSJzaGFwZSBzdHJva2UtTjEgZmlsbC1ONyIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgLz48cmVjdCB4PSI1MTAuMDAwMDAwIiB5PSIyNjIuMDAwMDAwIiB3aWR0aD0iMzE1LjAwMDAwMCIgaGVpZ2h0PSIzNi4wMDAwMDAiIGNsYXNzPSJjbGFzc19oZWFkZXIgZmlsbC1OMSIgLz48dGV4dCB4PSI1MjAuMDAwMDAwIiB5PSIyODcuNzUwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU43IiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjI0cHgiPlByb2R1aXQ8L3RleHQ+PHRleHQgeD0iNTIwLjAwMDAwMCIgeT0iMzIxLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0Pjx0ZXh0IHg9IjY0Mi4wMDAwMDAiIHk9IjMyMS4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtTjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+VkFSQ0hBUig4KTwvdGV4dD48dGV4dCB4PSI4MTUuMDAwMDAwIiB5PSIzMjEuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLUFBMiIgc3R5bGU9InRleHQtYW5jaG9yOmVuZDtmb250LXNpemU6MjBweCI+UEs8L3RleHQ+PGxpbmUgeDE9IjUxMC4wMDAwMDAiIHgyPSI4MjUuMDAwMDAwIiB5MT0iMzM0LjAwMDAwMCIgeTI9IjMzNC4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PHRleHQgeD0iNTIwLjAwMDAwMCIgeT0iMzU3LjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1CMiIgc3R5bGU9InRleHQtYW5jaG9yOnN0YXJ0O2ZvbnQtc2l6ZToyMHB4Ij5MaWJlbGzDqTwvdGV4dD48dGV4dCB4PSI2NDIuMDAwMDAwIiB5PSIzNTcuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPlZBUkNIQVIoNTApPC90ZXh0Pjx0ZXh0IHg9IjgxNS4wMDAwMDAiIHk9IjM1Ny4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQUEyIiBzdHlsZT0idGV4dC1hbmNob3I6ZW5kO2ZvbnQtc2l6ZToyMHB4IiAvPjxsaW5lIHgxPSI1MTAuMDAwMDAwIiB4Mj0iODI1LjAwMDAwMCIgeTE9IjM3MC4wMDAwMDAiIHkyPSIzNzAuMDAwMDAwIiBjbGFzcz0iIHN0cm9rZS1OMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyIiAvPjx0ZXh0IHg9IjUyMC4wMDAwMDAiIHk9IjM5My4wMDAwMDAiIGNsYXNzPSJ0ZXh0IGZpbGwtQjIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjpzdGFydDtmb250LXNpemU6MjBweCI+UHJpeCB1bml0YWlyZTwvdGV4dD48dGV4dCB4PSI2NDIuMDAwMDAwIiB5PSIzOTMuMDAwMDAwIiBjbGFzcz0idGV4dCBmaWxsLU4yIiBzdHlsZT0idGV4dC1hbmNob3I6c3RhcnQ7Zm9udC1zaXplOjIwcHgiPkRFQ0lNQUwoMTAsMik8L3RleHQ+PHRleHQgeD0iODE1LjAwMDAwMCIgeT0iMzkzLjAwMDAwMCIgY2xhc3M9InRleHQgZmlsbC1BQTIiIHN0eWxlPSJ0ZXh0LWFuY2hvcjplbmQ7Zm9udC1zaXplOjIwcHgiIC8+PGxpbmUgeDE9IjUxMC4wMDAwMDAiIHgyPSI4MjUuMDAwMDAwIiB5MT0iNDA2LjAwMDAwMCIgeTI9IjQwNi4wMDAwMDAiIGNsYXNzPSIgc3Ryb2tlLU4xIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjIiIC8+PC9nPjwvZz48ZyBpZD0iKENvbW1hbmRlIC0mZ3Q7IENsaWVudClbMF0iPjxtYXJrZXIgaWQ9Im1rLTM0ODgzNzgxMzQiIG1hcmtlcldpZHRoPSIxMC4wMDAwMDAiIG1hcmtlckhlaWdodD0iMTIuMDAwMDAwIiByZWZYPSI3LjAwMDAwMCIgcmVmWT0iNi4wMDAwMDAiIHZpZXdCb3g9IjAuMDAwMDAwIDAuMDAwMDAwIDEwLjAwMDAwMCAxMi4wMDAwMDAiIG9yaWVudD0iYXV0byIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIj4gPHBvbHlnb24gcG9pbnRzPSIwLjAwMDAwMCwwLjAwMDAwMCAxMC4wMDAwMDAsNi4wMDAwMDAgMC4wMDAwMDAsMTIuMDAwMDAwIiBjbGFzcz0iY29ubmVjdGlvbiBmaWxsLUIxIiBzdHJva2Utd2lkdGg9IjIiIC8+IDwvbWFya2VyPjxwYXRoIGQ9Ik0gMjI1LjAwMDAwMCA0MjYuMDAwMDAwIEMgMjI1LjAwMDAwMCA0NjQuMDAwMDAwIDIyNS4wMDAwMDAgNDg0LjAwMDAwMCAyMjUuMDAwMDAwIDUyMC4wMDAwMDAiIGZpbGw9Im5vbmUiIGNsYXNzPSJjb25uZWN0aW9uIHN0cm9rZS1CMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgbWFya2VyLWVuZD0idXJsKCNtay0zNDg4Mzc4MTM0KSIgbWFzaz0idXJsKCNkMi0xNTYzNzE3OTExKSIgLz48L2c+PGcgaWQ9IihJbmNsdXJlIC0mZ3Q7IENvbW1hbmRlKVswXSI+PHBhdGggZD0iTSAzMTQuMjQ3MTYyIDE0NC45NjMwOTggQyAyNDMuMTk5OTk3IDE4NC4wMDAwMDAgMjI1LjAwMDAwMCAyMDQuMDAwMDAwIDIyNS4wMDAwMDAgMjQwLjAwMDAwMCIgZmlsbD0ibm9uZSIgY2xhc3M9ImNvbm5lY3Rpb24gc3Ryb2tlLUIxIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjI7IiBtYXJrZXItZW5kPSJ1cmwoI21rLTM0ODgzNzgxMzQpIiBtYXNrPSJ1cmwoI2QyLTE1NjM3MTc5MTEpIiAvPjwvZz48ZyBpZD0iKEluY2x1cmUgLSZndDsgUHJvZHVpdClbMF0iPjxwYXRoIGQ9Ik0gNTc4LjI1MjgzOCAxNDQuOTYzMDk4IEMgNjQ5LjI5OTk4OCAxODQuMDAwMDAwIDY2Ny41MDAwMDAgMjA3LjYwMDAwNiA2NjcuNTAwMDAwIDI1OC4wMDAwMDAiIGZpbGw9Im5vbmUiIGNsYXNzPSJjb25uZWN0aW9uIHN0cm9rZS1CMSIgc3R5bGU9InN0cm9rZS13aWR0aDoyOyIgbWFya2VyLWVuZD0idXJsKCNtay0zNDg4Mzc4MTM0KSIgbWFzaz0idXJsKCNkMi0xNTYzNzE3OTExKSIgLz48L2c+PG1hc2sgaWQ9ImQyLTE1NjM3MTc5MTEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9Ii0xMDEiIHk9Ii0xMDEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiI+CjxyZWN0IHg9Ii0xMDEiIHk9Ii0xMDEiIHdpZHRoPSIxMDI3IiBoZWlnaHQ9IjkwNiIgZmlsbD0id2hpdGUiPjwvcmVjdD4KCjwvbWFzaz48L3N2Zz48L3N2Zz4K\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t d2 --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Autres conversions\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Diagramme de classes UML\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"À tout seigneur tout honneur, Mocodo peut traduire votre MCD en UML. Ce formalisme graphique n'a, curieusement, pas de DSL textuel officiel. Nous nous rabattons donc sur le standard de fait, PlantUML :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 84,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_uml.puml\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```puml\\n\",\n       \"@startuml \\\"CCP\\\"\\n\",\n       \"\\n\",\n       \"!define Table(x) class \\\"x\\\" << (T,#FFFFFF) >>\\n\",\n       \"!define pk(x) <b>x</b>\\n\",\n       \"\\n\",\n       \"Table(\\\"Client\\\") {\\n\",\n       \"    {field} + pk(Réf. client) VARCHAR(8)\\n\",\n       \"    {field} + Nom         VARCHAR(255)\\n\",\n       \"    {field} + Prénom      VARCHAR(255)\\n\",\n       \"    {field} + Adresse     VARCHAR(255)\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Client\\\" \\\"1\\\" --- \\\"*\\\" \\\"Commande\\\": \\\"Passer\\\"\\n\",\n       \"\\n\",\n       \"Table(\\\"Commande\\\") {\\n\",\n       \"    {field} + pk(Num. commande) VARCHAR(8)\\n\",\n       \"    {field} + Date          DATE\\n\",\n       \"    {field} + Montant       DECIMAL(10,2)\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"\\\"Commande\\\" \\\"*\\\" --- \\\"1..*\\\" \\\"Produit\\\": \\\"Inclure\\\"\\n\",\n       \"(\\\"Commande\\\", \\\"Produit\\\") .. \\\"Inclure\\\"\\n\",\n       \"Table(\\\"Inclure\\\") {\\n\",\n       \"    {field} + Quantité INTEGER\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"Table(\\\"Produit\\\") {\\n\",\n       \"    {field} + pk(Réf. produit)  VARCHAR(8)\\n\",\n       \"    {field} + Libellé       VARCHAR(50)\\n\",\n       \"    {field} + Prix unitaire DECIMAL(10,2)\\n\",\n       \"}\\n\",\n       \"\\n\",\n       \"@enduml\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp --title CCP -t uml:plantuml=- # '-' supprime un préambule par défaut qui ne nous intéresse pas ici\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 85,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_uml.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxNTlweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjEzMjZweDtoZWlnaHQ6MTU5cHg7YmFja2dyb3VuZDojRjdGN0Y3OyIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgMTMyNiAxNTkiIHdpZHRoPSIxMzI2cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48cmVjdCBmaWxsPSIjRjdGN0Y3IiBoZWlnaHQ9IjE1OSIgc3R5bGU9InN0cm9rZTpub25lO3N0cm9rZS13aWR0aDoxLjA7IiB3aWR0aD0iMTMyNiIgeD0iMCIgeT0iMCIvPjwhLS1jbGFzcyBDbGllbnQtLT48ZyBpZD0iZWxlbV9DbGllbnQiPjxyZWN0IGNvZGVMaW5lPSIyNCIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSIxMDUuMTg3NSIgaWQ9IkNsaWVudCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIzMiIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjIxOCIgeD0iNyIgeT0iMzYuNSIvPjxyZWN0IGNvZGVMaW5lPSIyNCIgZmlsbD0ibm9uZSIgaGVpZ2h0PSIxMDUuMTg3NSIgaWQ9IkNsaWVudCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjE4IiB4PSI3IiB5PSI3Ii8+PGVsbGlwc2UgY3g9Ijg1Ljc1IiBjeT0iMjMiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNODYuNTkzOCwyOS43NSBMODQuMTQwNiwyOS43NSBMODQuMTQwNiwxOS41IEw4MSwxOS41IEw4MSwxNy4zNTk0IEw4OS43MzQ0LDE3LjM1OTQgTDg5LjczNDQsMTkuNSBMODYuNTkzOCwxOS41IEw4Ni41OTM4LDI5Ljc1IFogIiBmaWxsPSIjMDAwMDAwIi8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE4IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjUyIiB4PSIxMDYuMjUiIHk9IjI5LjIzMTQiPkNsaWVudDwvdGV4dD48bGluZSBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHgxPSI4IiB4Mj0iMjI0IiB5MT0iMzkiIHkyPSIzOSIvPjxlbGxpcHNlIGN4PSIxOCIgY3k9IjUyLjY0ODQiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iODgiIHg9IjI3IiB5PSI1NS45OTUxIj5SJiMyMzM7Zi4mIzE2MDtjbGllbnQ8L3RleHQ+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4MCIgeD0iMTIzIiB5PSI1NS45OTUxIj5WQVJDSEFSKDgpPC90ZXh0PjxlbGxpcHNlIGN4PSIxOCIgY3k9IjY4Ljk0NTMiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxOTIiIHg9IjI3IiB5PSI3Mi4yOTIiPk5vbSYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwO1ZBUkNIQVIoMjU1KTwvdGV4dD48ZWxsaXBzZSBjeD0iMTgiIGN5PSI4NS4yNDIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTkyIiB4PSIyNyIgeT0iODguNTg4OSI+UHImIzIzMztub20mIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtWQVJDSEFSKDI1NSk8L3RleHQ+PGVsbGlwc2UgY3g9IjE4IiBjeT0iMTAxLjUzOTEiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxOTIiIHg9IjI3IiB5PSIxMDQuODg1NyI+QWRyZXNzZSYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwO1ZBUkNIQVIoMjU1KTwvdGV4dD48L2c+PCEtLWNsYXNzIENvbW1hbmRlLS0+PGcgaWQ9ImVsZW1fQ29tbWFuZGUiPjxyZWN0IGNvZGVMaW5lPSIzMyIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iQ29tbWFuZGUiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMzkyIiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMzIiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMzkyIiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMi41IiBzdHlsZT0ic3Ryb2tlOiM5MkM1REU7c3Ryb2tlLXdpZHRoOjEuNTsiIHdpZHRoPSIyNDIiIHg9IjM5MiIgeT0iNDQuNjUiLz48cmVjdCBjb2RlTGluZT0iMzMiIGZpbGw9Im5vbmUiIGhlaWdodD0iODguODkwNiIgaWQ9IkNvbW1hbmRlIiByeD0iMi41IiByeT0iMi41IiBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHdpZHRoPSIyNDIiIHg9IjM5MiIgeT0iMTUuMTUiLz48ZWxsaXBzZSBjeD0iNDU4LjI1IiBjeT0iMzEuMTUiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNNDU5LjA5MzgsMzcuOSBMNDU2LjY0MDYsMzcuOSBMNDU2LjY0MDYsMjcuNjUgTDQ1My41LDI3LjY1IEw0NTMuNSwyNS41MDk0IEw0NjIuMjM0NCwyNS41MDk0IEw0NjIuMjM0NCwyNy42NSBMNDU5LjA5MzgsMjcuNjUgTDQ1OS4wOTM4LDM3LjkgWiAiIGZpbGw9IiMwMDAwMDAiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTgiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTAxIiB4PSI0NzguNzUiIHk9IjM3LjM4MTQiPkNvbW1hbmRlPC90ZXh0PjxsaW5lIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgeDE9IjM5MyIgeDI9IjYzMyIgeTE9IjQ3LjE1IiB5Mj0iNDcuMTUiLz48ZWxsaXBzZSBjeD0iNDAzIiBjeT0iNjAuNzk4NCIgZmlsbD0ibm9uZSIgcng9IjMiIHJ5PSIzIiBzdHlsZT0ic3Ryb2tlOiMwMzgwNDg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ibW9ub3NwYWNlIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxMDQiIHg9IjQxMiIgeT0iNjQuMTQ1MSI+TnVtLiYjMTYwO2NvbW1hbmRlPC90ZXh0Pjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iODAiIHg9IjUyNCIgeT0iNjQuMTQ1MSI+VkFSQ0hBUig4KTwvdGV4dD48ZWxsaXBzZSBjeD0iNDAzIiBjeT0iNzcuMDk1MyIgZmlsbD0ibm9uZSIgcng9IjMiIHJ5PSIzIiBzdHlsZT0ic3Ryb2tlOiMwMzgwNDg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ibW9ub3NwYWNlIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjE0NCIgeD0iNDEyIiB5PSI4MC40NDIiPkRhdGUmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtEQVRFPC90ZXh0PjxlbGxpcHNlIGN4PSI0MDMiIGN5PSI5My4zOTIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMjE2IiB4PSI0MTIiIHk9Ijk2LjczODkiPk1vbnRhbnQmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDtERUNJTUFMKDEwLDIpPC90ZXh0PjwvZz48IS0tY2xhc3MgUHJvZHVpdC0tPjxnIGlkPSJlbGVtX1Byb2R1aXQiPjxyZWN0IGNvZGVMaW5lPSI0NSIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iUHJvZHVpdCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSIxNS4xNSIvPjxyZWN0IGZpbGw9IiM5MkM1REUiIGhlaWdodD0iMzIiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjI0MiIgeD0iMTA3NyIgeT0iMTUuMTUiLz48cmVjdCBmaWxsPSIjOTJDNURFIiBoZWlnaHQ9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSI0NC42NSIvPjxyZWN0IGNvZGVMaW5lPSI0NSIgZmlsbD0ibm9uZSIgaGVpZ2h0PSI4OC44OTA2IiBpZD0iUHJvZHVpdCIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMjQyIiB4PSIxMDc3IiB5PSIxNS4xNSIvPjxlbGxpcHNlIGN4PSIxMTYxLjc1IiBjeT0iMzEuMTUiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNMTE2Mi41OTM4LDM3LjkgTDExNjAuMTQwNiwzNy45IEwxMTYwLjE0MDYsMjcuNjUgTDExNTcsMjcuNjUgTDExNTcsMjUuNTA5NCBMMTE2NS43MzQ0LDI1LjUwOTQgTDExNjUuNzM0NCwyNy42NSBMMTE2Mi41OTM4LDI3LjY1IEwxMTYyLjU5MzgsMzcuOSBaICIgZmlsbD0iIzAwMDAwMCIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI2NCIgeD0iMTE4Mi4yNSIgeT0iMzcuMzgxNCI+UHJvZHVpdDwvdGV4dD48bGluZSBzdHlsZT0ic3Ryb2tlOiM0MzkzQzM7c3Ryb2tlLXdpZHRoOjEuNTsiIHgxPSIxMDc4IiB4Mj0iMTMxOCIgeTE9IjQ3LjE1IiB5Mj0iNDcuMTUiLz48ZWxsaXBzZSBjeD0iMTA4OCIgY3k9IjYwLjc5ODQiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOTYiIHg9IjEwOTciIHk9IjY0LjE0NTEiPlImIzIzMztmLiYjMTYwO3Byb2R1aXQ8L3RleHQ+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4MCIgeD0iMTIwOSIgeT0iNjQuMTQ1MSI+VkFSQ0hBUig4KTwvdGV4dD48ZWxsaXBzZSBjeD0iMTA4OCIgY3k9Ijc3LjA5NTMiIGZpbGw9Im5vbmUiIHJ4PSIzIiByeT0iMyIgc3R5bGU9InN0cm9rZTojMDM4MDQ4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9Im1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIyMDAiIHg9IjEwOTciIHk9IjgwLjQ0MiI+TGliZWxsJiMyMzM7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7VkFSQ0hBUig1MCk8L3RleHQ+PGVsbGlwc2UgY3g9IjEwODgiIGN5PSI5My4zOTIyIiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMjE2IiB4PSIxMDk3IiB5PSI5Ni43Mzg5Ij5Qcml4JiMxNjA7dW5pdGFpcmUmIzE2MDtERUNJTUFMKDEwLDIpPC90ZXh0PjwvZz48IS0tY2xhc3MgSW5jbHVyZS0tPjxnIGlkPSJlbGVtX0luY2x1cmUiPjxyZWN0IGNvZGVMaW5lPSI0MSIgZmlsbD0iI0QxRTVGMCIgaGVpZ2h0PSI1Ni4yOTY5IiBpZD0iSW5jbHVyZSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMTU0IiB4PSI4MDAiIHk9Ijk2LjQ0Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIzMiIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojOTJDNURFO3N0cm9rZS13aWR0aDoxLjU7IiB3aWR0aD0iMTU0IiB4PSI4MDAiIHk9Ijk2LjQ0Ii8+PHJlY3QgZmlsbD0iIzkyQzVERSIgaGVpZ2h0PSIyLjUiIHN0eWxlPSJzdHJva2U6IzkyQzVERTtzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjE1NCIgeD0iODAwIiB5PSIxMjUuOTQiLz48cmVjdCBjb2RlTGluZT0iNDEiIGZpbGw9Im5vbmUiIGhlaWdodD0iNTYuMjk2OSIgaWQ9IkluY2x1cmUiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzQzOTNDMztzdHJva2Utd2lkdGg6MS41OyIgd2lkdGg9IjE1NCIgeD0iODAwIiB5PSI5Ni40NCIvPjxlbGxpcHNlIGN4PSI4NDIuNDUiIGN5PSIxMTIuNDQiIGZpbGw9IiNEMUU1RjAiIHJ4PSIxMSIgcnk9IjExIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48cGF0aCBkPSJNODQzLjI5MzgsMTE5LjE5IEw4NDAuODQwNiwxMTkuMTkgTDg0MC44NDA2LDEwOC45NCBMODM3LjcsMTA4Ljk0IEw4MzcuNywxMDYuNzk5NCBMODQ2LjQzNDQsMTA2Ljc5OTQgTDg0Ni40MzQ0LDEwOC45NCBMODQzLjI5MzgsMTA4Ljk0IEw4NDMuMjkzOCwxMTkuMTkgWiAiIGZpbGw9IiMwMDAwMDAiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTgiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iNjEiIHg9Ijg2Mi41NSIgeT0iMTE4LjY3MTQiPkluY2x1cmU8L3RleHQ+PGxpbmUgc3R5bGU9InN0cm9rZTojNDM5M0MzO3N0cm9rZS13aWR0aDoxLjU7IiB4MT0iODAxIiB4Mj0iOTUzIiB5MT0iMTI4LjQ0IiB5Mj0iMTI4LjQ0Ii8+PGVsbGlwc2UgY3g9IjgxMSIgY3k9IjE0Mi4wODg0IiBmaWxsPSJub25lIiByeD0iMyIgcnk9IjMiIHN0eWxlPSJzdHJva2U6IzAzODA0ODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTI4IiB4PSI4MjAiIHk9IjE0NS40MzUxIj5RdWFudGl0JiMyMzM7JiMxNjA7SU5URUdFUjwvdGV4dD48L2c+PGVsbGlwc2UgY3g9Ijg3NyIgY3k9IjU5LjU5IiBmaWxsPSIjMTgxODE4IiByeD0iMiIgcnk9IjIiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjwhLS1saW5rIENsaWVudCB0byBDb21tYW5kZS0tPjxnIGlkPSJsaW5rX0NsaWVudF9Db21tYW5kZSI+PHBhdGggY29kZUxpbmU9IjMxIiBkPSJNMjI1LjQ2LDU5LjU5IEMyNzYuOTYsNTkuNTkgMzM4LjY4LDU5LjU5IDM5MS42Miw1OS41OSAiIGZpbGw9Im5vbmUiIGlkPSJDbGllbnQtQ29tbWFuZGUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjQzIiB4PSIyODciIHk9IjU1LjY1NjkiPlBhc3NlcjwvdGV4dD48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI4IiB4PSIyMzMuMDgzMSIgeT0iNzIuMTY1Ij4xPC90ZXh0Pjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjciIHg9IjM3Ny4wMTAxIiB5PSI3Mi4xMTc2Ij4qPC90ZXh0PjwvZz48IS0tbGluayBDb21tYW5kZSB0byBhcG9pbnQ4LS0+PGcgaWQ9ImxpbmtfQ29tbWFuZGVfYXBvaW50OCI+PHBhdGggZD0iTTYzNC4yOSw1OS41OSBDNzM0LjY5LDU5LjU5IDg2My4yOCw1OS41OSA4NzUuMTIsNTkuNTkgIiBmaWxsPSJub25lIiBpZD0iQ29tbWFuZGUtYXBvaW50OCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTMiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iNDIiIHg9IjY5NiIgeT0iNTUuNjU2OSI+SW5jbHVyZTwvdGV4dD48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI3IiB4PSI2NDEuODk0NCIgeT0iNzIuMTE3NiI+KjwvdGV4dD48L2c+PCEtLWxpbmsgYXBvaW50OCB0byBQcm9kdWl0LS0+PGcgaWQ9ImxpbmtfYXBvaW50OF9Qcm9kdWl0Ij48cGF0aCBkPSJNODc5LjQyLDU5LjU5IEM4OTIuNDMsNTkuNTkgOTkyLjI2LDU5LjU5IDEwNzYuNTcsNTkuNTkgIiBmaWxsPSJub25lIiBpZD0iYXBvaW50OC1Qcm9kdWl0IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMyIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIyMyIgeD0iMTA0NS44ODUiIHk9IjcyLjA5NCI+MS4uKjwvdGV4dD48L2c+PCEtLWxpbmsgYXBvaW50OCB0byBJbmNsdXJlLS0+PGcgaWQ9ImxpbmtfYXBvaW50OF9JbmNsdXJlIj48cGF0aCBkPSJNODc3LDYxLjg4IEM4NzcsNzMuMyA4NzcsODQuNzMgODc3LDk2LjE1ICIgZmlsbD0ibm9uZSIgaWQ9ImFwb2ludDgtSW5jbHVyZSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheTo3LjAsNy4wOyIvPjwvZz48IS0tU1JDPVtYUEpIUmplbTU4Umx5bklkeFd0UFE0UTBURXM0YTNCQUxnR01DT1BzeHlHZG5TQW5hTjRhckFlRm43Rm1PZENXQUltMXZqcDRFYi1FX18tUzRyeW5KQlg0Y0Q1OE82RmpHWXBlUVdMYUpRM05XeVFpVVNyeTM5QU0yX3MtU3JOMG9xTEV6Z0Ita2xTYndaanBwWDFJRDdGNUxleDBuODFIZUZkQnQwM1o2Y0YzYk5ITTJvd05MRENLTmhKQWJZQ3ZIeXFEYko1Mi1vV2VSRnhQZENTQllMUTZ4bU1MczQwOWZVNlF0VHdza2ttZTVqNXVhSVVNaDIySWhfYnBIRW9DWFNQZTdjSzZWb1hmMmhBck1uVjlDS3FIZGZMS2dvTURhTHJhVl9ETjFCelJQUnZOMVV4aE1pRUtQZ1dCZkRrdnh5SVRxeVl2OGtzR194aHhDMUxnSmlNZndEeDZOSk5xWURHVU5aRHB0dXUzWGV3cDdvQ280MW9iOEl3eUVNM05NeTlIaTdWdWQ0X0VUQmo5RjlpaTlycHU0cXU3Wi02cVNVVE1vQjVBZUxtYnIwdzJBWlJIc3VxaXFHalNvQklqNVRRblR5U2Z2R0JuMlRwU3QwM3ZQRHk3QWFzZlA0WS0wUGJPdndaOW1MeVBFLWJtZEFOTU84NVNpRlgwM052dVg4VG1EZ20wVGtCaTdzOUFPM1dPRk9URjNSX0xSMVV3SW5heG5KbGJsa1ZidVlUUWlPb1JORmo4bllCSkk5bVpzU3EzdU9CZDdLNjVtTjlWel9TaGl1Z3VzTXZXRDl1RFZtd2RrUEJZZ3FGRWl0clZ4WDROcGZWYllLU2VYM3RXdHdPNmhOaGwtSGVvUU15SFV5bEtvbENOXS0tPjwvZz48L3N2Zz4=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t uml --defer --colors brewer+5\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### ERD avec la convention _Look across_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.0.** Force est de reconnaître que de nos jours, les MCD à la sauce Merise ne sont plus goûtés que par une poignée d'irréductibles Gaulois (et contractuellement leurs étudiants). Dans le cadre de son projet secret de domination planétaire, Mocodo commence à faire du pied à des notations mieux comprises du reste de l'univers.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Notation de Chen\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Un MCD peut être converti en un ERD (_Entity-Relationship Diagram_) dans la notation de Chen, sans ses attributs ou avec :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 86,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI3MHB0IiBoZWlnaHQ9IjEzMHB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI2OS41MCAxMzAuNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTI2LjQpIj4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTEyNi40IDI2NS41LC0xMjYuNCAyNjUuNSw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjU4Ljc1LC0xMjIuNCAwLC0xMjIuNCAwLC04Ni40IDU4Ljc1LC04Ni40IDU4Ljc1LC0xMjIuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOS4zOCIgeT0iLTk5LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMxMzExMTQiPkNsaWVudDwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNiMmJiYTQiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNjUuMzgsLTUwLjQgMTMuNywtMjUuMiA2NS4zNywwIDExNy4wNSwtMjUuMiA2NS4zOCwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2NS4zOCIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMyNzM2MGMiPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0zNy4zNiwtODYuMjdDNDIuODcsLTc0LjQ1IDUwLjIyLC01OC43IDU2LjAxLC00Ni4yOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1Ni4wMSIgeT0iLTYxLjYyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjE3My41LC0xMjIuNCA3Ny4yNSwtMTIyLjQgNzcuMjUsLTg2LjQgMTczLjUsLTg2LjQgMTczLjUsLTEyMi40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEyNS4zOCIgeT0iLTk5LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMxMzExMTQiPkNvbW1hbmRlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTExMS4yNywtODYuODhDMTAxLjUzLC03NC4zNSA4OC4zNiwtNTcuNCA3OC40OSwtNDQuNyIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0xMTIuODUsLTg1LjY1QzEwMy4xMSwtNzMuMTMgODkuOTQsLTU2LjE4IDgwLjA3LC00My40OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5Ny4wOCIgeT0iLTQ4LjU0IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPk48L3RleHQ+CjwvZz4KPCEtLSA0IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIwNy4zOCwtNTAuNCAxNTMuMjUsLTI1LjIgMjA3LjM3LDAgMjYxLjUsLTI1LjIgMjA3LjM4LC01MC40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIwNy4zOCIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMyNzM2MGMiPkluY2x1cmU8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzQgLS0+CjxnIGlkPSJlZGdlNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNMTQyLjg5LC04NS41NEMxNTYuNjcsLTcyLjU3IDE3NS40OCwtNTQuODUgMTg5LjEsLTQyLjAzIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTE0NC4yNiwtODYuOTlDMTU4LjA0LC03NC4wMiAxNzYuODUsLTU2LjMxIDE5MC40OCwtNDMuNDgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjM5IiB5PSItNTYuNjYiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TjwvdGV4dD4KPC9nPgo8IS0tIDUgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiM5N2I4ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjYxLC0xMjIuNCAxOTEuNzUsLTEyMi40IDE5MS43NSwtODYuNCAyNjEsLTg2LjQgMjYxLC0xMjIuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjYuMzgiIHk9Ii05OS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5Qcm9kdWl0PC90ZXh0Pgo8L2c+CjwhLS0gNSYjNDU7JiM0NTs0IC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjUmIzQ1OyYjNDU7NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTIyMi4xNiwtODYuMjdDMjE5LjQsLTc1LjA3IDIxNS43OCwtNjAuMzUgMjEyLjgxLC00OC4yOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjUuMzUiIHk9Ii01OS4xOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjNzI2ZjgzIj5NPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t chen --defer --colors ocean\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 87,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjEzNjhwdCIgaGVpZ2h0PSIyMTJwdCIKIHZpZXdCb3g9IjAuMDAgMC4wMCAxMzY4LjM0IDIxMi4xMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAyMDguMSkiPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMjA4LjEgMTM2NC4zNCwtMjA4LjEgMTM2NC4zNCw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjI4Ni4yNywtMjA0LjEgMjI3LjUyLC0yMDQuMSAyMjcuNTIsLTE2OC4xIDI4Ni4yNywtMTY4LjEgMjg2LjI3LC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyNTYuOSIgeT0iLTE4MS40MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5DbGllbnQ8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8ZWxsaXBzZSBmaWxsPSIjYzBkNGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBjeD0iMzQuOSIgY3k9Ii0xMDIuMDUiIHJ4PSIzNC45IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzQuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPk5vbTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MyAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjI3LjI3LC0xNzkuMDlDMTkxLjEzLC0xNzEuMTQgMTI4LjcyLC0xNTUuMzQgNzguOSwtMTMyLjEgNzAuMjcsLTEyOC4wOCA2MS4zOSwtMTIyLjUzIDUzLjg5LC0xMTcuMzYiLz4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIxMzcuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI1MC4xNiIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzNy45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UHLDqW5vbTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7NCAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjMxLjY2LC0xNjcuN0MyMTAuNTEsLTE1My4xMiAxODAuNiwtMTMyLjUgMTYwLjI5LC0xMTguNDkiLz4KPC9nPgo8IS0tIDUgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NTwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIyNTYuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI1MS4yMSIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI1Ni45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+QWRyZXNzZTwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7NSAtLT4KPGcgaWQ9ImVkZ2U0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMjU2LjksLTE2Ny43QzI1Ni45LC0xNTMuNzggMjU2LjksLTEzNC4zNSAyNTYuOSwtMTIwLjQzIi8+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTExIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjM2NS45IiBjeT0iLTEwMi4wNSIgcng9IjM5LjQyIiByeT0iMjUuNDYiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTIuMDIiIHk9Ii0xMDMuNzUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgdGV4dC1kZWNvcmF0aW9uPSJ1bmRlcmxpbmUiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPlLDqWYuPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM0Ni4wMiIgeT0iLTg5Ljc1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIHRleHQtZGVjb3JhdGlvbj0idW5kZXJsaW5lIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5jbGllbnQ8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgZD0iTTI4MC4wMSwtMTY3LjdDMjk3Ljg5LC0xNTQuMjUgMzIyLjU5LC0xMzUuNjUgMzQwLjkyLC0xMjEuODYiLz4KPC9nPgo8IS0tIDYgLS0+CjxnIGlkPSJub2RlMTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjQ3NC45LC0xMjcuMjUgNDIzLjIyLC0xMDIuMDUgNDc0LjksLTc2Ljg1IDUyNi41OCwtMTAyLjA1IDQ3NC45LC0xMjcuMjUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDc0LjkiIHk9Ii05Ny4zOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMjczNjBjIj5QYXNzZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzYgLS0+CjxnIGlkPSJlZGdlMTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjEmIzQ1OyYjNDU7NjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTI4Ni41LC0xNzYuMjdDMzE4LjM2LC0xNjYuNDkgMzcwLjMxLC0xNDkuNzcgNDEzLjksLTEzMi4xIDQyNi4wNywtMTI3LjE3IDQzOS4yNywtMTIwLjk5IDQ1MC4yNywtMTE1LjYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDM3LjY4IiB5PSItMTI2LjQ3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPjE8L3RleHQ+CjwvZz4KPCEtLSA3IC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjc8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjOTdiOGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjczNS4wMiwtMjA0LjEgNjM4Ljc3LC0yMDQuMSA2MzguNzcsLTE2OC4xIDczNS4wMiwtMTY4LjEgNzM1LjAyLC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2ODYuOSIgeT0iLTE4MS40MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjMTMxMTE0Ij5Db21tYW5kZTwvdGV4dD4KPC9nPgo8IS0tIDkgLS0+CjxnIGlkPSJub2RlNyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+OTwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSI1NzkuOSIgY3k9Ii0xMDIuMDUiIHJ4PSIzNC45IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTc5LjkiIHk9Ii05Ny4zOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5EYXRlPC90ZXh0Pgo8L2c+CjwhLS0gNyYjNDU7JiM0NTs5IC0tPgo8ZyBpZD0iZWRnZTYiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7OTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGQ9Ik02NjQuMjEsLTE2Ny43QzY0NC43LC0xNTIuNzQgNjE2LjksLTEzMS40MyA1OTguNjQsLTExNy40MiIvPgo8L2c+CjwhLS0gMTAgLS0+CjxnIGlkPSJub2RlOCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTA8L3RpdGxlPgo8ZWxsaXBzZSBmaWxsPSIjYzBkNGZmIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBjeD0iNjg2LjkiIGN5PSItMTAyLjA1IiByeD0iNTMuODQiIHJ5PSIxOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI2ODYuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPk1vbnRhbnQ8L3RleHQ+CjwvZz4KPCEtLSA3JiM0NTsmIzQ1OzEwIC0tPgo8ZyBpZD0iZWRnZTciIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7MTA8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNNjg2LjksLTE2Ny43QzY4Ni45LC0xNTMuNzggNjg2LjksLTEzNC4zNSA2ODYuOSwtMTIwLjQzIi8+CjwvZz4KPCEtLSA4IC0tPgo8ZyBpZD0ibm9kZTEyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT44PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjgyNC45IiBjeT0iLTEwMi4wNSIgcng9IjY1Ljk0IiByeT0iMjUuNDYiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI4MDUuNCIgeT0iLTEwMy43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+TnVtLjwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3ODYuMjciIHk9Ii04OS43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+Y29tbWFuZGU8L3RleHQ+CjwvZz4KPCEtLSA3JiM0NTsmIzQ1OzggLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NyYjNDU7JiM0NTs4PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgZD0iTTcxNi4xNiwtMTY3LjdDNzM3LjY5LC0xNTQuOTEgNzY3LjAzLC0xMzcuNDYgNzg5LjgxLC0xMjMuOTIiLz4KPC9nPgo8IS0tIDcmIzQ1OyYjNDU7NiAtLT4KPGcgaWQ9ImVkZ2UxNCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NyYjNDU7JiM0NTs2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNNjM4LjE1LC0xNzAuNTJDNjA4LjI3LC0xNjAuNTggNTY5LjM1LC0xNDYuOTcgNTM1LjUyLC0xMzMuMDMgNTIzLjMzLC0xMjggNTEwLjEzLC0xMjEuODIgNDk5LjEyLC0xMTYuNDMiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNzI2ZjgzIiBkPSJNNjM4Ljc4LC0xNjguNjJDNjA4LjkyLC0xNTguNjkgNTcwLjAxLC0xNDUuMDggNTM2LjI4LC0xMzEuMTggNTI0LjE4LC0xMjYuMTkgNTEwLjk4LC0xMjAgNTAwLC0xMTQuNjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTE5LjU2IiB5PSItMTExLjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM3MjZmODMiPk48L3RleHQ+CjwvZz4KPCEtLSAxMSAtLT4KPGcgaWQ9Im5vZGUxNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjYjJiYmE0IiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9Ijk2Mi45LC0xMjcuMjUgOTA4Ljc3LC0xMDIuMDUgOTYyLjksLTc2Ljg1IDEwMTcuMDMsLTEwMi4wNSA5NjIuOSwtMTI3LjI1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9Ijk2Mi45IiB5PSItOTcuMzgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzI3MzYwYyI+SW5jbHVyZTwvdGV4dD4KPC9nPgo8IS0tIDcmIzQ1OyYjNDU7MTEgLS0+CjxnIGlkPSJlZGdlMTUiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjcmIzQ1OyYjNDU7MTE8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik03MzUuMjUsLTE3NC43N0M3NzguOSwtMTY1LjcyIDg0NC40OSwtMTUwLjUzIDg5OS41NywtMTMxLjE2IDkxMi4zMywtMTI2LjY4IDkyNi4xMSwtMTIwLjQ5IDkzNy40NywtMTE1Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzcyNmY4MyIgZD0iTTczNS42NiwtMTc2LjczQzc3OS4zNSwtMTY3LjY2IDg0NC45NCwtMTUyLjQ3IDkwMC4yMywtMTMzLjA1IDkxMy4xNSwtMTI4LjUgOTI2LjkzLC0xMjIuMzEgOTM4LjM0LC0xMTYuOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5MjUuMjEiIHk9Ii0xMjYuNjgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TjwvdGV4dD4KPC9nPgo8IS0tIDEyIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjEyPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iIzk3YjhmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxMTcxLjUyLC0yMDQuMSAxMTAyLjI3LC0yMDQuMSAxMTAyLjI3LC0xNjguMSAxMTcxLjUyLC0xNjguMSAxMTcxLjUyLC0yMDQuMSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTM2LjkiIHk9Ii0xODEuNDMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzEzMTExNCI+UHJvZHVpdDwvdGV4dD4KPC9nPgo8IS0tIDE1IC0tPgo8ZyBpZD0ibm9kZTkiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE1PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjEwNzkuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI0NC44OSIgcnk9IjE4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwNzkuOSIgeT0iLTk3LjM4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiMzZTNjNDIiPkxpYmVsbMOpPC90ZXh0Pgo8L2c+CjwhLS0gMTImIzQ1OyYjNDU7MTUgLS0+CjxnIGlkPSJlZGdlOSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTU8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTEyNC44MSwtMTY3LjdDMTExNS4wMSwtMTUzLjU5IDExMDEuMjcsLTEzMy44MiAxMDkxLjU4LC0xMTkuODciLz4KPC9nPgo8IS0tIDE2IC0tPgo8ZyBpZD0ibm9kZTEwIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xNjwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjMGQ0ZmYiIHN0cm9rZT0iIzU3OGRmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSIxMTkzLjkiIGN5PSItMTAyLjA1IiByeD0iNTEuMDkiIHJ5PSIzMC4wNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTkzLjkiIHk9Ii0xMDYiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UHJpeDwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTE5My45IiB5PSItODguNzUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+dW5pdGFpcmU8L3RleHQ+CjwvZz4KPCEtLSAxMiYjNDU7JiM0NTsxNiAtLT4KPGcgaWQ9ImVkZ2UxMCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTY8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTE0OC45OSwtMTY3LjdDMTE1Ni41LC0xNTYuODggMTE2Ni4zMywtMTQyLjc0IDExNzQuODcsLTEzMC40NCIvPgo8L2c+CjwhLS0gMTQgLS0+CjxnIGlkPSJub2RlMTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE0PC90aXRsZT4KPGVsbGlwc2UgZmlsbD0iI2MwZDRmZiIgc3Ryb2tlPSIjNTc4ZGZmIiBzdHJva2Utd2lkdGg9IjEuNSIgY3g9IjEzMTEuOSIgY3k9Ii0xMDIuMDUiIHJ4PSI0OC40NCIgcnk9IjI1LjQ2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI5OC4wMiIgeT0iLTEwMy43NSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiB0ZXh0LWRlY29yYXRpb249InVuZGVybGluZSIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzNlM2M0MiI+UsOpZi48L3RleHQ+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI4NS42NSIgeT0iLTg5Ljc1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIHRleHQtZGVjb3JhdGlvbj0idW5kZXJsaW5lIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjM2UzYzQyIj5wcm9kdWl0PC90ZXh0Pgo8L2c+CjwhLS0gMTImIzQ1OyYjNDU7MTQgLS0+CjxnIGlkPSJlZGdlOCIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM1NzhkZmYiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNMTE3MS44OCwtMTY5LjY5QzExOTUuMjEsLTE1OS4zIDEyMjYuNTIsLTE0NS4xNSAxMjUzLjksLTEzMi4xIDEyNjEuNjIsLTEyOC40MiAxMjY5Ljg4LC0xMjQuMzYgMTI3Ny42NiwtMTIwLjQ4Ii8+CjwvZz4KPCEtLSAxMiYjNDU7JiM0NTsxMSAtLT4KPGcgaWQ9ImVkZ2UxMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTImIzQ1OyYjNDU7MTE8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM3MjZmODMiIGQ9Ik0xMTAyLjExLC0xNjguN0MxMDY4Ljc4LC0xNTIuOTggMTAxOS4yNCwtMTI5LjYyIDk4OS4xMiwtMTE1LjQyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwMDkuMTIiIHk9Ii0xMTAuODMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCIgZmlsbD0iIzcyNmY4MyI+TTwvdGV4dD4KPC9nPgo8IS0tIDEzIC0tPgo8ZyBpZD0ibm9kZTE0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xMzwvdGl0bGU+CjxlbGxpcHNlIGZpbGw9IiNjY2Q2YmEiIHN0cm9rZT0iIzg1OTU2YiIgc3Ryb2tlLXdpZHRoPSIxLjUiIGN4PSI5NjIuOSIgY3k9Ii0xOCIgcng9IjU0Ljg5IiByeT0iMTgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTYyLjkiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjNjA3NzM0Ij5RdWFudGl0w6k8L3RleHQ+CjwvZz4KPCEtLSAxMSYjNDU7JiM0NTsxMyAtLT4KPGcgaWQ9ImVkZ2UxMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MTEmIzQ1OyYjNDU7MTM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM4NTk1NmIiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNOTYyLjksLTc2LjQzQzk2Mi45LC02My41IDk2Mi45LC00Ny45NiA5NjIuOSwtMzYuMzEiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t chen:attrs --defer --colors ocean\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Notation _crow's foot_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans le même ordre d'idées, Mocodo peut générer des ERD dans l'astucieuse notation introduite en 1976 par Gordon Everest. Par défaut, le format du fichier intermédiaire est là encore Graphviz :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 88,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_erd_crow.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjYyNHB0IiBoZWlnaHQ9IjMzMnB0Igogdmlld0JveD0iMC4wMCAwLjAwIDYyNC4wMCAzMzEuNTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMzI3LjUpIj4KPHBvbHlnb24gZmlsbD0iI2Y3ZjdmNyIgc3Ryb2tlPSJub25lIiBwb2ludHM9Ii00LDQgLTQsLTMyNy41IDYyMCwtMzI3LjUgNjIwLDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzOSwtMTc2LjUgMzksLTMxOS41IDI2OSwtMzE5LjUgMjY5LC0xNzYuNSAzOSwtMTc2LjUiLz4KPHBvbHlnb24gZmlsbD0iI2E2ZGJhMCIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjM5LC0yODguNSAzOSwtMzE5LjUgMjY5LC0zMTkuNSAyNjksLTI4OC41IDM5LC0yODguNSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTI4OC41IDM5LC0zMTkuNSAyNjksLTMxOS41IDI2OSwtMjg4LjUgMzksLTI4OC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTI3Ljc1IiB5PSItMjk3LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+Q2xpZW50PC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTI2MC41IDM5LC0yODguNSA2NywtMjg4LjUgNjcsLTI2MC41IDM5LC0yNjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQzLjYyIiB5PSItMjY5LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlBLPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjg4LjUgNjcsLTI4OC41IDY3LC0yNjAuNSAxNTEsLTI2MC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzEuODgiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gY2xpZW50PC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjYwLjUgMjY5LC0yNjAuNSAyNjksLTI4OC41IDE1MSwtMjg4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzQiIHk9Ii0yNjkuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM5LC0yMzIuNSAzOSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAzOSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MC43NSIgeT0iLTI0MS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjYwLjUgNjcsLTI2MC41IDY3LC0yMzIuNSAxNTEsLTIzMi41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNzIiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+Tm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjMyLjUgMjY5LC0yMzIuNSAyNjksLTI2MC41IDE1MSwtMjYwLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yNDEuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTIwNC41IDM5LC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDM5LC0yMDQuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMjEzLjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTUxLC0yMzIuNSA2NywtMjMyLjUgNjcsLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTIxMy4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QcsOpbm9tPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMjA0LjUgMjY5LC0yMDQuNSAyNjksLTIzMi41IDE1MSwtMjMyLjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0yMTMuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMzksLTE3Ni41IDM5LC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDM5LC0xNzYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjUwLjc1IiB5PSItMTg1LjI1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTUxLC0yMDQuNSA2NywtMjA0LjUgNjcsLTE3Ni41IDE1MSwtMTc2LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI3MiIgeT0iLTE4NS4yNSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5BZHJlc3NlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE1MSwtMTc2LjUgMjY5LC0xNzYuNSAyNjksLTIwNC41IDE1MSwtMjA0LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNTYiIHk9Ii0xODUuMjUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUigyNTUpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2Q5ZjBkMyIgc3Ryb2tlPSJub25lIiBwb2ludHM9IjgsLTQgOCwtMTE5IDMwMCwtMTE5IDMwMCwtNCA4LC00Ii8+Cjxwb2x5Z29uIGZpbGw9IiNhNmRiYTAiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSI4LC04OCA4LC0xMTkgMzAwLC0xMTkgMzAwLC04OCA4LC04OCIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtODggOCwtMTE5IDMwMCwtMTE5IDMwMCwtODggOCwtODgiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxMDIuMjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPkNvbW1hbmRlPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtNjAgOCwtODggMzYsLTg4IDM2LC02MCA4LC02MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjEyLjYyIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC04OCAzNiwtODggMzYsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MC43NSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk51bS4gY29tbWFuZGU8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC02MCAzMDAsLTYwIDMwMCwtODggMTczLC04OCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIwNSIgeT0iLTY4Ljc1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPlZBUkNIQVIoOCk8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI4LC0zMiA4LC02MCAzNiwtNjAgMzYsLTMyIDgsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTkuNzUiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj4gPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE3MywtNjAgMzYsLTYwIDM2LC0zMiAxNzMsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDEiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EYXRlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjE3MywtMzIgMzAwLC0zMiAzMDAsLTYwIDE3MywtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIyNTkiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5EQVRFPC90ZXh0Pgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iOCwtNCA4LC0zMiAzNiwtMzIgMzYsLTQgOCwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE5Ljc1IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+IDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIxNzMsLTMyIDM2LC0zMiAzNiwtNCAxNzMsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPk1vbnRhbnQ8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iMTczLC00IDMwMCwtNCAzMDAsLTMyIDE3MywtMzIiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxNzgiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5ERUNJTUFMKDEwLDIpPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7Jmd0OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7Jmd0OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiM5OTcwYWIiIGQ9Ik0xNTQsLTE2Mi45NEMxNTQsLTE1NS45NSAxNTQsLTE0OC44OSAxNTQsLTE0MS45MyIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU5LC0xNzEuNzUgMTQ5LC0xNzEuNzUgMTQ5LC0xNjkuNzUgMTU5LC0xNjkuNzUgMTU5LC0xNzEuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIxNTQsLTE3Mi43NSAxNTQsLTE2Ny43NSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU5LC0xNjYuNzUgMTQ5LC0xNjYuNzUgMTQ5LC0xNjQuNzUgMTU5LC0xNjQuNzUgMTU5LC0xNjYuNzUiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIxNTQsLTE2Ny43NSAxNTQsLTE2Mi43NSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMTU0LC0xMzMuMDYgMTU4LjUsLTEyMy4wNiAxNTQsLTEyNy43MyAxNTQsLTEyMy40IDE1NCwtMTIzLjQgMTU0LC0xMjMuNCAxNTQsLTEyNy43MyAxNDkuNSwtMTIzLjA2IDE1NCwtMTMzLjA2Ii8+CjxlbGxpcHNlIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgY3g9IjE1NCIgY3k9Ii0xMzguNzgiIHJ4PSI0IiByeT0iNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIiIHk9Ii0xNDQuMDUiIGZvbnQtZmFtaWx5PSJGdXR1cmEiIGZvbnQtc2l6ZT0iMTEuMDAiIGZpbGw9IiMxYjc4MzciPlBhc3NlcjwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjE4LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjE4LjUgMzU2LjUsLTIxOC41Ii8+Cjxwb2x5Z29uIGZpbGw9IiNhNmRiYTAiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIzNTYuNSwtMjQ2LjUgMzU2LjUsLTI3Ny41IDUzMy41LC0yNzcuNSA1MzMuNSwtMjQ2LjUgMzU2LjUsLTI0Ni41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDE0LjYyIiB5PSItMjU1LjQiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxOC4wMCIgZmlsbD0iIzAwMDAwMCI+SW5jbHVyZTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1Ni41LC0yMTguNSAzNTYuNSwtMjQ2LjUgMzg0LjUsLTI0Ni41IDM4NC41LC0yMTguNSAzNTYuNSwtMjE4LjUiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNjEuMTIiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UEs8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDYwLjUsLTI0Ni41IDM4NC41LC0yNDYuNSAzODQuNSwtMjE4LjUgNDYwLjUsLTIxOC41Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg5LjUiIHk9Ii0yMjcuMjUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UXVhbnRpdMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ2MC41LC0yMTguNSA1MzMuNSwtMjE4LjUgNTMzLjUsLTI0Ni41IDQ2MC41LC0yNDYuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ2NS41IiB5PSItMjI3LjI1IiBmb250LWZhbWlseT0iQ291cmllcixtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPklOVEVHRVI8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmZ3Q7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmZ3Q7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgc3Ryb2tlLWRhc2hhcnJheT0iMSw1IiBkPSJNMzgxLjA3LC0yMDYuNDdDMzQ0Ljg5LC0xODMuNTMgMjk4Ljc4LC0xNTQuMyAyNTcuNTgsLTEyOC4xNyIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMzg1LjI1LC0yMDkuMTIgMzkxLjI5LC0yMTguMjcgMzg5Ljc2LC0yMTEuOTcgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzkzLjQxLC0yMTQuMjkgMzg5Ljc2LC0yMTEuOTcgMzk2LjExLC0yMTAuNjcgMzg1LjI1LC0yMDkuMTIiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjM4Ni4wNSwtMjAzLjcxIDM4MC43LC0yMTIuMTUgMzc5LjAxLC0yMTEuMDggMzg0LjM3LC0yMDIuNjQgMzg2LjA1LC0yMDMuNzEiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIzODQuMjIsLTIwOC40NyAzODAsLTIwNS43OSIvPgo8cG9seWdvbiBmaWxsPSIjOTk3MGFiIiBzdHJva2U9IiM5OTcwYWIiIHBvaW50cz0iMjQ3LjMsLTEyNy41OCAyNTIuNjYsLTExOS4xMyAyNTQuMzUsLTEyMC4yIDI0OC45OSwtMTI4LjY1IDI0Ny4zLC0xMjcuNTgiLz4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIyNDkuMTQsLTEyMi44MiAyNTMuMzYsLTEyNS41Ii8+Cjxwb2x5Z29uIGZpbGw9IiM5OTcwYWIiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSIyNTEuNTMsLTEzMC4yNSAyNTYuODgsLTEyMS44MSAyNTguNTcsLTEyMi44OCAyNTMuMjIsLTEzMS4zMyAyNTEuNTMsLTEzMC4yNSIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjI1My4zNiwtMTI1LjUgMjU3LjU4LC0xMjguMTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjk4LjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMWI3ODM3Ij5ERjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNkOWYwZDMiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSIzNTIsLTQgMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC00IDM1MiwtNCIvPgo8cG9seWdvbiBmaWxsPSIjYTZkYmEwIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iMzUyLC04OCAzNTIsLTExOSA2MDgsLTExOSA2MDgsLTg4IDM1MiwtODgiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtODggMzUyLC0xMTkgNjA4LC0xMTkgNjA4LC04OCAzNTIsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDQ4LjUiIHk9Ii05Ni45IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTguMDAiIGZpbGw9IiMwMDAwMDAiPlByb2R1aXQ8L3RleHQ+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSIzNTIsLTYwIDM1MiwtODggMzgwLC04OCAzODAsLTYwIDM1MiwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzNTYuNjIiIHk9Ii02OC43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5QSzwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI0ODEsLTg4IDM4MCwtODggMzgwLC02MCA0ODEsLTYwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzg1IiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2Esc2Fucy1TZXJpZiIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KPHBvbHlsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVhYWU2MSIgcG9pbnRzPSI0ODEsLTYwIDYwOCwtNjAgNjA4LC04OCA0ODEsLTg4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNTEzIiB5PSItNjguNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+VkFSQ0hBUig4KTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtMzIgMzUyLC02MCAzODAsLTYwIDM4MCwtMzIgMzUyLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDgxLC02MCAzODAsLTYwIDM4MCwtMzIgNDgxLC0zMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM4NSIgeT0iLTQwLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPkxpYmVsbMOpPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ4MSwtMzIgNjA4LC0zMiA2MDgsLTYwIDQ4MSwtNjAiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI1MDQiIHk9Ii00MC43NSIgZm9udC1mYW1pbHk9IkNvdXJpZXIsbW9ub3NwYWNlIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5WQVJDSEFSKDUwKTwvdGV4dD4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjM1MiwtNCAzNTIsLTMyIDM4MCwtMzIgMzgwLC00IDM1MiwtNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjM2My43NSIgeT0iLTEyLjc1IiBmb250LWZhbWlseT0iSGVsdmV0aWNhLHNhbnMtU2VyaWYiIGZvbnQtc2l6ZT0iMTUuMDAiIGZpbGw9IiMwMDAwMDAiPiA8L3RleHQ+Cjxwb2x5bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiM1YWFlNjEiIHBvaW50cz0iNDgxLC0zMiAzODAsLTMyIDM4MCwtNCA0ODEsLTQiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzODQuNzUiIHk9Ii0xMi43NSIgZm9udC1mYW1pbHk9IkhlbHZldGljYSxzYW5zLVNlcmlmIiBmb250LXNpemU9IjE1LjAwIiBmaWxsPSIjMDAwMDAwIj5Qcml4IHVuaXRhaXJlPC90ZXh0Pgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNWFhZTYxIiBwb2ludHM9IjQ4MSwtNCA2MDgsLTQgNjA4LC0zMiA0ODEsLTMyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDg2IiB5PSItMTIuNzUiIGZvbnQtZmFtaWx5PSJDb3VyaWVyLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNS4wMCIgZmlsbD0iIzAwMDAwMCI+REVDSU1BTCgxMCwyKTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyZndDs0IC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyZndDs0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBzdHJva2UtZGFzaGFycmF5PSIxLDUiIGQ9Ik00NTQuNywtMTk1Ljg3QzQ1OC40MiwtMTc2LjI3IDQ2Mi43MywtMTUzLjU2IDQ2Ni43MiwtMTMyLjUiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ1My4wMiwtMjA0LjcxIDQ0Ni43NCwtMjEzLjcgNDUyLjAzLC0yMDkuOTUgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUxLjIyLC0yMTQuMjEgNDUyLjAzLC0yMDkuOTUgNDU1LjU4LC0yMTUuMzcgNDUzLjAyLC0yMDQuNzEiLz4KPGVsbGlwc2UgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBjeD0iNDU0LjA5IiBjeT0iLTE5OS4wOSIgcng9IjQiIHJ5PSI0Ii8+Cjxwb2x5Z29uIGZpbGw9IiM5OTcwYWIiIHN0cm9rZT0iIzk5NzBhYiIgcG9pbnRzPSI0NjMuNDMsLTEyMyA0NzMuMjYsLTEyNC44NyA0NzIuODksLTEyNi44MyA0NjMuMDYsLTEyNC45NyA0NjMuNDMsLTEyMyIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2OC41MywtMTIyLjk1IDQ2Ny42LC0xMjcuODYiLz4KPHBvbHlnb24gZmlsbD0iIzk5NzBhYiIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2Mi41LC0xMjcuOTIgNDcyLjMzLC0xMjkuNzggNDcxLjk1LC0xMzEuNzQgNDYyLjEzLC0xMjkuODggNDYyLjUsLTEyNy45MiIvPgo8cG9seWxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTk3MGFiIiBwb2ludHM9IjQ2Ny42LC0xMjcuODYgNDY2LjY3LC0xMzIuNzgiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDcyLjEyIiB5PSItMTQ0LjA1IiBmb250LWZhbWlseT0iRnV0dXJhIiBmb250LXNpemU9IjExLjAwIiBmaWxsPSIjMWI3ODM3Ij5ERjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t crow --defer --colors brewer+3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il est également possible de demander une sortie au format Mermaid. Vous en avez un exemple dans l'introduction, nous ne le répétons pas ici. Le DSL de Mermaid est de plus haut niveau, non encombré d'informations de style. Cependant, le format Graphviz peut être préféré pour plusieurs raisons :\\n\",\n    \"\\n\",\n    \"- on peut lui appliquer une palette de couleurs de Mocodo (cf. ci-dessus) ;\\n\",\n    \"- il gère les accents ;\\n\",\n    \"- il admet la virgule dans les types (Mermaid demande [actuellement](https://github.com/mermaid-js/mermaid/issues/1546) à transformer `DECIMAL(10,2)` en `DECIMAL(10-2)`) ;\\n\",\n    \"- il peut produire de meilleurs plongements (notamment en jouant sur la valeur de l'option `--seed`) ;\\n\",\n    \"- ceux-ci peuvent-être rectifiés à la main (quoique péniblement).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Dictionnaire des données\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez extraire sous forme de table diverses informations sur les attributs de votre MCD.\\n\",\n    \"\\n\",\n    \"Un format possible est TSV. Dans ce cas, sous Jupyter Notebook, si la bibliothèque `pandas` est installée, elle sera rendue comme un _dataframe_ :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 89,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_data_dict_3.tsv\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style type=\\\"text/css\\\">\\n\",\n       \"#T_83121 th {\\n\",\n       \"  text-align: left;\\n\",\n       \"}\\n\",\n       \"#T_83121_row0_col0, #T_83121_row0_col1, #T_83121_row0_col2, #T_83121_row1_col0, #T_83121_row1_col1, #T_83121_row1_col2, #T_83121_row2_col0, #T_83121_row2_col1, #T_83121_row2_col2, #T_83121_row3_col0, #T_83121_row3_col1, #T_83121_row3_col2, #T_83121_row4_col0, #T_83121_row4_col1, #T_83121_row4_col2, #T_83121_row5_col0, #T_83121_row5_col1, #T_83121_row5_col2, #T_83121_row6_col0, #T_83121_row6_col1, #T_83121_row6_col2, #T_83121_row7_col0, #T_83121_row7_col1, #T_83121_row7_col2, #T_83121_row8_col0, #T_83121_row8_col1, #T_83121_row8_col2, #T_83121_row9_col0, #T_83121_row9_col1, #T_83121_row9_col2, #T_83121_row10_col0, #T_83121_row10_col1, #T_83121_row10_col2 {\\n\",\n       \"  text-align: left;\\n\",\n       \"}\\n\",\n       \"</style>\\n\",\n       \"<table id=\\\"T_83121\\\">\\n\",\n       \"  <thead>\\n\",\n       \"    <tr>\\n\",\n       \"      <th class=\\\"blank level0\\\" >&nbsp;</th>\\n\",\n       \"      <th id=\\\"T_83121_level0_col0\\\" class=\\\"col_heading level0 col0\\\" >Entité ou association</th>\\n\",\n       \"      <th id=\\\"T_83121_level0_col1\\\" class=\\\"col_heading level0 col1\\\" >Libellé de l'attribut</th>\\n\",\n       \"      <th id=\\\"T_83121_level0_col2\\\" class=\\\"col_heading level0 col2\\\" >Type</th>\\n\",\n       \"    </tr>\\n\",\n       \"  </thead>\\n\",\n       \"  <tbody>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row0\\\" class=\\\"row_heading level0 row0\\\" >0</th>\\n\",\n       \"      <td id=\\\"T_83121_row0_col0\\\" class=\\\"data row0 col0\\\" >Client</td>\\n\",\n       \"      <td id=\\\"T_83121_row0_col1\\\" class=\\\"data row0 col1\\\" >Adresse</td>\\n\",\n       \"      <td id=\\\"T_83121_row0_col2\\\" class=\\\"data row0 col2\\\" >VARCHAR(255)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row1\\\" class=\\\"row_heading level0 row1\\\" >1</th>\\n\",\n       \"      <td id=\\\"T_83121_row1_col0\\\" class=\\\"data row1 col0\\\" >Client</td>\\n\",\n       \"      <td id=\\\"T_83121_row1_col1\\\" class=\\\"data row1 col1\\\" >Nom</td>\\n\",\n       \"      <td id=\\\"T_83121_row1_col2\\\" class=\\\"data row1 col2\\\" >VARCHAR(255)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row2\\\" class=\\\"row_heading level0 row2\\\" >2</th>\\n\",\n       \"      <td id=\\\"T_83121_row2_col0\\\" class=\\\"data row2 col0\\\" >Client</td>\\n\",\n       \"      <td id=\\\"T_83121_row2_col1\\\" class=\\\"data row2 col1\\\" >Prénom</td>\\n\",\n       \"      <td id=\\\"T_83121_row2_col2\\\" class=\\\"data row2 col2\\\" >VARCHAR(255)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row3\\\" class=\\\"row_heading level0 row3\\\" >3</th>\\n\",\n       \"      <td id=\\\"T_83121_row3_col0\\\" class=\\\"data row3 col0\\\" >Client</td>\\n\",\n       \"      <td id=\\\"T_83121_row3_col1\\\" class=\\\"data row3 col1\\\" >Réf. client</td>\\n\",\n       \"      <td id=\\\"T_83121_row3_col2\\\" class=\\\"data row3 col2\\\" >VARCHAR(8)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row4\\\" class=\\\"row_heading level0 row4\\\" >4</th>\\n\",\n       \"      <td id=\\\"T_83121_row4_col0\\\" class=\\\"data row4 col0\\\" >Commande</td>\\n\",\n       \"      <td id=\\\"T_83121_row4_col1\\\" class=\\\"data row4 col1\\\" >Date</td>\\n\",\n       \"      <td id=\\\"T_83121_row4_col2\\\" class=\\\"data row4 col2\\\" >DATE</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row5\\\" class=\\\"row_heading level0 row5\\\" >5</th>\\n\",\n       \"      <td id=\\\"T_83121_row5_col0\\\" class=\\\"data row5 col0\\\" >Commande</td>\\n\",\n       \"      <td id=\\\"T_83121_row5_col1\\\" class=\\\"data row5 col1\\\" >Montant</td>\\n\",\n       \"      <td id=\\\"T_83121_row5_col2\\\" class=\\\"data row5 col2\\\" >DECIMAL(10,2)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row6\\\" class=\\\"row_heading level0 row6\\\" >6</th>\\n\",\n       \"      <td id=\\\"T_83121_row6_col0\\\" class=\\\"data row6 col0\\\" >Commande</td>\\n\",\n       \"      <td id=\\\"T_83121_row6_col1\\\" class=\\\"data row6 col1\\\" >Num. commande</td>\\n\",\n       \"      <td id=\\\"T_83121_row6_col2\\\" class=\\\"data row6 col2\\\" >VARCHAR(8)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row7\\\" class=\\\"row_heading level0 row7\\\" >7</th>\\n\",\n       \"      <td id=\\\"T_83121_row7_col0\\\" class=\\\"data row7 col0\\\" >Inclure</td>\\n\",\n       \"      <td id=\\\"T_83121_row7_col1\\\" class=\\\"data row7 col1\\\" >Quantité</td>\\n\",\n       \"      <td id=\\\"T_83121_row7_col2\\\" class=\\\"data row7 col2\\\" >INTEGER</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row8\\\" class=\\\"row_heading level0 row8\\\" >8</th>\\n\",\n       \"      <td id=\\\"T_83121_row8_col0\\\" class=\\\"data row8 col0\\\" >Produit</td>\\n\",\n       \"      <td id=\\\"T_83121_row8_col1\\\" class=\\\"data row8 col1\\\" >Libellé</td>\\n\",\n       \"      <td id=\\\"T_83121_row8_col2\\\" class=\\\"data row8 col2\\\" >VARCHAR(50)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row9\\\" class=\\\"row_heading level0 row9\\\" >9</th>\\n\",\n       \"      <td id=\\\"T_83121_row9_col0\\\" class=\\\"data row9 col0\\\" >Produit</td>\\n\",\n       \"      <td id=\\\"T_83121_row9_col1\\\" class=\\\"data row9 col1\\\" >Prix unitaire</td>\\n\",\n       \"      <td id=\\\"T_83121_row9_col2\\\" class=\\\"data row9 col2\\\" >DECIMAL(10,2)</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th id=\\\"T_83121_level0_row10\\\" class=\\\"row_heading level0 row10\\\" >10</th>\\n\",\n       \"      <td id=\\\"T_83121_row10_col0\\\" class=\\\"data row10 col0\\\" >Produit</td>\\n\",\n       \"      <td id=\\\"T_83121_row10_col1\\\" class=\\\"data row10 col1\\\" >Réf. produit</td>\\n\",\n       \"      <td id=\\\"T_83121_row10_col2\\\" class=\\\"data row10 col2\\\" >VARCHAR(8)</td>\\n\",\n       \"    </tr>\\n\",\n       \"  </tbody>\\n\",\n       \"</table>\\n\"\n      ],\n      \"text/plain\": [\n       \"<pandas.io.formats.style.Styler at 0x1184d33d0>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t data_dict:tsv\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le format par défaut est Markdown. Vous pouvez préciser en sous-sous-option tout ou partie des colonnes suivantes dans l'ordre où vous les souhaitez :\\n\",\n    \"\\n\",\n    \"- `label`: le libellé de l'attribut ;\\n\",\n    \"- `type` : son type ou un descriptif (auquel cas il conviendra de changer le nom de la colonne) ;\\n\",\n    \"- `box` : le nom de l'entité ou association où il se trouve.\\n\",\n    \"\\n\",\n    \"Entourez ces noms de colonnes de balises Markdown pour les mettre en forme (pas d'incidence en TSV). Faites-les suivre de `=\\\"Nom de colonne personnalisé\\\"` pour éviter la valeur par défaut (dépendante de l'option `language`). Dans l'exemple ci-dessous, les sous-sous-options se décodent ainsi :\\n\",\n    \"\\n\",\n    \"- `**box**=\\\"Entité ou association\\\"` : boîtes en colonne 1, en-tête personnalisé, cellules en gras ;\\n\",\n    \"- `label` : libellé des attributs en colonne 2 ;\\n\",\n    \"- \\\\``type`\\\\``=`\\\\``Type`\\\\` : types en colonne 3, en-tête personnalisé et cellules dans une police non proportionnelle.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 90,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_data_dict_3.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"| **Entité ou<br>association** | Libellé de l'attribut | ``Type de données`` |\\n\",\n       \"|:-----------------------------|:----------------------|:--------------------|\\n\",\n       \"| **Client**                   | Adresse               | `VARCHAR(255)`      |\\n\",\n       \"| **\\\"**                        | Nom                   | `VARCHAR(255)`      |\\n\",\n       \"| **\\\"**                        | Prénom                | `VARCHAR(255)`      |\\n\",\n       \"| **\\\"**                        | Réf. client           | `VARCHAR(8)`        |\\n\",\n       \"| **Commande**                 | Date                  | `DATE`              |\\n\",\n       \"| **\\\"**                        | Montant               | `DECIMAL(10,2)`     |\\n\",\n       \"| **\\\"**                        | Num. commande         | `VARCHAR(8)`        |\\n\",\n       \"| **Inclure**                  | Quantité              | `INTEGER`           |\\n\",\n       \"| **Produit**                  | Libellé               | `VARCHAR(50)`       |\\n\",\n       \"| **\\\"**                        | Prix unitaire         | `DECIMAL(10,2)`     |\\n\",\n       \"| **\\\"**                        | Réf. produit          | `VARCHAR(8)`        |\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t data_dict:**box**=\\\"Entité ou<br>association\\\",label,`type`=`\\\"Type de données\\\"`\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Aménités.**\\n\",\n    \"\\n\",\n    \"- Au format Markdown, les répétitions de cellules de la _première_ colonne sont remplacées par un guillemet itératif.\\n\",\n    \"- Le tableau est automatiquement trié selon sa première, puis éventuellement deuxième et troisième colonnes.\\n\",\n    \"- Si une seule colonne est demandée, la ligne d'en-tête n'est pas générée et, en Markdown, c'est une liste qui est produite.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 91,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_data_dict_1.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- Adresse\\n\",\n       \"- Date\\n\",\n       \"- Libellé\\n\",\n       \"- Montant\\n\",\n       \"- Nom\\n\",\n       \"- Num. commande\\n\",\n       \"- Prix unitaire\\n\",\n       \"- Prénom\\n\",\n       \"- Quantité\\n\",\n       \"- Réf. client\\n\",\n       \"- Réf. produit\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t data_dict:label\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveautés de la version 4.0.**\\n\",\n    \"- Sélection, ordre et nommage des colonnes, mise en forme Markdown, tri, guillemets itératifs.\\n\",\n    \"- Remplacement par un algorithme dédié du gabarit relationnel utilisé (abusivement) dans les versions antérieures.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### URL de partage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez demander à encoder le texte-source de votre MCD dans un lien vers Mocodo online, qui le composera automatiquement dans la zone d'entrée :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 92,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_url.url\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"https://www.mocodo.net/?mcd=eNptkMEKgkAQhu89xRwLJDQQwtuySgm5mEgX6bDlBgu6xrYLvZLP4Ys1ahZYt_m_Yeb_Z2glhTIBZF17W8N1UFCcSEb3JFtuV2cHWFN_ycb3e5bqrlV_OCm1eDzEjC9SjlA74DKgg4UDnge0qWuuSrGYigCYrTHFW85yhNwgCkkeoUgaZXgfNYxonJDD0nOdDTrF6lpZLXA_--wffFPdlFbipUeLc9J0LRQxy6NdlGG-qTm-4T7Kmf9BXkRV9XMT9t3xF_IJVknDpRY_gV4LRG5Z\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t share\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Mocodo pour la pédagogie\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Vue en extension\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Un chiffre ou tiret bas à la fin du nom d'une boîte (entité ou association) est utilisé en interne pour distinguer cette boîte des autres, mais n'est pas affiché dans le diagramme conceptuel. Cela peut servir à produire une vue en extension d'un MCD.\\n\",\n    \"\\n\",\n    \"Voici par exemple le MCD que j'utilise en cours pour introduire la notion d'entité faible (à gauche, vue en compréhension, à droite vue en extension):\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 93,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"715\\\" height=\\\"294\\\" viewBox=\\\"0 0 715 294\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"715\\\" height=\\\"294\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"84\\\" y1=\\\"56\\\" x2=\\\"84\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"84\\\" y1=\\\"238\\\" x2=\\\"84\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"84\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"71\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"89\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"89\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"89\\\" y1=\\\"185\\\" x2=\\\"107\\\" y2=\\\"185\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"476\\\" y1=\\\"56\\\" x2=\\\"313\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"313\\\" y1=\\\"238\\\" x2=\\\"313\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"313\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"300\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"392.47\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"318\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"476\\\" y1=\\\"56\\\" x2=\\\"476\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"476\\\" y1=\\\"238\\\" x2=\\\"476\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"476\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"463\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"481\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"481\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"476\\\" y1=\\\"56\\\" x2=\\\"639\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"639\\\" y1=\\\"238\\\" x2=\\\"639\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"639\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"626\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"541.53\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"644\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"9\\\" width=\\\"136\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"39\\\" width=\\\"136\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"9\\\" width=\\\"136\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"16\\\" y1=\\\"39\\\" x2=\\\"152\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"50\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ŒUVRE</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cote</text>\\n\",\n       \"\\t<line x1=\\\"24\\\" y1=\\\"59\\\" x2=\\\"53\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date de publication</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"9\\\" width=\\\"254\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"39\\\" width=\\\"254\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"9\\\" width=\\\"254\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"349\\\" y1=\\\"39\\\" x2=\\\"603\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"442\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ŒUVRE</text>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">612.NAT.34</text>\\n\",\n       \"\\t<line x1=\\\"357\\\" y1=\\\"59\\\" x2=\\\"434\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">J’apprends à lire à mes souris blanches</text>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">mai 1975</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"150\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"150\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"150\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"159\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"25\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">numéro d’exemplaire</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"150\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">état</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date d’achat</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"246\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"246\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"246\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"246\\\" y1=\\\"221\\\" x2=\\\"380\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">1</text>\\n\",\n       \"\\t<line x1=\\\"254\\\" y1=\\\"241\\\" x2=\\\"263\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bon état</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">12/6/1975</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"409\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"409\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"409\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"409\\\" y1=\\\"221\\\" x2=\\\"543\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">2</text>\\n\",\n       \"\\t<line x1=\\\"417\\\" y1=\\\"241\\\" x2=\\\"426\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bon état</text>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">1/8/1977</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"572\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"572\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"572\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"572\\\" y1=\\\"221\\\" x2=\\\"706\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"580\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"580\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">3</text>\\n\",\n       \"\\t<line x1=\\\"580\\\" y1=\\\"241\\\" x2=\\\"589\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"580\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">reliure rongée</text>\\n\",\n       \"\\t<text x=\\\"580\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">3/4/2005</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"ŒUVRE1: cote, titre, date de publication\\n\",\n    \":::\\n\",\n    \"ŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\\n\",\n    \":\\n\",\n    \"  \\n\",\n    \"DF, 1N ŒUVRE1, _11 EXEMPLAIRE1\\n\",\n    \"::\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE2\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE3\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE4\\n\",\n    \"\\n\",\n    \"EXEMPLAIRE1: numéro d'exemplaire, état, date d'achat\\n\",\n    \"::\\n\",\n    \"EXEMPLAIRE2: 1, bon état, 12/6/1975\\n\",\n    \"EXEMPLAIRE3: 2, bon état, 1/8/1977\\n\",\n    \"EXEMPLAIRE4: 3, reliure rongée, 3/4/2005\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo n'interdit pas la conversion en relationnel d'un tel MCD, mais celle-ci n'a aucun sens.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Si l'on veut garder les cardinalités sans les afficher, on peut les préfixer d'un `-`. Le résultat de la conversion en relationnel peut alors être interprété comme l'ensemble des lignes des différentes tables.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 94,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"478\\\" height=\\\"294\\\" viewBox=\\\"0 0 478 294\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"478\\\" height=\\\"294\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"239\\\" y1=\\\"56\\\" x2=\\\"76\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"76\\\" y1=\\\"238\\\" x2=\\\"76\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"76\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"63\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"155.47\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"81\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"81\\\" y1=\\\"185\\\" x2=\\\"99\\\" y2=\\\"185\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"239\\\" y1=\\\"56\\\" x2=\\\"239\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"239\\\" y1=\\\"238\\\" x2=\\\"239\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"239\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"226\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"244\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"244\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"244\\\" y1=\\\"185\\\" x2=\\\"262\\\" y2=\\\"185\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"239\\\" y1=\\\"56\\\" x2=\\\"402\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"402\\\" y1=\\\"238\\\" x2=\\\"402\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"402\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"389\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"304.53\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"407\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"407\\\" y1=\\\"185\\\" x2=\\\"425\\\" y2=\\\"185\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"9\\\" width=\\\"254\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"39\\\" width=\\\"254\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"112\\\" y=\\\"9\\\" width=\\\"254\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"112\\\" y1=\\\"39\\\" x2=\\\"366\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ŒUVRE</text>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">612.NAT.34</text>\\n\",\n       \"\\t<line x1=\\\"120\\\" y1=\\\"59\\\" x2=\\\"197\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">J’apprends à lire à mes souris blanches</text>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">mai 1975</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"143\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">1</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"26\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bon état</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">12/6/1975</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"172\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"172\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"172\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"172\\\" y1=\\\"221\\\" x2=\\\"306\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">2</text>\\n\",\n       \"\\t<line x1=\\\"180\\\" y1=\\\"241\\\" x2=\\\"189\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bon état</text>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">1/8/1977</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"335\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"335\\\" y=\\\"221\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"335\\\" y=\\\"191\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"335\\\" y1=\\\"221\\\" x2=\\\"469\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"343\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"343\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">3</text>\\n\",\n       \"\\t<line x1=\\\"343\\\" y1=\\\"241\\\" x2=\\\"352\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"343\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">reliure rongée</text>\\n\",\n       \"\\t<text x=\\\"343\\\" y=\\\"272\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">3/4/2005</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **EXEMPLAIRE** (<u>_#612.NAT.34_</u>, <u>1</u>, bon état, 12/6/1975)\\n\",\n       \"- **EXEMPLAIRE** (<u>_#612.NAT.34_</u>, <u>2</u>, bon état, 1/8/1977)\\n\",\n       \"- **EXEMPLAIRE** (<u>_#612.NAT.34_</u>, <u>3</u>, reliure rongée, 3/4/2005)\\n\",\n       \"- **ŒUVRE** (<u>612.NAT.34</u>, J'apprends à lire à mes souris blanches, mai 1975)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"ŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\\n\",\n    \"  \\n\",\n    \"DF, -1N ŒUVRE, -_11 EXEMPLAIRE1\\n\",\n    \"DF, -1N ŒUVRE, -_11 EXEMPLAIRE2\\n\",\n    \"DF, -1N ŒUVRE, -_11 EXEMPLAIRE3\\n\",\n    \"\\n\",\n    \"EXEMPLAIRE1: 1, bon état, 12/6/1975\\n\",\n    \"EXEMPLAIRE2: 2, bon état, 1/8/1977\\n\",\n    \"EXEMPLAIRE3: 3, reliure rongée, 3/4/2005\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## MCD interactif\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Afficher des explications au survol\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut être incluse dans le texte-source en annotant les pattes correspondantes. Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 95,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"691\\\" height=\\\"112\\\" viewBox=\\\"0 0 691 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"691\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"307\\\" y1=\\\"56\\\" x2=\\\"175\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"56\\\" y1=\\\"56\\\" x2=\\\"175\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M204 27 a14 14 90 0 1 14 14 V55 h-86 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M218 55 v16 a14 14 90 0 1 -14 14 H146 a14 14 90 0 1 -14 -14 V55 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"27\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"55\\\" x2=\\\"218\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"139\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"139\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"223\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Une commande inclut au moins un produit.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Un produit peut être commandé un nombre quelconque de fois.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"504\\\" y1=\\\"56\\\" x2=\\\"416\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"307\\\" y1=\\\"56\\\" x2=\\\"416\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"416\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"403\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"441\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Un client peut passer zéro (prospect) ou plusieurs commandes.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"372\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Une commande est passée par un et un seul client.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association PARRAINER -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M504 56 C533.67 24 574.67 24 627 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M504 56 C534.33 88 575.33 88 627 56\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M668 27 a14 14 90 0 1 14 14 V55 h-110 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M682 55 v16 a14 14 90 0 1 -14 14 H586 a14 14 90 0 1 -14 -14 V55 H110\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"572\\\" y=\\\"27\\\" width=\\\"110\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"572\\\" y1=\\\"55\\\" x2=\\\"682\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"580\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Parrainer</text>\\n\",\n       \"\\t\\t<text x=\\\"579\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date parrainage</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"548\\\" y=\\\"49\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Un client peut avoir été parrainé ou non.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"548\\\" y=\\\"71\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_eacbdfe3(evt,'Un client peut parrainer d’autres clients.')\\\" onmouseout=\\\"hide_eacbdfe3(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"103\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"20\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"89\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"247\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"247\\\" y=\\\"39\\\" width=\\\"120\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"247\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"247\\\" y1=\\\"39\\\" x2=\\\"367\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"255\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"255\\\" y1=\\\"59\\\" x2=\\\"359\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"255\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"255\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g class=\\\"page_0_eacbdfe3 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"465\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"465\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"465\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"465\\\" y1=\\\"39\\\" x2=\\\"543\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"474\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"473\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. client</text>\\n\",\n       \"\\t<line x1=\\\"473\\\" y1=\\\"59\\\" x2=\\\"532\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"473\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"473\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_eacbdfe3(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 67) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_eacbdfe3\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_eacbdfe3\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_eacbdfe3(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_eacbdfe3\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_eacbdfe3\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_eacbdfe3\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_eacbdfe3\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_eacbdfe3\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_eacbdfe3\\\" text-anchor=\\\"middle\\\" x=\\\"345\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_eacbdfe3\\\" x=\\\"0\\\" y=\\\"72\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_eacbdfe3\\\" text-anchor=\\\"middle\\\" x=\\\"345\\\" y=\\\"96\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N [Une commande inclut au moins un produit.] Commande, 0N [Un produit peut être commandé un nombre quelconque de fois.] Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N [Un client peut passer zéro (prospect) ou plusieurs commandes.] Client, 11 [Une commande est passée par un et un seul client.] Commande\\n\",\n    \"Client: réf. client, nom, adresse\\n\",\n    \"Parrainer, 01 [Un client peut avoir été parrainé ou non.] Client, 0N [Un client peut parrainer d'autres clients.] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.3.** Avec l'option `-t prompt:cards`, Mocodo compose un _prompt_ à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec de telles descriptions. Ce _prompt_ est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les explications générées par [DeepSeek](https://chat.deepseek.com) pour le MCD de la page d'accueil de Mocodo online :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 96,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"764\\\" height=\\\"276\\\" viewBox=\\\"0 0 764 276\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"764\\\" height=\\\"276\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"250\\\" y1=\\\"138\\\" x2=\\\"250\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"401\\\" y1=\\\"138\\\" x2=\\\"250\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M282 18 a14 14 90 0 1 14 14 V46 h-92 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M296 46 v16 a14 14 90 0 1 -14 14 H218 a14 14 90 0 1 -14 -14 V46 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"18\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"204\\\" y1=\\\"46\\\" x2=\\\"296\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"212\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"255\\\" y=\\\"92\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un employé peut diriger zéro ou un projet.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"333\\\" y=\\\"122.22\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un projet est dirigé par au plus un employé.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"401\\\" y1=\\\"138\\\" x2=\\\"401\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"545\\\" y1=\\\"47\\\" x2=\\\"401\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M443 18 a14 14 90 0 1 14 14 V46 h-112 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M457 46 v16 a14 14 90 0 1 -14 14 H359 a14 14 90 0 1 -14 -14 V46 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"345\\\" y=\\\"18\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"345\\\" y1=\\\"46\\\" x2=\\\"457\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"353\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">REQUÉRIR</text>\\n\",\n       \"\\t\\t<text x=\\\"352\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté requise</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"406\\\" y=\\\"92\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un projet requiert au moins une pièce.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"476\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une pièce peut être requise par plusieurs projets.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M545 47 C576 15 624.33 15 690 47\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M545 47 C576 79 624.33 79 690 47\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M736 18 a14 14 90 0 1 14 14 V46 h-120 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M750 46 v16 a14 14 90 0 1 -14 14 H644 a14 14 90 0 1 -14 -14 V46 H120\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"630\\\" y=\\\"18\\\" width=\\\"120\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"630\\\" y1=\\\"46\\\" x2=\\\"750\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"637\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMPOSER</text>\\n\",\n       \"\\t\\t<text x=\\\"637\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"595\\\" y=\\\"40\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une pièce peut être composée de plusieurs autres pièces.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"595\\\" y=\\\"62\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une pièce peut entrer dans la composition de plusieurs autres pièces.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"86\\\" y1=\\\"47\\\" x2=\\\"86\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"250\\\" y1=\\\"138\\\" x2=\\\"86\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"86\\\" cy=\\\"138\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"73\\\" y=\\\"142.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"91\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un ayant-droit est associé à un et un seul employé.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"91\\\" y1=\\\"103\\\" x2=\\\"109\\\" y2=\\\"103\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"174\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un employé peut avoir plusieurs ayants-droit.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"401\\\" y1=\\\"138\\\" x2=\\\"545\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"545\\\" y1=\\\"47\\\" x2=\\\"545\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"545\\\" y1=\\\"229\\\" x2=\\\"545\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M581 109 a14 14 90 0 1 14 14 V137 h-100 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M595 137 v16 a14 14 90 0 1 -14 14 H509 a14 14 90 0 1 -14 -14 V137 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"109\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"495\\\" y1=\\\"137\\\" x2=\\\"595\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"503\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOURNIR</text>\\n\",\n       \"\\t\\t<text x=\\\"502\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté fournie</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"451\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un projet est fourni par au moins une société.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"550\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une pièce est fournie par au moins une société.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"550\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une société fournit au moins une pièce pour un projet.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EMPLOYER -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"250\\\" y1=\\\"138\\\" x2=\\\"250\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"86\\\" y1=\\\"229\\\" x2=\\\"250\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M294 200 a14 14 90 0 1 14 14 V228 h-116 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M308 228 v16 a14 14 90 0 1 -14 14 H206 a14 14 90 0 1 -14 -14 V228 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"192\\\" y=\\\"200\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"192\\\" y1=\\\"228\\\" x2=\\\"308\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"200\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"227\\\" y=\\\"192\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un employé appartient à un et un seul département.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"168\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un département emploie au moins un employé.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"250\\\" y1=\\\"138\\\" x2=\\\"401\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"401\\\" y1=\\\"138\\\" x2=\\\"401\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M451 200 a14 14 90 0 1 14 14 V228 h-128 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M465 228 v16 a14 14 90 0 1 -14 14 H351 a14 14 90 0 1 -14 -14 V228 H128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"337\\\" y=\\\"200\\\" width=\\\"128\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"337\\\" y1=\\\"228\\\" x2=\\\"465\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"344\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TRAVAILLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"307\\\" y=\\\"166.0\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un employé peut travailler sur plusieurs projets.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"406\\\" y=\\\"192\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Un projet implique au moins un employé.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONTROLER -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M545 229 C584 197 632.33 197 690 229\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"624.99 205.92 612.34 210.39 617.05 204.93 613.83 198.48\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M545 229 C583.33 261 631.67 261 690 229\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M741 200 a14 14 90 0 1 14 14 V228 h-130 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M755 228 v16 a14 14 90 0 1 -14 14 H639 a14 14 90 0 1 -14 -14 V228 H130\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"625\\\" y=\\\"200\\\" width=\\\"130\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"625\\\" y1=\\\"228\\\" x2=\\\"755\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"632\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CONTRÔLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"601\\\" y=\\\"222\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une société peut en contrôler une autre.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"601\\\" y=\\\"244\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_7adbbe8c(evt,'Une société est contrôlée par au plus une autre société.')\\\" onmouseout=\\\"hide_7adbbe8c(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AYANT_DROIT -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"39\\\" width=\\\"140\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"16\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"16\\\" y1=\\\"39\\\" x2=\\\"156\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">AYANT-DROIT</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom ayant-droit</text>\\n\",\n       \"\\t<line x1=\\\"24\\\" y1=\\\"59\\\" x2=\\\"125\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lien</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"500\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"500\\\" y=\\\"39\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"500\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"500\\\" y1=\\\"39\\\" x2=\\\"590\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"517\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"508\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"508\\\" y1=\\\"59\\\" x2=\\\"566\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"508\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"198\\\" y=\\\"100\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"198\\\" y=\\\"130\\\" width=\\\"104\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"198\\\" y=\\\"100\\\" width=\\\"104\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"198\\\" y1=\\\"130\\\" x2=\\\"302\\\" y2=\\\"130\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"206\\\" y=\\\"121.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"206\\\" y=\\\"147.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">matricule</text>\\n\",\n       \"\\t<line x1=\\\"206\\\" y1=\\\"150\\\" x2=\\\"265\\\" y2=\\\"150\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"206\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"356\\\" y=\\\"100\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"356\\\" y=\\\"130\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"356\\\" y=\\\"100\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"356\\\" y1=\\\"130\\\" x2=\\\"446\\\" y2=\\\"130\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"365\\\" y=\\\"121.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"364\\\" y=\\\"147.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"150\\\" x2=\\\"438\\\" y2=\\\"150\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"364\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"154\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"154\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"154\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"163\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. département</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"132\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_7adbbe8c diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"494\\\" y=\\\"191\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"494\\\" y=\\\"221\\\" width=\\\"102\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"494\\\" y=\\\"191\\\" width=\\\"102\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"494\\\" y1=\\\"221\\\" x2=\\\"596\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"505\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SOCIÉTÉ</text>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"502\\\" y1=\\\"241\\\" x2=\\\"582\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_7adbbe8c(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 231) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_7adbbe8c\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_7adbbe8c\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_7adbbe8c(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_7adbbe8c\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_7adbbe8c\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_7adbbe8c\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_7adbbe8c\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_7adbbe8c\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_7adbbe8c\\\" text-anchor=\\\"middle\\\" x=\\\"382\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_7adbbe8c\\\" x=\\\"0\\\" y=\\\"236\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_7adbbe8c\\\" text-anchor=\\\"middle\\\" x=\\\"382\\\" y=\\\"260\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"AYANT-DROIT: nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [Un employé peut diriger zéro ou un projet.] EMPLOYÉ, 01 [Un projet est dirigé par au plus un employé.] PROJET\\n\",\n    \"REQUÉRIR, 1N [Un projet requiert au moins une pièce.] PROJET, 0N [Une pièce peut être requise par plusieurs projets.] PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [Une pièce peut être composée de plusieurs autres pièces.] PIÈCE, 0N [Une pièce peut entrer dans la composition de plusieurs autres pièces.] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, _11 [Un ayant-droit est associé à un et un seul employé.] AYANT-DROIT, 0N [Un employé peut avoir plusieurs ayants-droit.] EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N [Un projet est fourni par au moins une société.] PROJET, 1N [Une pièce est fournie par au moins une société.] PIÈCE, 1N [Une société fournit au moins une pièce pour un projet.] SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 [Un employé appartient à un et un seul département.] EMPLOYÉ, 1N [Un département emploie au moins un employé.] DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N [Un employé peut travailler sur plusieurs projets.] EMPLOYÉ, 1N [Un projet implique au moins un employé.] PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N< [Une société peut en contrôler une autre.] SOCIÉTÉ, 01 [Une société est contrôlée par au plus une autre société.] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le résultat est en général plus qu'honorable, mais demande à être relu attentivement pour vérifier l'adhérence au MCD original, corriger d'éventuelles hallucinations ou apporter des précisions. Ci-dessus, en l'occurrence, une société peut en contrôler _plusieurs autres_ (et non _une autre_).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Différence syntaxique entre rôles et explications.** Remarquez que la syntaxe est la même que pour les rôles, qui sont en plus utilisés lors du passage au relationnel. Comment Mocodo fait-il la différence ? En appliquant les règles suivantes :\\n\",\n    \"\\n\",\n    \"- si la note de patte commence par `+` ou `-`, ou qu'elle ne contient aucun espace, c'est un rôle.\\n\",\n    \"- sinon, c'est une description de cardinalité.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Explication de contraintes.** Le même principe s'applique aux contraintes (survolez le Ⓘ) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 97,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"397\\\" height=\\\"185\\\" viewBox=\\\"0 0 397 185\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"397\\\" height=\\\"185\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint I_CONSTRAINT_#1 -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"138\\\" x2=\\\"135.5\\\" y2=\\\"92.5\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"107.76 109 115.0 97.71 114.63 104.91 121.14 108.02\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"138\\\" x2=\\\"135.5\\\" y2=\\\"92.5\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"47\\\" x2=\\\"135.5\\\" y2=\\\"92.5\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"135.5\\\" cy=\\\"92.5\\\" r=\\\"12\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\" onmouseover=\\\"show_5a339f92(evt,'Toute pièce fournie doit avoir été requise.')\\\" onmouseout=\\\"hide_5a339f92(evt)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"133\\\" y=\\\"96.7\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">I</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"47\\\" x2=\\\"212\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"138\\\" x2=\\\"212\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"337\\\" y1=\\\"47\\\" x2=\\\"212\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M243 18 a14 14 90 0 1 14 14 V46 h-90 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M257 46 v16 a14 14 90 0 1 -14 14 H181 a14 14 90 0 1 -14 -14 V46 H90\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"167\\\" y=\\\"18\\\" width=\\\"90\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"167\\\" y1=\\\"46\\\" x2=\\\"257\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"175\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Fournir</text>\\n\",\n       \"\\t\\t<text x=\\\"174\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"217\\\" y=\\\"92\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"262\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"47\\\" x2=\\\"59\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"138\\\" x2=\\\"59\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M95 109 a14 14 90 0 1 14 14 V137 h-100 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M109 137 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V137 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"137\\\" x2=\\\"109\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"17\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Requérir</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"64\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"143\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"14\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"14\\\" y=\\\"39\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"14\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"14\\\" y1=\\\"39\\\" x2=\\\"104\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"28\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"22\\\" y1=\\\"59\\\" x2=\\\"96\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"286\\\" y=\\\"9\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"286\\\" y=\\\"39\\\" width=\\\"102\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"286\\\" y=\\\"9\\\" width=\\\"102\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"286\\\" y1=\\\"39\\\" x2=\\\"388\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"303\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Société</text>\\n\",\n       \"\\t<text x=\\\"294\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"294\\\" y1=\\\"59\\\" x2=\\\"374\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"294\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_5a339f92 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"167\\\" y=\\\"100\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"167\\\" y=\\\"130\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"167\\\" y=\\\"100\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"167\\\" y1=\\\"130\\\" x2=\\\"257\\\" y2=\\\"130\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"188\\\" y=\\\"121.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Pièce</text>\\n\",\n       \"\\t<text x=\\\"175\\\" y=\\\"147.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"175\\\" y1=\\\"150\\\" x2=\\\"233\\\" y2=\\\"150\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"175\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_5a339f92(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 140) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_5a339f92\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_5a339f92\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_5a339f92(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_5a339f92\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_5a339f92\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_5a339f92\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_5a339f92\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_5a339f92\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_5a339f92\\\" text-anchor=\\\"middle\\\" x=\\\"198\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_5a339f92\\\" x=\\\"0\\\" y=\\\"145\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_5a339f92\\\" text-anchor=\\\"middle\\\" x=\\\"198\\\" y=\\\"169\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Projet: num. projet, nom projet\\n\",\n    \":\\n\",\n    \"Fournir, 1N Projet, 1N Pièce, 1N Société: quantité\\n\",\n    \"Société: num. société, raison sociale\\n\",\n    \"\\n\",\n    \"Requérir, 1N Projet, 0N Pièce: quantité\\n\",\n    \":\\n\",\n    \"Pièce: réf. pièce, libellé pièce\\n\",\n    \"\\n\",\n    \"(I) [Toute pièce fournie doit avoir été requise.] ..Pièce, ->Requérir, --Fournir, Projet\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Limitations.**\\n\",\n    \"- Non pris en charge par les éditeurs de SVG comme Inkscape.\\n\",\n    \"- Ne semble pas fonctionner dans une page HTML statique (comme la version HTML de ce document sous GitHub).\\n\",\n    \"- Nécessite de faire confiance à un notebook (Trust notebook) pour s'afficher à la réouverture.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Dévoiler un MCD par étapes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 3.** Il est possible de faire apparaître progressivement les différentes « boîtes » constituant un MCD. Pour cela, il suffit d'indenter (décaler vers la droite à l'aide d'espaces ou de tabulations) au moins une ligne. Les éléments correspondants seront alors répartis sur autant de « calques » qu'il y a de niveaux d'indentations.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Voici par exemple un exercice consistant en la description du « réel perçu » d'une entreprise de VPC :\\n\",\n    \"\\n\",\n    \"> 1. Un produit est connu par une référence, un libellé et un prix unitaire.\\n\",\n    \"> 1. Toute commande inclut un produit ou plusieurs, chacun en une certaine quantité.\\n\",\n    \"> 1. Un client peut passer zéro (_client potentiel_) ou plusieurs commandes.\\n\",\n    \"> 1. Un client peut entrer dans la base par parrainage d'un autre client.\\n\",\n    \"\\n\",\n    \"L'enseignant peut le présenter pas à pas en suivant les étapes de l'énoncé :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 98,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"385\\\" height=\\\"278\\\" viewBox=\\\"0 0 385 278\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"385\\\" height=\\\"238\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PARRAINER -->\\n\",\n       \"<g class=\\\"page_3_0743d298 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<path d=\\\"M64 174 C26.67 124 26.67 84.67 64 56\\\" fill=\\\"none\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M64 174 C102.67 124 102.67 84.67 64 56\\\" fill=\\\"none\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M105 27 a14 14 90 0 1 14 14 V55 h-110 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M119 55 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V55 H110\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"27\\\" width=\\\"110\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"55\\\" x2=\\\"119\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"17\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Parrainer</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date parrainage</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"111\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"68\\\" y=\\\"111\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g class=\\\"page_1_0743d298 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<line x1=\\\"314\\\" y1=\\\"174\\\" x2=\\\"314\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"195\\\" y1=\\\"56\\\" x2=\\\"314\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M343 27 a14 14 90 0 1 14 14 V55 h-86 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M357 55 v16 a14 14 90 0 1 -14 14 H285 a14 14 90 0 1 -14 -14 V55 H86\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"271\\\" y=\\\"27\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"271\\\" y1=\\\"55\\\" x2=\\\"357\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"278\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"278\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"319\\\" y=\\\"119\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"72\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_2_0743d298 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<line x1=\\\"64\\\" y1=\\\"174\\\" x2=\\\"195\\\" y2=\\\"174\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"314\\\" y1=\\\"174\\\" x2=\\\"195\\\" y2=\\\"174\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"195\\\" cy=\\\"174\\\" r=\\\"20\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\" fill=\\\"#b2bba4\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"182\\\" y=\\\"178.8\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"190\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"229\\\" y=\\\"190\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g class=\\\"page_0_0743d298 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"148\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"148\\\" y=\\\"39\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"148\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"148\\\" y1=\\\"39\\\" x2=\\\"242\\\" y2=\\\"39\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"159\\\" y=\\\"30.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"56.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"156\\\" y1=\\\"59\\\" x2=\\\"231\\\" y2=\\\"59\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"73.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"156\\\" y=\\\"90\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g class=\\\"page_2_0743d298 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"25\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"25\\\" y=\\\"149\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"25\\\" y=\\\"119\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"25\\\" y1=\\\"149\\\" x2=\\\"103\\\" y2=\\\"149\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"34\\\" y=\\\"140.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"166.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"33\\\" y1=\\\"169\\\" x2=\\\"95\\\" y2=\\\"169\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"183.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"200.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"217\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g class=\\\"page_1_0743d298 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"252\\\" y=\\\"127\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"252\\\" y=\\\"157\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"252\\\" y=\\\"127\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"252\\\" y1=\\\"157\\\" x2=\\\"376\\\" y2=\\\"157\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"267\\\" y=\\\"148.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"174.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"260\\\" y1=\\\"177\\\" x2=\\\"368\\\" y2=\\\"177\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"191.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"208\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Pager -->\\n\",\n       \"<circle cx=\\\"162.5\\\" cy=\\\"258\\\" r=\\\"5\\\" fill=\\\"gray\\\" id=\\\"pager_dot_0_0743d298\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_0743d298(evt,0)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"182.5\\\" cy=\\\"258\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_1_0743d298\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_0743d298(evt,1)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"202.5\\\" cy=\\\"258\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_2_0743d298\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_0743d298(evt,2)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"222.5\\\" cy=\\\"258\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_3_0743d298\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_0743d298(evt,3)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction switch_page_visibility_0743d298(evt, page) {\\n\",\n       \"\\t\\tfor (var i = 0; i < 4; i++) {\\n\",\n       \"\\t\\t\\tcomponents = document.getElementsByClassName(`page_${i}_0743d298`);\\n\",\n       \"\\t\\t\\tfor (var j = 0; j < components.length; j++) {\\n\",\n       \"\\t\\t\\t\\tcomponents[j].setAttributeNS(null, \\\"visibility\\\", i <= page ? \\\"visible\\\" : \\\"hidden\\\");\\n\",\n       \"\\t\\t\\t};\\n\",\n       \"\\t\\t\\tdot = document.getElementById(`pager_dot_${i}_0743d298`);\\n\",\n       \"\\t\\t\\tdot.setAttributeNS(null, \\\"fill\\\", i <= page ? \\\"gray\\\" : \\\"lightgray\\\");\\n\",\n       \"\\t\\t}\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --colors ocean\\n\",\n    \"      Parrainer, 01 Client, 0N Client : date parrainage\\n\",\n    \"Produit: Réf. produit, Libellé, Prix unitaire\\n\",\n    \"  Inclure, 1N Commande, 0N Produit: Quantité\\n\",\n    \" \\n\",\n    \"    Client: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"    DF, 0N Client, 11 Commande\\n\",\n    \"  Commande: Num. commande, Date, Montant\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Remarques.**\\n\",\n    \"- Pas de règle sur la taille de l'indentation. Pour Mocodo, autant de niveaux d'indentation distincts, autant de calques.\\n\",\n    \"- Les différents calques sont codés directement dans le SVG. L'interaction ne nécessite donc aucun logiciel spécifique.\\n\",\n    \"- Sous Mocodo online, le MCD est toujours présenté entièrement dévoilé. Cela permet de voir directement le résultat d'une modification du texte-source.\\n\",\n    \"- Pour ajouter facilement de l'interactivité à un MCD existant :\\n\",\n    \"    1. commencez par indenter au maximum toutes les lignes ;\\n\",\n    \"    1. effacez l'indentation des lignes du premier calque ;\\n\",\n    \"    1. décalez votre curseur de $n$ caractères vers la droite ;\\n\",\n    \"    1. placez-vous tour à tour sur les lignes à intégrer au deuxième calque et effacez les espaces surnuméraires ;\\n\",\n    \"    1. recommencez à l'étape 3 jusqu'au dernier calque.\\n\",\n    \"    \\n\",\n    \"  Depuis la version 4.0, l'éditeur de Mocodo online vous permet de créer des curseurs multiples, ce qui simplifie encore ces opérations.\\n\",\n    \"\\n\",\n    \"**Limitations.**\\n\",\n    \"- Pas de granularité plus fine que la ligne (entité ou association avec toutes ses pattes et cardinalités).\\n\",\n    \"- Pas de prise en charge des touches directionnelles. Cela serait sans doute possible, mais difficilement compatible avec la présence de plusieurs MCD interactifs sur une même page (comme dans cette documentation).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Éviter qu'une interaction sur un SVG ne s'applique à un autre.**\\n\",\n    \"\\n\",\n    \"Dans le cas très rare où plusieurs SVG interactifs générés **à partir du même texte-source** coexistent sur une même page web, une interaction opérée sur l'un s'applique également à tous les autres. Par exemple, cliquer sur l'un des ronds gris de l'une des figures ci-dessous agira sur les deux figures :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 99,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"159\\\" height=\\\"118\\\" viewBox=\\\"0 0 159 118\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"159\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity FOO -->\\n\",\n       \"<g class=\\\"page_0_1caf7840 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"65\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOO</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">foo</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"39\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BAR -->\\n\",\n       \"<g class=\\\"page_1_1caf7840 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"94\\\" y1=\\\"39\\\" x2=\\\"150\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BAR</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bar</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"59\\\" x2=\\\"123\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Pager -->\\n\",\n       \"<circle cx=\\\"69.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"gray\\\" id=\\\"pager_dot_0_1caf7840\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840(evt,0)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"89.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_1_1caf7840\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840(evt,1)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction switch_page_visibility_1caf7840(evt, page) {\\n\",\n       \"\\t\\tfor (var i = 0; i < 2; i++) {\\n\",\n       \"\\t\\t\\tcomponents = document.getElementsByClassName(`page_${i}_1caf7840`);\\n\",\n       \"\\t\\t\\tfor (var j = 0; j < components.length; j++) {\\n\",\n       \"\\t\\t\\t\\tcomponents[j].setAttributeNS(null, \\\"visibility\\\", i <= page ? \\\"visible\\\" : \\\"hidden\\\");\\n\",\n       \"\\t\\t\\t};\\n\",\n       \"\\t\\t\\tdot = document.getElementById(`pager_dot_${i}_1caf7840`);\\n\",\n       \"\\t\\t\\tdot.setAttributeNS(null, \\\"fill\\\", i <= page ? \\\"gray\\\" : \\\"lightgray\\\");\\n\",\n       \"\\t\\t}\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"FOO: foo\\n\",\n    \"  BAR: bar\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 100,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"159\\\" height=\\\"118\\\" viewBox=\\\"0 0 159 118\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"159\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity FOO -->\\n\",\n       \"<g class=\\\"page_0_1caf7840 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"65\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOO</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">foo</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"39\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BAR -->\\n\",\n       \"<g class=\\\"page_1_1caf7840 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"94\\\" y1=\\\"39\\\" x2=\\\"150\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BAR</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bar</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"59\\\" x2=\\\"123\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Pager -->\\n\",\n       \"<circle cx=\\\"69.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"gray\\\" id=\\\"pager_dot_0_1caf7840\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840(evt,0)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"89.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_1_1caf7840\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840(evt,1)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction switch_page_visibility_1caf7840(evt, page) {\\n\",\n       \"\\t\\tfor (var i = 0; i < 2; i++) {\\n\",\n       \"\\t\\t\\tcomponents = document.getElementsByClassName(`page_${i}_1caf7840`);\\n\",\n       \"\\t\\t\\tfor (var j = 0; j < components.length; j++) {\\n\",\n       \"\\t\\t\\t\\tcomponents[j].setAttributeNS(null, \\\"visibility\\\", i <= page ? \\\"visible\\\" : \\\"hidden\\\");\\n\",\n       \"\\t\\t\\t};\\n\",\n       \"\\t\\t\\tdot = document.getElementById(`pager_dot_${i}_1caf7840`);\\n\",\n       \"\\t\\t\\tdot.setAttributeNS(null, \\\"fill\\\", i <= page ? \\\"gray\\\" : \\\"lightgray\\\");\\n\",\n       \"\\t\\t}\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"FOO: foo\\n\",\n    \"  BAR: bar\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ce problème trahit une « collision » : différents éléments du [DOM](https://fr.wikipedia.org/wiki/Document_Object_Model) se sont vus attribuer la même empreinte (obtenue par hachage du texte-source). La solution est de passer un entier discriminant qui, par concaténation, fera de ces empreintes de véritables identifiants.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 101,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"159\\\" height=\\\"118\\\" viewBox=\\\"0 0 159 118\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"159\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity FOO -->\\n\",\n       \"<g class=\\\"page_0_1caf7840_1 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"65\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOO</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">foo</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"39\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BAR -->\\n\",\n       \"<g class=\\\"page_1_1caf7840_1 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"94\\\" y1=\\\"39\\\" x2=\\\"150\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BAR</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bar</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"59\\\" x2=\\\"123\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Pager -->\\n\",\n       \"<circle cx=\\\"69.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"gray\\\" id=\\\"pager_dot_0_1caf7840_1\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840_1(evt,0)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"89.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_1_1caf7840_1\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840_1(evt,1)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction switch_page_visibility_1caf7840_1(evt, page) {\\n\",\n       \"\\t\\tfor (var i = 0; i < 2; i++) {\\n\",\n       \"\\t\\t\\tcomponents = document.getElementsByClassName(`page_${i}_1caf7840_1`);\\n\",\n       \"\\t\\t\\tfor (var j = 0; j < components.length; j++) {\\n\",\n       \"\\t\\t\\t\\tcomponents[j].setAttributeNS(null, \\\"visibility\\\", i <= page ? \\\"visible\\\" : \\\"hidden\\\");\\n\",\n       \"\\t\\t\\t};\\n\",\n       \"\\t\\t\\tdot = document.getElementById(`pager_dot_${i}_1caf7840_1`);\\n\",\n       \"\\t\\t\\tdot.setAttributeNS(null, \\\"fill\\\", i <= page ? \\\"gray\\\" : \\\"lightgray\\\");\\n\",\n       \"\\t\\t}\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --uid_suffix 1\\n\",\n    \"FOO: foo\\n\",\n    \"  BAR: bar\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 102,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"159\\\" height=\\\"118\\\" viewBox=\\\"0 0 159 118\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"159\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity FOO -->\\n\",\n       \"<g class=\\\"page_0_1caf7840_2 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"65\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOO</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">foo</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"39\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BAR -->\\n\",\n       \"<g class=\\\"page_1_1caf7840_2 diagram_page\\\" visibility=\\\"hidden\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"39\\\" width=\\\"56\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"9\\\" width=\\\"56\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"94\\\" y1=\\\"39\\\" x2=\\\"150\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BAR</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">bar</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"59\\\" x2=\\\"123\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Pager -->\\n\",\n       \"<circle cx=\\\"69.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"gray\\\" id=\\\"pager_dot_0_1caf7840_2\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840_2(evt,0)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<circle cx=\\\"89.5\\\" cy=\\\"98\\\" r=\\\"5\\\" fill=\\\"lightgray\\\" id=\\\"pager_dot_1_1caf7840_2\\\" class=\\\"pager_dot\\\" stroke-width=\\\"0\\\" onclick=\\\"switch_page_visibility_1caf7840_2(evt,1)\\\" style=\\\"cursor: pointer;\\\"/>\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction switch_page_visibility_1caf7840_2(evt, page) {\\n\",\n       \"\\t\\tfor (var i = 0; i < 2; i++) {\\n\",\n       \"\\t\\t\\tcomponents = document.getElementsByClassName(`page_${i}_1caf7840_2`);\\n\",\n       \"\\t\\t\\tfor (var j = 0; j < components.length; j++) {\\n\",\n       \"\\t\\t\\t\\tcomponents[j].setAttributeNS(null, \\\"visibility\\\", i <= page ? \\\"visible\\\" : \\\"hidden\\\");\\n\",\n       \"\\t\\t\\t};\\n\",\n       \"\\t\\t\\tdot = document.getElementById(`pager_dot_${i}_1caf7840_2`);\\n\",\n       \"\\t\\t\\tdot.setAttributeNS(null, \\\"fill\\\", i <= page ? \\\"gray\\\" : \\\"lightgray\\\");\\n\",\n       \"\\t\\t}\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --uid_suffix 2\\n\",\n    \"FOO: foo\\n\",\n    \"  BAR: bar\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Explications du passage au relationnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les gabarits de conversion en MLD (à savoir `html`, `markdown`, `latex` et `text`) admettent une sous-sous-option `e` qui accompagne le résultat par des explications détaillées du mécanisme de passage :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 103,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Client** (<u>Réf. client</u>, Nom, Prénom, Adresse)\\n\",\n       \"  - Le champ _Réf. client_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Client_.\\n\",\n       \"  - Les champs _Nom_, _Prénom_ et _Adresse_ étaient déjà de simples attributs de l'entité _Client_.\\n\",\n       \"\\n\",\n       \"- **Commande** (<u>Num. commande</u>, Date, Montant, _#Réf. client_)\\n\",\n       \"  - Le champ _Num. commande_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Commande_.\\n\",\n       \"  - Les champs _Date_ et _Montant_ étaient déjà de simples attributs de l'entité _Commande_.\\n\",\n       \"  - Le champ _Réf. client_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Passer_ à partir de l'entité _Client_ en perdant son caractère identifiant.\\n\",\n       \"\\n\",\n       \"- **Inclure** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\\n\",\n       \"  - Le champ _Num. commande_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Commande_.\\n\",\n       \"  - Le champ _Réf. produit_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Produit_.\\n\",\n       \"  - Le champ _Quantité_ était déjà un simple attribut de l'association _Inclure_.\\n\",\n       \"\\n\",\n       \"- **Produit** (<u>Réf. produit</u>, Libellé, Prix unitaire)\\n\",\n       \"  - Le champ _Réf. produit_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Produit_.\\n\",\n       \"  - Les champs _Libellé_ et _Prix unitaire_ étaient déjà de simples attributs de l'entité _Produit_.\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t markdown:e\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Nous avons essayé d'être aussi précis que possible, tout en « factorisant » avec soin les lignes consécutives suseptibles de l'être. Vous pouvez adapter ces explications à votre enseignement en modifiant une copie du gabarit `html-ce.yaml`, dont les autres sont dérivés.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## MCD à compléter\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les MCD à trous sont des exercices classiques d'introduction aux bases de données.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Supprimer le marquage d'un identifiant\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour éviter le marquage automatique du premier attribut d'une entité comme identifiant, il suffit de le préfixer par un tiret bas (`_`) : ce caractère est donc un commutateur, qui souligne un attribut non souligné par défaut, et désouligne un attribut souligné par défaut.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 104,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"128\\\" viewBox=\\\"0 0 630 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M196 35 a14 14 90 0 1 14 14 V63 h-88 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M210 63 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V63 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"35\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"63\\\" x2=\\\"210\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"571\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M478 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M492 63 v16 a14 14 90 0 1 -14 14 H408 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"63\\\" x2=\\\"492\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"402\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"401\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"370\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"239\\\" y1=\\\"47\\\" x2=\\\"365\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"248\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"521\\\" y1=\\\"47\\\" x2=\\\"621\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: _Réf. client, Nom, Prénom, Adresse\\n\",\n    \"PASSER, 0N CLIENT, 11 COMMANDE\\n\",\n    \"COMMANDE: _Num. commande, Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: _Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Masquer un couple de cardinalités\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez masquer n'importe quelles cardinalités en les remplaçant par `XX` ou en les préfixant d'un `-` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 105,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"128\\\" viewBox=\\\"0 0 630 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"166\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M196 35 a14 14 90 0 1 14 14 V63 h-88 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M210 63 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V63 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"35\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"63\\\" x2=\\\"210\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"571\\\" y1=\\\"64\\\" x2=\\\"443\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M478 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M492 63 v16 a14 14 90 0 1 -14 14 H408 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"63\\\" x2=\\\"492\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"402\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"401\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"370\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"498\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"239\\\" y1=\\\"47\\\" x2=\\\"365\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"248\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"247\\\" y1=\\\"67\\\" x2=\\\"355\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"521\\\" y1=\\\"47\\\" x2=\\\"621\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"529\\\" y1=\\\"67\\\" x2=\\\"604\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"PASSER, XX CLIENT, XX COMMANDE\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"INCLURE, -1N COMMANDE, -0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Nouveauté de la version 4.0.** Si la cardinalité comporte un et un seul `X`, l'autre caractère sera affiché tout seul.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Masquer un attribut\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez mettre deux virgules consécutives pour réserver la place d'un attribut manquant. Les espaces insécables sont préservés, ce qui permet de réserver plus d'espace horizontal, cf. ci-dessous premier attribut vide de INCLURE.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 106,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"630\\\" height=\\\"144\\\" viewBox=\\\"0 0 630 144\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"630\\\" height=\\\"144\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"72\\\" x2=\\\"166\\\" y2=\\\"72\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"72\\\" x2=\\\"166\\\" y2=\\\"72\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M196 43 a14 14 90 0 1 14 14 V71 h-88 V57 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M210 71 v16 a14 14 90 0 1 -14 14 H136 a14 14 90 0 1 -14 -14 V71 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"122\\\" y=\\\"43\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"122\\\" y1=\\\"71\\\" x2=\\\"210\\\" y2=\\\"71\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"64.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PASSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"88\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"88\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"302\\\" y1=\\\"72\\\" x2=\\\"443\\\" y2=\\\"72\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"571\\\" y1=\\\"72\\\" x2=\\\"443\\\" y2=\\\"72\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M478 9 a14 14 90 0 1 14 14 V37 h-98 V23 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M492 37 v84 a14 14 90 0 1 -14 14 H408 a14 14 90 0 1 -14 -14 V37 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"394\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"126\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"394\\\" y1=\\\"37\\\" x2=\\\"492\\\" y2=\\\"37\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"402\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"401\\\" y=\\\"55.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"370\\\" y=\\\"88\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"88\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"17\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"47\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"17\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"47\\\" x2=\\\"93\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"67\\\" x2=\\\"79\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"25\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"55\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"239\\\" y=\\\"25\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"239\\\" y1=\\\"55\\\" x2=\\\"365\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"248\\\" y=\\\"46.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"89.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"247\\\" y=\\\"106\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"25\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"55\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"521\\\" y=\\\"25\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"521\\\" y1=\\\"55\\\" x2=\\\"621\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"530\\\" y=\\\"46.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"72.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"529\\\" y1=\\\"75\\\" x2=\\\"604\\\" y2=\\\"75\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"89.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"106\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"CLIENT: Réf. client,,, \\n\",\n    \"PASSER, XX CLIENT, XX COMMANDE\\n\",\n    \"COMMANDE: , Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité,,,,\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Régression de la version 4.0.** Les espaces insécables ne sont plus préservés. Il n'y a donc plus d'autre moyen de réserver davantage d'espace horizontal que d'employer le style `blank` (paragraphe suivant).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Ne faire apparaître que le squelette du schéma conceptuel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez transformer en exercice à trous n'importe quel MCD en rendant complètement transparentes les couleurs des attributs, associations et cardinalités. Le style `blank` a été prédéfini à cet effet:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 107,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"594\\\" height=\\\"128\\\" viewBox=\\\"0 0 594 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"594\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"none\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"none\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"285\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"538\\\" y1=\\\"64\\\" x2=\\\"419\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M448 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M462 63 v16 a14 14 90 0 1 -14 14 H390 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"376\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"376\\\" y1=\\\"63\\\" x2=\\\"462\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"383\\\" y=\\\"81.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"352\\\" y=\\\"80\\\" fill=\\\"none\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"467\\\" y=\\\"80\\\" fill=\\\"none\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"347\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"238\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"64.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"67\\\" x2=\\\"339\\\" y2=\\\"67\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"81.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"98\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"47\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"491\\\" y=\\\"17\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"491\\\" y1=\\\"47\\\" x2=\\\"585\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"64.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"499\\\" y1=\\\"67\\\" x2=\\\"574\\\" y2=\\\"67\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"81.1\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"499\\\" y=\\\"98\\\" fill=\\\"none\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp --colors=blank\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Attention, n'utilisez cette méthode que pour la projection : l'information textuelle est toujours présente, susceptible d'être sélectionnée et collée ailleurs. Vous pouvez bien sûr empêcher cette possibilité en convertissant le SVG en PNG, mais le plus simple est d'appliquer une réécriture `empty` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 108,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"576\\\" height=\\\"128\\\" viewBox=\\\"0 0 576 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"576\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"64\\\" x2=\\\"155\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 63 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"63\\\" x2=\\\"194\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"200\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"64\\\" x2=\\\"405\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"522\\\" y1=\\\"64\\\" x2=\\\"405\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M434 35 a14 14 90 0 1 14 14 V63 h-86 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M448 63 v16 a14 14 90 0 1 -14 14 H376 a14 14 90 0 1 -14 -14 V63 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"362\\\" y=\\\"35\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"362\\\" y1=\\\"63\\\" x2=\\\"448\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"369\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"338\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"454\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"47\\\" width=\\\"110\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"17\\\" width=\\\"110\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"47\\\" x2=\\\"333\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"477\\\" y=\\\"17\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"477\\\" y=\\\"47\\\" width=\\\"90\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"477\\\" y=\\\"17\\\" width=\\\"90\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"477\\\" y1=\\\"47\\\" x2=\\\"567\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"486\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo \\n\",\n      \"Client:  ,  ,  ,  \\n\",\n      \"Passer, XX Client, XX Commande\\n\",\n      \"Commande:  ,  ,  \\n\",\n      \"Inclure, XX Commande, XX Produit:  \\n\",\n      \"Produit:  ,  ,\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t empty # équivalent de \\\"delete:types,notes,attrs,cards\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Obfuscation d'un MCD donné\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Obfusquer un MCD consiste à vider celui-ci de sa sémantique de surface en substituant des chaînes aléatoires à tous les libellés. Cela permet de créer des exemples d'illustration de telle ou telle notion « pure » sans risquer de voir son public se focaliser sur des détails-métier (c'est l'équivalent de la [variable méta-syntaxique](https://fr.wikipedia.org/wiki/Variable_métasyntaxique) `foobar` dans le contexte de la pédagogie de la programmation).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 109,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"586\\\" height=\\\"128\\\" viewBox=\\\"0 0 586 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"586\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association LIBELLUM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"64\\\" x2=\\\"185\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"295\\\" y1=\\\"64\\\" x2=\\\"185\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M220 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M234 63 v16 a14 14 90 0 1 -14 14 H150 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"136\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"136\\\" y1=\\\"63\\\" x2=\\\"234\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"143\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Libellum</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"112\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"240\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association MULIERES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"295\\\" y1=\\\"64\\\" x2=\\\"406\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"531\\\" y1=\\\"64\\\" x2=\\\"406\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M442 35 a14 14 90 0 1 14 14 V63 h-100 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M456 63 v16 a14 14 90 0 1 -14 14 H370 a14 14 90 0 1 -14 -14 V63 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"356\\\" y=\\\"35\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"356\\\" y1=\\\"63\\\" x2=\\\"456\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"364\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Mulieres</text>\\n\",\n       \"\\t\\t<text x=\\\"363\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Carus</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"332\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"461\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SCRIPTAM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"98\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"98\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"107\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Scriptam</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Spicula</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"60\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Persequitur</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Defensor</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Frontem</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"17\\\" width=\\\"64\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"47\\\" width=\\\"64\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"17\\\" width=\\\"64\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"263\\\" y1=\\\"47\\\" x2=\\\"327\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"276\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Fuit</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Artes</text>\\n\",\n       \"\\t<line x1=\\\"271\\\" y1=\\\"67\\\" x2=\\\"307\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Leporis</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Sociis</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity THEATRO -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"485\\\" y=\\\"17\\\" width=\\\"92\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"485\\\" y=\\\"47\\\" width=\\\"92\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"485\\\" y=\\\"17\\\" width=\\\"92\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"485\\\" y1=\\\"47\\\" x2=\\\"577\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"494\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Theatro</text>\\n\",\n       \"\\t<text x=\\\"493\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Reperiri</text>\\n\",\n       \"\\t<line x1=\\\"493\\\" y1=\\\"67\\\" x2=\\\"544\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"493\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Serpentes</text>\\n\",\n       \"\\t<text x=\\\"493\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Amissum</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp --seed=1 --select mcd -t obfuscate  # raccourci pour \\\"obfuscate:labels\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"En argument, vous pouvez ajouter le chemin d'un fichier texte quelconque où puiser les mots de substitution. Par exemple, le texte du `README` de ce projet :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 110,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"676\\\" height=\\\"128\\\" viewBox=\\\"0 0 676 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"676\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association NOTEBOOK -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"64\\\" x2=\\\"203\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"332\\\" y1=\\\"64\\\" x2=\\\"203\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M240 35 a14 14 90 0 1 14 14 V63 h-102 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M254 63 v16 a14 14 90 0 1 -14 14 H166 a14 14 90 0 1 -14 -14 V63 H102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"35\\\" width=\\\"102\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"152\\\" y1=\\\"63\\\" x2=\\\"254\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"159\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Notebook</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"260\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ESPECE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"332\\\" y1=\\\"64\\\" x2=\\\"449\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"592\\\" y1=\\\"64\\\" x2=\\\"449\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M474 35 a14 14 90 0 1 14 14 V63 h-78 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M488 63 v16 a14 14 90 0 1 -14 14 H424 a14 14 90 0 1 -14 -14 V63 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"410\\\" y=\\\"35\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"410\\\" y1=\\\"63\\\" x2=\\\"488\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"418\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Espèce</text>\\n\",\n       \"\\t\\t<text x=\\\"417\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Texte</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"386\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"493\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity VERSION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"123\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"30\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Version</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Cardinalités</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"92\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Décomposition</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Relationnelle</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Master</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AFFICHEE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"283\\\" y=\\\"17\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"283\\\" y=\\\"47\\\" width=\\\"98\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"283\\\" y=\\\"17\\\" width=\\\"98\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"283\\\" y1=\\\"47\\\" x2=\\\"381\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"292\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Affichée</text>\\n\",\n       \"\\t<text x=\\\"291\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Bonus</text>\\n\",\n       \"\\t<line x1=\\\"291\\\" y1=\\\"67\\\" x2=\\\"330\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"291\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Incluant</text>\\n\",\n       \"\\t<text x=\\\"291\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Svg</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SPECIALISATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"517\\\" y=\\\"17\\\" width=\\\"150\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"517\\\" y=\\\"47\\\" width=\\\"150\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"517\\\" y=\\\"17\\\" width=\\\"150\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"517\\\" y1=\\\"47\\\" x2=\\\"667\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"526\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Spécialisation</text>\\n\",\n       \"\\t<text x=\\\"525\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Également</text>\\n\",\n       \"\\t<line x1=\\\"525\\\" y1=\\\"67\\\" x2=\\\"589\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"525\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Délégué</text>\\n\",\n       \"\\t<text x=\\\"525\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Exportation</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t obfuscate:labels=../../README.md --seed=1 --select mcd\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo essaie d'abord de trouver ce fichier à l'endroit indiqué. En cas d'échec, il le cherche (avec extension `.txt` facultative) parmi ceux distribués avec le logiciel, à savoir:\\n\",\n    \"\\n\",\n    \"- `\\\"lorem.txt\\\"` (6464 mots) : le [faux-texte](https://fr.wikipedia.org/wiki/Faux-texte) le plus courant, augmenté d'une sélection des 10000 mots latins les plus courants [compilés par Kyle P. Johnson](https://kyle-p-johnson.com/blog/2015/04/23/most-common-greek-latin-words.html), le tout privé de ses doublons et des mots de moins de 3 lettres (`\\\"lorem_ipsum.txt\\\"` avant la version 4.0).\\n\",\n    \"- `\\\"fr.txt\\\"` (3396 mots) : une liste des 4000 mots français les plus courants, privée de ceux comportant une apostrophe ou moins de 4 lettres. Source : http://wortschatz.uni-leipzig.de/index.html _via_ [Wikitionary](https://fr.wiktionary.org/wiki/Wiktionnaire:Listes_de_fréquence). Nouveauté de la version 4.0.\\n\",\n    \"- `\\\"fr5.txt\\\"` (464 mots): la liste de `\\\"fr.txt\\\"`, restreinte aux mots de 5 lettres. Nouveauté de la version 4.0.\\n\",\n    \"- `\\\"en4.txt\\\"` (640 mots): une sélection (SFW) de mots anglais de quatre lettres (`\\\"four_letter_words.txt\\\"` avant la version 4.0).\\n\",\n    \"- `\\\"disparition.txt\\\"` (7489 mots) : le lexique du [célèbre roman lipogrammatique](https://fr.wikipedia.org/wiki/La_Disparition_&#40;roman&#41;) de Georges Perec, privé des mots de moins de 4 lettres.\\n\",\n    \"\\n\",\n    \"En cas de nouvel échec, il se rabat sur `\\\"lorem.txt\\\"`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** L'algorithme s'assure que la [distance de Damerau-Levenshtein](https://fr.wikipedia.org/wiki/Distance_de_Damerau-Levenshtein) entre deux libellés de substitution quelconques est d'au moins 3. En clair, cela signifie que, si vous donnez en examen un exercice de conversion en relationnel basé sur un tel MCD, les erreurs de transcription d'un étudiant stressé, inattentif, illettré, dyslexique, roublard, ou tout cela à la fois, ne devraient pas vous empêcher de lui octroyer les points qui lui reviennent.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Croissance stochastique\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez créer un MCD partiellement aléatoire à partir d'un MCD donné en lui ajoutant un nombre `n` d'associations (avec les entités nécessaires) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 111,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"527\\\" height=\\\"428\\\" viewBox=\\\"0 0 527 428\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"527\\\" height=\\\"428\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association TERNAIRE_9_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"217\\\" y1=\\\"47\\\" x2=\\\"217\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"217\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"75\\\" y1=\\\"138\\\" x2=\\\"217\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M259 109 a14 14 90 0 1 14 14 V137 h-112 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M273 137 v16 a14 14 90 0 1 -14 14 H175 a14 14 90 0 1 -14 -14 V137 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"161\\\" y=\\\"109\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"161\\\" y1=\\\"137\\\" x2=\\\"273\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"168\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ternaire 9</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"222\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"279\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"126\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TERNAIRE_7_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"75\\\" y1=\\\"138\\\" x2=\\\"75\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"217\\\" y1=\\\"246\\\" x2=\\\"75\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M217 372 C207.02 313.41 159.69 271.41 75 246\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M117 217 a14 14 90 0 1 14 14 V245 h-112 V231 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M131 245 v16 a14 14 90 0 1 -14 14 H33 a14 14 90 0 1 -14 -14 V245 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"19\\\" y=\\\"217\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"19\\\" y1=\\\"245\\\" x2=\\\"131\\\" y2=\\\"245\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"26\\\" y=\\\"238.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ternaire 7</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"80\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"154\\\" y=\\\"262\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"161.48\\\" y=\\\"317\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association PASSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"217\\\" y1=\\\"246\\\" x2=\\\"364\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"364\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M389 217 a14 14 90 0 1 14 14 V245 h-78 V231 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M403 245 v16 a14 14 90 0 1 -14 14 H339 a14 14 90 0 1 -14 -14 V245 H78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"325\\\" y=\\\"217\\\" width=\\\"78\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"325\\\" y1=\\\"245\\\" x2=\\\"403\\\" y2=\\\"245\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"332\\\" y=\\\"238.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Passer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"262\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"341\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"475\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M217 372 C197.95 343.14 283.95 301.14 475 246\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M504 217 a14 14 90 0 1 14 14 V245 h-86 V231 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M518 245 v16 a14 14 90 0 1 -14 14 H446 a14 14 90 0 1 -14 -14 V245 H86\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"432\\\" y=\\\"217\\\" width=\\\"86\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"432\\\" y1=\\\"245\\\" x2=\\\"518\\\" y2=\\\"245\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"439\\\" y=\\\"238.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Inclure</text>\\n\",\n       \"\\t\\t<text x=\\\"439\\\" y=\\\"263.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"395.24\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"269\\\" y=\\\"332.18\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REFLEXIVE_11_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M217 372 C182.33 404 135 404 75 372\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M217 372 C183 340 135.67 340 75 372\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M127 343 a14 14 90 0 1 14 14 V371 h-132 V357 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M141 371 v16 a14 14 90 0 1 -14 14 H23 a14 14 90 0 1 -14 -14 V371 H132\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"343\\\" width=\\\"132\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"371\\\" x2=\\\"141\\\" y2=\\\"371\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"17\\\" y=\\\"364.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réflexive 11</text>\\n\",\n       \"\\t\\t<text x=\\\"16\\\" y=\\\"389.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 11 1</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"387\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"147\\\" y=\\\"365\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REFLEXIVE_10_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M217 372 C249.33 340 298.33 340 364 372\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M217 372 C249.33 404 298.33 404 364 372\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M416 343 a14 14 90 0 1 14 14 V371 h-132 V357 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M430 371 v16 a14 14 90 0 1 -14 14 H312 a14 14 90 0 1 -14 -14 V371 H132\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"298\\\" y=\\\"343\\\" width=\\\"132\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"298\\\" y1=\\\"371\\\" x2=\\\"430\\\" y2=\\\"371\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"306\\\" y=\\\"364.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réflexive 10</text>\\n\",\n       \"\\t\\t<text x=\\\"305\\\" y=\\\"389.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 10 1</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"269\\\" y=\\\"365\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"269\\\" y=\\\"387\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_8_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"171\\\" y=\\\"9\\\" width=\\\"92\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"171\\\" y=\\\"39\\\" width=\\\"92\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"171\\\" y=\\\"9\\\" width=\\\"92\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"171\\\" y1=\\\"39\\\" x2=\\\"263\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"180\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entité 8</text>\\n\",\n       \"\\t<text x=\\\"179\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id 8 1</text>\\n\",\n       \"\\t<line x1=\\\"179\\\" y1=\\\"59\\\" x2=\\\"215\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"179\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 8 2</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_6_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"29\\\" y=\\\"91\\\" width=\\\"92\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"29\\\" y=\\\"121\\\" width=\\\"92\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"29\\\" y=\\\"91\\\" width=\\\"92\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"29\\\" y1=\\\"121\\\" x2=\\\"121\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"38\\\" y=\\\"112.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entité 6</text>\\n\",\n       \"\\t<text x=\\\"37\\\" y=\\\"138.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id 6 1</text>\\n\",\n       \"\\t<line x1=\\\"37\\\" y1=\\\"141\\\" x2=\\\"73\\\" y2=\\\"141\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"37\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 6 2</text>\\n\",\n       \"\\t<text x=\\\"37\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 6 3</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"302\\\" y=\\\"91\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"302\\\" y=\\\"121\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"302\\\" y=\\\"91\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"302\\\" y1=\\\"121\\\" x2=\\\"426\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"317\\\" y=\\\"112.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"310\\\" y=\\\"138.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"310\\\" y1=\\\"141\\\" x2=\\\"418\\\" y2=\\\"141\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"310\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"310\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"191\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"221\\\" width=\\\"78\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"178\\\" y=\\\"191\\\" width=\\\"78\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"178\\\" y1=\\\"221\\\" x2=\\\"256\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"187\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"186\\\" y1=\\\"241\\\" x2=\\\"248\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"272.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"186\\\" y=\\\"289\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"170\\\" y=\\\"325\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"170\\\" y=\\\"355\\\" width=\\\"94\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"170\\\" y=\\\"325\\\" width=\\\"94\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"170\\\" y1=\\\"355\\\" x2=\\\"264\\\" y2=\\\"355\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"346.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Produit</text>\\n\",\n       \"\\t<text x=\\\"178\\\" y=\\\"372.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"178\\\" y1=\\\"375\\\" x2=\\\"253\\\" y2=\\\"375\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"178\\\" y=\\\"389.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"178\\\" y=\\\"406\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t grow:n=4 arrange --seed=1 --select mcd\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"- Des sous-options pré-définies (données ci-dessous avec leur valeur par défaut après le `=`) permettent de spécifier finement le nombre désiré :\\n\",\n    \"  - d'associations réflexives (`arity_1=2`) ;\\n\",\n    \"  - d'associations ternaires (`arity_3=2`) ;\\n\",\n    \"  - d'associations quaternaires (`arity_4=0`) ;\\n\",\n    \"  - d'associations doubles, i.e., associant le même couple d'entités (`doubles=1`) ;\\n\",\n    \"  - d'identifiants composites (`composites=1`) ;\\n\",\n    \"  - d'attributs maximum par entité (`ent_attrs=4`) ;\\n\",\n    \"  - d'attributs maximum par association (`assoc_attrs=2`).\\n\",\n    \"\\n\",\n    \"- On ne peut pas préciser directement le nombre d'associations binaires : si le nombre total des autres associations spécifiées n'arrivent pas à `n`, elles viennent en complément.\\n\",\n    \"\\n\",\n    \"- Des sous-options de forme plus ou moins libre décrivent les cardinalités. Par exemple, `_11-*N=2` créera deux entités faibles et `/*N-*N` un agrégat. Les associations de complément sont `*N-*N`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Avec la sous-option `from_scratch`, le MCD de départ est vide. À titre d'exemple, voici la transformation complexe invoquée par Mocodo online pour créer un MCD d'entraînement à la conversion au relationnel, accompagné de cette dernière. Notez la création de rôles par défaut : ils permettent de simuler le rétablissement de la sémantique des associations disparues.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%mocodo --seed=2 --mld -t grow:from_scratch,arity_3=1,_11-*N=1 obfuscate create:roles lower:roles arrange\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il n'est pas impossible que le MCD résultant soit incorrect (p. ex., apparition d'une identification relative circulaire), mais les contrôles effectués _a priori_ et _a posteriori_ devraient dans la majorité des cas produire quelque chose de raisonnable.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Génération d'un QR code\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Impressionnez votre public en accompagnant l'option `-t share` de `--defer` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 112,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_url.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMTAwOCIgaGVpZ2h0PSIxMDA4Ij4KCTwhLS0gQ3JlYXRlZCB3aXRoIGh0dHBzOi8vYXBpLnFyc2VydmVyLmNvbSAoUVIgQ29kZSBBUEksIHNlZSBnb1FSLm1lL2FwaSBmb3IgaW5mb3JtYXRpb24pIC0tPgoJPHRpdGxlPlFSIENvZGU8L3RpdGxlPgoJPGRlc2M+aHR0cHM6Ly93d3cubW9jb2RvLm5ldC8/bWNkPWVOcHRrTUVLZ2tBUWh1ODl4UndMSkRRUXd0dXlTZ201bUVnWDZiRGxCZ3U2eHJZTHZaTFA0WXMxYWhaWXRfbV9ZZWJfWjJnbGhUSUJaRjE3VzhOMVVGQ2NTRWIzSkZ0dVYyY0hXRk5feWNiM2U1YnFybFZfT0NtMWVEekVqQzlTamxBNzRES2dnNFVEbmdlMHFXdXVTckdZaWdDWXJUSEZXODV5aE53Z0Nra2VvVWdhWlhnZk5ZeG9uSkREMG5PZERUckY2bHBaTFhBXy0td2ZmRlBkbEZiaXBVZUxjOUowTFJReHk2TmRsR0ctcVRtLTRUN0ttZjlCWGtSVjlYTVQ5dDN4Rl9JSlZrbkRwUllfZ1Y0TFJHNVo8L2Rlc2M+Cgk8cmVjdCBzdHlsZT0iZmlsbDpyZ2IoMjU1LCAyNTUsIDI1NSk7ZmlsbC1vcGFjaXR5OjEiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMDA4IiBoZWlnaHQ9IjEwMDgiIC8+Cgk8ZyBpZD0iZWxlbWVudHMiPgoJCTxwYXRoIHN0eWxlPSJmaWxsOnJnYigwLCAwLCAwKSIgZD0iTSAxNiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDExMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDExMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1MiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwxMTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5MiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwxMjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDE0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCwxNDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDE0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwxNjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDE2MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwxNzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDE3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwyMDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsMjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCwyMDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDIwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMjI0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1MiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwyMjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDI0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwyNzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDI3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsMjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDI4OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsMjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3MiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwyODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDMwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsMzIwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1MiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwzMjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDMzNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzNTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDM1MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDM2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsMzY4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5MiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3NiwzNjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDM4NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsMzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQwMCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNDAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0MTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDQxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw0MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNDMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw0NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDQ0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNDQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDQ2NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNDY0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw0NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDQ4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNDk2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw0OTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDUxMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw1MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDUyOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDU0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw1NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDU2MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw1NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDU3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw1OTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNTkyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw1OTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDU5MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDYwOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNjA4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw2MDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDYyNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNjI0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2MjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsNjQwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw2NDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzY4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDY0MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY1NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNjU2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2NTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDY3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw2NzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDY3MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMzYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsNjcyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDY4OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsNjg4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw2ODggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDcwNCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMjgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NzIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsNzA0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3MjAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDczNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsNzM2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3MzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDc1MiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzUyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3NTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjQwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjcyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjg4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjU2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYwLDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDc2OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsNzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDc4NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsNzg0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDEyOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk0NCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw3ODQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDgwMCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODAwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4MDAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsODE2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw4MTYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTI4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTkyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjA4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzUyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzY4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTI4LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTQ0LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDgxNiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMiw4MzIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDgzMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsODMyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDg0OCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsODQ4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMzNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU2MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgzMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4NDggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM1Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQzMiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ0OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc1Miw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgxNiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4NjQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDg4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIsODgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDg4MCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsODgwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE5Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI1Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI3Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI4OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ2NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ5Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUyOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU0NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYwOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc2OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDc4NCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg0OCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkxMiw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk2MCw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw4ODAgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjU2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTI4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTQ0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjg4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAwLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTEyLDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDg5NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OCw5MTIgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY0LDkxMiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MzIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MjgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NzYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2ODgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MDAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MTIsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsOTEyIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQ4LDkyOCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjQsOTI4IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDExMiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE0NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIwOCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDIyNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDI0MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMwNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM2OCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDM4NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQwMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDQxNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDUxMiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDU5Miw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDYyNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY1Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY3Miw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDY4OCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcwNCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDcyMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDczNiw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwMCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg2NCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg4MCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDg5Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDkyOCw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDk3Niw5MjggbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsOTQ0IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw5NDQgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTEyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTQ0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMjI0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzA0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzIwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzM2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMzg0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDAwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDMyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDQ4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDY0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTEyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTYwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNTkyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjA4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjI0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNjcyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzA0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzIwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzM2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzUyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNzg0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODE2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODMyLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODQ4LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODY0LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODgwLDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gODk2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTc2LDk0NCBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gMTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxOTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNzIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNTIsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MDAsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0MTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0NjQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NjgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NDgsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4ODAsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTYwIGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNiw5NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDMyLDk3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gNDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NCw5NzYgbCAxNiwwIDAsMTYgLTE2LDAgeiBNIDgwLDk3NiBsIDE2LDAgMCwxNiAtMTYsMCB6IE0gOTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxMTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAxNzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyMjQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyNDAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAyODgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzMDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzNjgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSAzODQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0ODAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA0OTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1MTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1NjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA1OTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2MDgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA2NTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3MzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3NTIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA3ODQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4MzIsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4NjQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA4OTYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5MjgsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NDQsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NjAsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogTSA5NzYsOTc2IGwgMTYsMCAwLDE2IC0xNiwwIHogIiAvPgoJPC9nPgo8L3N2Zz4K\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t share --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Limitation.** Comme il faut un mobile pour scanner ce QR code, et que Mocodo online n'est pas vraiment adapté aux mobiles, l'intérêt réel de cette fonctionnalité est pour l'instant discutable.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Bibliothèque de MCD en ligne\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous avez créé avec Mocodo toute une bibliothèque de MCD, certains pour illustrer des points de votre cours, d'autres comme solutions d'exercices. À partir de la version 4.1, vous pouvez donner accès à tel ou tel de ces MCD en communiquant simplement son nom à vos étudiants.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Accès sous Mocodo online\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour comprendre le fonctionnement, accédons à un MCD de la bibliothèque par défaut : copiez-collez la chaîne `def_weak-974e` comme titre du MCD dans l'onglet _Entrée_ de [Mocodo online](https://www.mocodo.net). Le texte-source est mis à jour avec le contenu d'un fichier `def_weak-974e.mcd` stocké en ligne :\\n\",\n    \"\\n\",\n    \"![](examples/lib_demo.png)\\n\",\n    \"\\n\",\n    \"**Remarques.**\\n\",\n    \"- Vous avez sans doute déjà utilisé cette fonctionnalité sans le savoir en parcourant le tutoriel, dont les MCD, appelés `tuto-0000`, `tuto-0001`, etc., sont récupérés de la même manière.\\n\",\n    \"- Tous les noms de fichiers de la bibliothèque par défaut se terminent par un code de quatre caractères alphanumériques : cette disposition évite qu'un utilisateur ne tombe dessus par hasard, et protège certains MCD (typiquement, les solutions d'exercices) de la curiosité naturelle des étudiants. Au moment de la correction, je leur donne simplement le nom complet, et ils récupèrent directement la solution, ce qui dégage du temps pour des activités plus éducatives que la recopie.\\n\",\n    \"\\n\",\n    \"Bien sûr, la plupart des MCD de la bibliothèque par défaut n'intéressent que mon enseignement, et n'ont pas vocation à être diffusés au-delà du cercle très select des _happy few_ qui en bénéficient.  \\n\",\n    \"Pour mettre votre propre bibliothèque à la disposition de vos propres étudiants :\\n\",\n    \"\\n\",\n    \"1. placez-la dans un répertoire dédié d'un serveur sur lequel vous avez les droits ;\\n\",\n    \"2. copiez-collez l'URL de ce répertoire dans le champ _Bibliothèque de MCD_ (onglet _Options_). Désormais, c'est à cette adresse que Mocodo essaiera de trouver les MCD quand vous mettrez à jour leur titre ;\\n\",\n    \"3. vos étudiants devront eux-mêmes avoir renseigné le champ en question, ce qui peut poser des problèmes à certains. Facilitez-leur la tâche en leur donnant le lien suivant (tout ce qui suit `lib=` doit bien sûr être remplacé par l'adresse de votre répertoire distant) :\\n\",\n    \"\\n\",\n    \"  ```\\n\",\n    \"  https://www.mocodo.net/?lib=https://your_server.com/path/to/your/mcd/directory\\n\",\n    \"  ```\\n\",\n    \"\\n\",\n    \"  Ils n'auront plus qu'à cliquer pour remplir automatiquement le champ approprié, lequel persistera dans les cookies de leur navigateur.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Accès sous terminal ou Jupyter Notebook\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'option `--input` (ou `-i`) est surchargée pour aller chercher un MCD sur internet s'il ne se trouve pas dans le répertoire local. Pour commencer la démonstration, assurons-nous que le fichier en question n'existe pas en local :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 113,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": 113,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"path = Path(\\\"def_weak-974e.mcd\\\")\\n\",\n    \"path.unlink(missing_ok=True)\\n\",\n    \"path.is_file()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Récupérons-le de façon transparente dans la bibliothèque par défaut (avec ou sans extension `.mcd`) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 114,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"344\\\" height=\\\"112\\\" viewBox=\\\"0 0 344 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"344\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"61\\\" y1=\\\"56\\\" x2=\\\"162\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"273\\\" y1=\\\"56\\\" x2=\\\"162\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"162\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"149\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"188\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"188\\\" y1=\\\"74\\\" x2=\\\"206\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"113\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">OEuvre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Cote oeuvre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"97\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date parution</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"9\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"39\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"9\\\" width=\\\"124\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"211\\\" y1=\\\"39\\\" x2=\\\"335\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"222\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Exemplaire</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. exemplaire</text>\\n\",\n       \"\\t<line x1=\\\"219\\\" y1=\\\"59\\\" x2=\\\"327\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Etat du livre</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date d’achat</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i def_weak-974e.mcd\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez qu'au passage, pour le rendre disponible hors ligne, le fichier a été sauvegardé sur votre machine :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 115,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": 115,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"path.is_file()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** Si le paramètre de `-i` est un chemin de la forme `path/to/file.mcd` (avec ou sans extension `.mcd`), c'est la dernière partie du chemin (à savoir `file.mcd`) qui sera récupérée sur le serveur. Par contre, c'est le chemin complet qui déterminera l'emplacement de la sauvegarde.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour utiliser votre propre répertoire distant, passez son URL à l'option `--lib` :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"mocodo -i your_diagram.mcd --lib https://your_server.com/path/to/your/mcd/directory\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"Nous vous conseillons d'ajouter cette option dans votre fichier de paramètres personnalisé `params.json`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Compléments sur l'aspect visuel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Styles\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Plusieurs styles prédéfinis sont distribués avec l'application. Un style se définit comme la combinaison d'une palette de couleurs (répertoire `colors`) avec un dictionnaire de polices et de dimensions (répertoire `shapes`).\\n\",\n    \"\\n\",\n    \"Vous pouvez bien sûr créer vos propres styles en vous inspirant des fichiers fournis. Si vous êtes particulièrement content d'un style, soumettez-le pour inclusion dans une prochaine distribution.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Réglages.** Une approximation de la largeur des caractères des différentes polices a été pré-calculée sous macOS. Il est possible qu'elle soit inexacte, en particulier sous Windows ou Linux. Dans ce cas, en particulier, les traits de soulignement n'atteindront pas ou excéderont la largeur des libellés soulignés. Vous pouvez contourner le problème en appliquant un facteur multiplicatif avec l'argument `--adjust_width`).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Paramétrage du réarrangement automatique\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il est possible de demander à Mocodo de chercher tout seul une « bonne » permutation des définitions des boîtes, ce qui à la main deviendrait vite difficile.\\n\",\n    \"\\n\",\n    \"Le critère que nous avons retenu pour évaluer la qualité du tracé est double :\\n\",\n    \"\\n\",\n    \"1. les liens ne doivent pas se couper ;\\n\",\n    \"2. leur longueur cumulée doit être minimale.\\n\",\n    \"\\n\",\n    \"Actuellement, deux algorithmes d'arrangement sont fournis :\\n\",\n    \"\\n\",\n    \"- un algorithme exact (`bb`, pour _Branch & Bound_), qui ne trouve que des solutions satisfaisant au premier critère ;\\n\",\n    \"- un algorithme approché (`ga`, pour _Genetic Algorithm_), réservé aux cas où il est impossible d'y satisfaire. L'algorithme va alors chercher des solutions où les liens se coupent seulement le moins possible.\\n\",\n    \"\\n\",\n    \"**Remarque.** Mocodo met en œuvre une technique de réarrangement originale : en contraignant la position des boîtes aux intersections d'une grille invisible, il transforme un classique [problème de plongement](https://en.wikipedia.org/wiki/Graph_embedding) en un [problème d'affectation](https://fr.wikipedia.org/wiki/Problème_d%27affectation), ce qui permet de satisfaire de façon efficace à un certain nombre de contraintes esthétiques pertinentes (planarité, compacité, etc.).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Nous illustrerons les algorithmes et leurs paramètres sur le MCD d'accueil de Mocodo online.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le réarrangement automatique peut se faire sans contraintes, ou dans les limites d'une grille spécifiée par l'utilisateur.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Méthode exacte (_branch & bound_)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Arrangement non contraint (par défaut)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le réarrangement dit organique consiste à choisir une première boîte au hasard, puis à essayer d'agréger les autres sans se préoccuper de contenir le tout dans une grille prédéterminée :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 116,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"727\\\" height=\\\"376\\\" viewBox=\\\"0 0 727 376\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"727\\\" height=\\\"376\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"394\\\" y1=\\\"47\\\" x2=\\\"256\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"147\\\" x2=\\\"256\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"256\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"243\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"301\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"301\\\" y1=\\\"65\\\" x2=\\\"319\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EMPLOYER -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"147\\\" x2=\\\"86\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"86\\\" y1=\\\"238\\\" x2=\\\"86\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M130 118 a14 14 90 0 1 14 14 V146 h-116 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M144 146 v16 a14 14 90 0 1 -14 14 H42 a14 14 90 0 1 -14 -14 V146 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"118\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"28\\\" y1=\\\"146\\\" x2=\\\"144\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"36\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"163\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"91\\\" y=\\\"192\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"147\\\" x2=\\\"394\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"394\\\" y1=\\\"238\\\" x2=\\\"394\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M426 118 a14 14 90 0 1 14 14 V146 h-92 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M440 146 v16 a14 14 90 0 1 -14 14 H362 a14 14 90 0 1 -14 -14 V146 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"348\\\" y=\\\"118\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"348\\\" y1=\\\"146\\\" x2=\\\"440\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"356\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"313\\\" y=\\\"163\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_e0826f75(evt,'responsable')\\\" onmouseout=\\\"hide_e0826f75(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"399\\\" y=\\\"192\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"147\\\" x2=\\\"256\\\" y2=\\\"238\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"394\\\" y1=\\\"238\\\" x2=\\\"256\\\" y2=\\\"238\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M306 209 a14 14 90 0 1 14 14 V237 h-128 V223 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M320 237 v16 a14 14 90 0 1 -14 14 H206 a14 14 90 0 1 -14 -14 V237 H128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"192\\\" y=\\\"209\\\" width=\\\"128\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"192\\\" y1=\\\"237\\\" x2=\\\"320\\\" y2=\\\"237\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"199\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TRAVAILLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"325\\\" y=\\\"254\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"394\\\" y1=\\\"238\\\" x2=\\\"524\\\" y2=\\\"238\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"524\\\" y1=\\\"329\\\" x2=\\\"524\\\" y2=\\\"238\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M566 209 a14 14 90 0 1 14 14 V237 h-112 V223 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M580 237 v16 a14 14 90 0 1 -14 14 H482 a14 14 90 0 1 -14 -14 V237 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"468\\\" y=\\\"209\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"468\\\" y1=\\\"237\\\" x2=\\\"580\\\" y2=\\\"237\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"476\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">REQUÉRIR</text>\\n\",\n       \"\\t\\t<text x=\\\"475\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté requise</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"444\\\" y=\\\"254\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"529\\\" y=\\\"283\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONTROLER -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M256 329 C225.33 361 168.67 361 86 329\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"151.01 348.7 163.95 345.17 158.85 350.27 161.6 356.94\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M256 329 C226 297 169.33 297 86 329\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M137 300 a14 14 90 0 1 14 14 V328 h-130 V314 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M151 328 v16 a14 14 90 0 1 -14 14 H35 a14 14 90 0 1 -14 -14 V328 H130\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"21\\\" y=\\\"300\\\" width=\\\"130\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"21\\\" y1=\\\"328\\\" x2=\\\"151\\\" y2=\\\"328\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"28\\\" y=\\\"321.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CONTRÔLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"344\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_e0826f75(evt,'mère')\\\" onmouseout=\\\"hide_e0826f75(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"182\\\" y=\\\"322\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_e0826f75(evt,'filiale')\\\" onmouseout=\\\"hide_e0826f75(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"394\\\" y1=\\\"238\\\" x2=\\\"394\\\" y2=\\\"329\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"524\\\" y1=\\\"329\\\" x2=\\\"394\\\" y2=\\\"329\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"329\\\" x2=\\\"394\\\" y2=\\\"329\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M430 300 a14 14 90 0 1 14 14 V328 h-100 V314 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M444 328 v16 a14 14 90 0 1 -14 14 H358 a14 14 90 0 1 -14 -14 V328 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"344\\\" y=\\\"300\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"344\\\" y1=\\\"328\\\" x2=\\\"444\\\" y2=\\\"328\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"352\\\" y=\\\"321.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOURNIR</text>\\n\",\n       \"\\t\\t<text x=\\\"351\\\" y=\\\"346.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté fournie</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"399\\\" y=\\\"292\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"455\\\" y=\\\"345\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"312\\\" y=\\\"345\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M524 329 C558.67 297 603.33 297 658 329\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M524 329 C558.67 361 603.33 361 658 329\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M704 300 a14 14 90 0 1 14 14 V328 h-120 V314 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M718 328 v16 a14 14 90 0 1 -14 14 H612 a14 14 90 0 1 -14 -14 V328 H120\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"598\\\" y=\\\"300\\\" width=\\\"120\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"598\\\" y1=\\\"328\\\" x2=\\\"718\\\" y2=\\\"328\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"605\\\" y=\\\"321.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMPOSER</text>\\n\",\n       \"\\t\\t<text x=\\\"605\\\" y=\\\"346.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"574\\\" y=\\\"322\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_e0826f75(evt,'composée')\\\" onmouseout=\\\"hide_e0826f75(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"574\\\" y=\\\"344\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_e0826f75(evt,'composante')\\\" onmouseout=\\\"hide_e0826f75(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AYANT_DROIT -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"39\\\" width=\\\"140\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"324\\\" y1=\\\"39\\\" x2=\\\"464\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"332\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">AYANT-DROIT</text>\\n\",\n       \"\\t<text x=\\\"332\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom ayant-droit</text>\\n\",\n       \"\\t<line x1=\\\"332\\\" y1=\\\"59\\\" x2=\\\"433\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"332\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lien</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"109\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"139\\\" width=\\\"104\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"109\\\" width=\\\"104\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"204\\\" y1=\\\"139\\\" x2=\\\"308\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">matricule</text>\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"159\\\" x2=\\\"271\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"200\\\" width=\\\"154\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"230\\\" width=\\\"154\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"200\\\" width=\\\"154\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"230\\\" x2=\\\"163\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"247.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. département</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"250\\\" x2=\\\"132\\\" y2=\\\"250\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"200\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"230\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"200\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"349\\\" y1=\\\"230\\\" x2=\\\"439\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"358\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"247.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"357\\\" y1=\\\"250\\\" x2=\\\"431\\\" y2=\\\"250\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"357\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"205\\\" y=\\\"291\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"205\\\" y=\\\"321\\\" width=\\\"102\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"205\\\" y=\\\"291\\\" width=\\\"102\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"205\\\" y1=\\\"321\\\" x2=\\\"307\\\" y2=\\\"321\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"312.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SOCIÉTÉ</text>\\n\",\n       \"\\t<text x=\\\"213\\\" y=\\\"338.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"213\\\" y1=\\\"341\\\" x2=\\\"293\\\" y2=\\\"341\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"213\\\" y=\\\"355.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_e0826f75 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"291\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"321\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"291\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"479\\\" y1=\\\"321\\\" x2=\\\"569\\\" y2=\\\"321\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"496\\\" y=\\\"312.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"487\\\" y=\\\"338.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"487\\\" y1=\\\"341\\\" x2=\\\"545\\\" y2=\\\"341\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"487\\\" y=\\\"355.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_e0826f75(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 331) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_e0826f75\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_e0826f75\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_e0826f75(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_e0826f75\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_e0826f75\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_e0826f75\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_e0826f75\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_e0826f75\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_e0826f75\\\" text-anchor=\\\"middle\\\" x=\\\"363\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_e0826f75\\\" x=\\\"0\\\" y=\\\"336\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_e0826f75\\\" text-anchor=\\\"middle\\\" x=\\\"363\\\" y=\\\"360\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cela donne un plongement sur une grille $5\\\\times4$, ce qui est loin d'être optimal. Cependant, l'arrangement organique fournit souvent un bon point de départ pour chercher soi-même une permutation plus esthétique ou mettant en évidence certaines propriétés du MCD.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Arrangement dans la grille courante\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le réarrangement automatique des boîtes peut s'opérer dans les limites de la grille courante ; c'est-à-dire que le MCD résultant aura (au plus) le même nombre de colonnes et de rangées que le texte de départ (ici, $4\\\\times5$) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 117,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"743\\\" height=\\\"294\\\" viewBox=\\\"0 0 743 294\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"743\\\" height=\\\"294\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association EMPLOYER -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"47\\\" x2=\\\"86\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"86\\\" y1=\\\"147\\\" x2=\\\"86\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M130 18 a14 14 90 0 1 14 14 V46 h-116 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M144 46 v16 a14 14 90 0 1 -14 14 H42 a14 14 90 0 1 -14 -14 V46 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"18\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"28\\\" y1=\\\"46\\\" x2=\\\"144\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"36\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"150\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"91\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"47\\\" x2=\\\"389\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"47\\\" x2=\\\"389\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M439 18 a14 14 90 0 1 14 14 V46 h-128 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M453 46 v16 a14 14 90 0 1 -14 14 H339 a14 14 90 0 1 -14 -14 V46 H128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"325\\\" y=\\\"18\\\" width=\\\"128\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"325\\\" y1=\\\"46\\\" x2=\\\"453\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"332\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TRAVAILLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"39\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"465\\\" y=\\\"39\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"47\\\" x2=\\\"674\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"147\\\" x2=\\\"674\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M716 18 a14 14 90 0 1 14 14 V46 h-112 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M730 46 v16 a14 14 90 0 1 -14 14 H632 a14 14 90 0 1 -14 -14 V46 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"618\\\" y=\\\"18\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"618\\\" y1=\\\"46\\\" x2=\\\"730\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"626\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">REQUÉRIR</text>\\n\",\n       \"\\t\\t<text x=\\\"625\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté requise</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"584\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"679\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"247\\\" x2=\\\"225\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"47\\\" x2=\\\"225\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"225\\\" cy=\\\"147\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"212\\\" y=\\\"151.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"230\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"230\\\" y1=\\\"203\\\" x2=\\\"248\\\" y2=\\\"203\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"201\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"47\\\" x2=\\\"389\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"47\\\" x2=\\\"389\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M421 118 a14 14 90 0 1 14 14 V146 h-92 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M435 146 v16 a14 14 90 0 1 -14 14 H357 a14 14 90 0 1 -14 -14 V146 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"343\\\" y=\\\"118\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"343\\\" y1=\\\"146\\\" x2=\\\"435\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"351\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"75.42\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_64ca7141(evt,'responsable')\\\" onmouseout=\\\"hide_64ca7141(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"466\\\" y=\\\"75.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"47\\\" x2=\\\"534\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"674\\\" y1=\\\"147\\\" x2=\\\"534\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"247\\\" x2=\\\"534\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M570 118 a14 14 90 0 1 14 14 V146 h-100 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M584 146 v16 a14 14 90 0 1 -14 14 H498 a14 14 90 0 1 -14 -14 V146 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"484\\\" y=\\\"118\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"484\\\" y1=\\\"146\\\" x2=\\\"584\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"492\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOURNIR</text>\\n\",\n       \"\\t\\t<text x=\\\"491\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté fournie</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"539\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"605\\\" y=\\\"163\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"539\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONTROLER -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M534 247 C495 279 446.67 279 389 247\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"454.01 270.08 466.66 265.61 461.95 271.07 465.17 277.52\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M534 247 C495.67 215 447.33 215 389 247\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M440 218 a14 14 90 0 1 14 14 V246 h-130 V232 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M454 246 v16 a14 14 90 0 1 -14 14 H338 a14 14 90 0 1 -14 -14 V246 H130\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"218\\\" width=\\\"130\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"324\\\" y1=\\\"246\\\" x2=\\\"454\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"331\\\" y=\\\"239.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CONTRÔLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"459\\\" y=\\\"262\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_64ca7141(evt,'mère')\\\" onmouseout=\\\"hide_64ca7141(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"460\\\" y=\\\"240\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_64ca7141(evt,'filiale')\\\" onmouseout=\\\"hide_64ca7141(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M674 147 C712.67 180.33 712.67 213.67 674 247\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M674 147 C635.33 180.33 635.33 213.67 674 247\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M720 218 a14 14 90 0 1 14 14 V246 h-120 V232 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M734 246 v16 a14 14 90 0 1 -14 14 H628 a14 14 90 0 1 -14 -14 V246 H120\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"614\\\" y=\\\"218\\\" width=\\\"120\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"614\\\" y1=\\\"246\\\" x2=\\\"734\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"621\\\" y=\\\"239.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMPOSER</text>\\n\",\n       \"\\t\\t<text x=\\\"621\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"677\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_64ca7141(evt,'composée')\\\" onmouseout=\\\"hide_64ca7141(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"652\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_64ca7141(evt,'composante')\\\" onmouseout=\\\"hide_64ca7141(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"173\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"173\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"173\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"173\\\" y1=\\\"39\\\" x2=\\\"277\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">matricule</text>\\n\",\n       \"\\t<line x1=\\\"181\\\" y1=\\\"59\\\" x2=\\\"240\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"489\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"489\\\" y=\\\"39\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"489\\\" y=\\\"9\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"489\\\" y1=\\\"39\\\" x2=\\\"579\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"498\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"497\\\" y1=\\\"59\\\" x2=\\\"571\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"497\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"154\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"139\\\" width=\\\"154\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"154\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"139\\\" x2=\\\"163\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. département</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"159\\\" x2=\\\"132\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"629\\\" y=\\\"109\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"629\\\" y=\\\"139\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"629\\\" y=\\\"109\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"629\\\" y1=\\\"139\\\" x2=\\\"719\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"646\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"637\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"637\\\" y1=\\\"159\\\" x2=\\\"695\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"637\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AYANT_DROIT -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"155\\\" y=\\\"209\\\" width=\\\"140\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"155\\\" y=\\\"239\\\" width=\\\"140\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"155\\\" y=\\\"209\\\" width=\\\"140\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"155\\\" y1=\\\"239\\\" x2=\\\"295\\\" y2=\\\"239\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"163\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">AYANT-DROIT</text>\\n\",\n       \"\\t<text x=\\\"163\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom ayant-droit</text>\\n\",\n       \"\\t<line x1=\\\"163\\\" y1=\\\"259\\\" x2=\\\"264\\\" y2=\\\"259\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"163\\\" y=\\\"273.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lien</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_64ca7141 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"209\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"239\\\" width=\\\"102\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"209\\\" width=\\\"102\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"483\\\" y1=\\\"239\\\" x2=\\\"585\\\" y2=\\\"239\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"494\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SOCIÉTÉ</text>\\n\",\n       \"\\t<text x=\\\"491\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"491\\\" y1=\\\"259\\\" x2=\\\"571\\\" y2=\\\"259\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"491\\\" y=\\\"273.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_64ca7141(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 249) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_64ca7141\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_64ca7141\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_64ca7141(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_64ca7141\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_64ca7141\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_64ca7141\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_64ca7141\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_64ca7141\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_64ca7141\\\" text-anchor=\\\"middle\\\" x=\\\"371\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_64ca7141\\\" x=\\\"0\\\" y=\\\"254\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_64ca7141\\\" text-anchor=\\\"middle\\\" x=\\\"371\\\" y=\\\"278\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange:current\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Arrangement en privilégiant la largeur\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans un document paginé, on cherche en général à utiliser en priorité l'espace horizontal. La version 4.0 introduit à cet effet une option de réarrangement « en largeur d'abord ». Le MCD d'accueil s'y prête particulièrement bien :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 118,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"920\\\" height=\\\"161\\\" viewBox=\\\"0 0 920 161\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"920\\\" height=\\\"161\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"63\\\" y1=\\\"39\\\" x2=\\\"158\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"290\\\" y1=\\\"39\\\" x2=\\\"158\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"158\\\" cy=\\\"39\\\" r=\\\"16\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"148\\\" y=\\\"43.5\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"123\\\" y=\\\"51.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"123\\\" y1=\\\"53.2\\\" x2=\\\"138\\\" y2=\\\"53.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"229\\\" y=\\\"51.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"290\\\" y1=\\\"39\\\" x2=\\\"412\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"532\\\" y1=\\\"39\\\" x2=\\\"412\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M437.8 15 a11.2 11.2 90 0 1 11.2 11.2 V38 h-74 V26.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M449 38 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H386.2 a11.2 11.2 90 0 1 -11.2 -11.2 V38 H74\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"375\\\" y=\\\"15\\\" width=\\\"74\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"375\\\" y1=\\\"38\\\" x2=\\\"449\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"381\\\" y=\\\"32.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"336\\\" y=\\\"32.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\" onmouseover=\\\"show_6fea9945(evt,'responsable')\\\" onmouseout=\\\"hide_6fea9945(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"477\\\" y=\\\"32.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"532\\\" y1=\\\"39\\\" x2=\\\"636\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"636\\\" y1=\\\"122\\\" x2=\\\"636\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"744\\\" y1=\\\"39\\\" x2=\\\"636\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M664.8 15 a11.2 11.2 90 0 1 11.2 11.2 V38 h-80 V26.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M676 38 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H607.2 a11.2 11.2 90 0 1 -11.2 -11.2 V38 H80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"596\\\" y=\\\"15\\\" width=\\\"80\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"596\\\" y1=\\\"38\\\" x2=\\\"676\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"602\\\" y=\\\"32.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">FOURNIR</text>\\n\",\n       \"\\t\\t<text x=\\\"602\\\" y=\\\"53.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">qté fournie</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"572\\\" y=\\\"51.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"640\\\" y=\\\"83.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"685\\\" y=\\\"51.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONTROLER -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M744 39 C774 13.67 812.67 13.67 860 39\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<polygon points=\\\"806.99 20.71 796.88 24.32 800.64 19.94 798.05 14.79\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M744 39 C774 64.33 812.67 64.33 860 39\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M901.8 15 a11.2 11.2 90 0 1 11.2 11.2 V38 h-106 V26.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M913 38 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H818.2 a11.2 11.2 90 0 1 -11.2 -11.2 V38 H106\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"807\\\" y=\\\"15\\\" width=\\\"106\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"807\\\" y1=\\\"38\\\" x2=\\\"913\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"814\\\" y=\\\"32.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">CONTRÔLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"788\\\" y=\\\"33.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\" onmouseover=\\\"show_6fea9945(evt,'mère')\\\" onmouseout=\\\"hide_6fea9945(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"788\\\" y=\\\"50.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\" onmouseover=\\\"show_6fea9945(evt,'filiale')\\\" onmouseout=\\\"hide_6fea9945(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association EMPLOYER -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"290\\\" y1=\\\"39\\\" x2=\\\"290\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"158\\\" y1=\\\"122\\\" x2=\\\"290\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M325.8 98 a11.2 11.2 90 0 1 11.2 11.2 V121 h-94 V109.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M337 121 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H254.2 a11.2 11.2 90 0 1 -11.2 -11.2 V121 H94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"243\\\" y=\\\"98\\\" width=\\\"94\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"243\\\" y1=\\\"121\\\" x2=\\\"337\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"250\\\" y=\\\"115.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">EMPLOYER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"83.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"224\\\" y=\\\"134.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"290\\\" y1=\\\"39\\\" x2=\\\"412\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"532\\\" y1=\\\"39\\\" x2=\\\"412\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M452.8 98 a11.2 11.2 90 0 1 11.2 11.2 V121 h-104 V109.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M464 121 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H371.2 a11.2 11.2 90 0 1 -11.2 -11.2 V121 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"98\\\" width=\\\"104\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"360\\\" y1=\\\"121\\\" x2=\\\"464\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"367\\\" y=\\\"115.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">TRAVAILLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"336\\\" y=\\\"65.34\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"477\\\" y=\\\"61.72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"532\\\" y1=\\\"39\\\" x2=\\\"532\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<line x1=\\\"636\\\" y1=\\\"122\\\" x2=\\\"532\\\" y2=\\\"122\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M565.8 98 a11.2 11.2 90 0 1 11.2 11.2 V121 h-90 V109.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M577 121 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H498.2 a11.2 11.2 90 0 1 -11.2 -11.2 V121 H90\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"487\\\" y=\\\"98\\\" width=\\\"90\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"487\\\" y1=\\\"121\\\" x2=\\\"577\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"493\\\" y=\\\"115.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">REQUÉRIR</text>\\n\",\n       \"\\t\\t<text x=\\\"493\\\" y=\\\"136.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">qté requise</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"536\\\" y=\\\"83.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"581\\\" y=\\\"134.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M636 122 C663.33 96.67 699.33 96.67 744 122\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<path d=\\\"M636 122 C663.33 147.33 699.33 147.33 744 122\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M781.8 98 a11.2 11.2 90 0 1 11.2 11.2 V121 h-98 V109.2 a11.2 11.2 90 0 1 11.2 -11.2\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M793 121 v13.8 a11.2 11.2 90 0 1 -11.2 11.2 H706.2 a11.2 11.2 90 0 1 -11.2 -11.2 V121 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"695\\\" y=\\\"98\\\" width=\\\"98\\\" height=\\\"48\\\" fill=\\\"none\\\" rx=\\\"11.2\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"695\\\" y1=\\\"121\\\" x2=\\\"793\\\" y2=\\\"121\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"702\\\" y=\\\"115.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">COMPOSER</text>\\n\",\n       \"\\t\\t<text x=\\\"701\\\" y=\\\"136.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"676\\\" y=\\\"116.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\" onmouseover=\\\"show_6fea9945(evt,'composée')\\\" onmouseout=\\\"hide_6fea9945(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"676\\\" y=\\\"133.6\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"8.8\\\" onmouseover=\\\"show_6fea9945(evt,'composante')\\\" onmouseout=\\\"hide_6fea9945(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AYANT_DROIT -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"7\\\" y=\\\"7\\\" width=\\\"112\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"7\\\" y=\\\"32\\\" width=\\\"112\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"7\\\" y=\\\"7\\\" width=\\\"112\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"7\\\" y1=\\\"32\\\" x2=\\\"119\\\" y2=\\\"32\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"14\\\" y=\\\"24.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">AYANT-DROIT</text>\\n\",\n       \"\\t<text x=\\\"13\\\" y=\\\"46.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">nom ayant-droit</text>\\n\",\n       \"\\t<line x1=\\\"13\\\" y1=\\\"48.6\\\" x2=\\\"94\\\" y2=\\\"48.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\" stroke-dasharray=\\\"3.2\\\"/>\\n\",\n       \"\\t<text x=\\\"13\\\" y=\\\"60.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">lien</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"248\\\" y=\\\"7\\\" width=\\\"84\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"248\\\" y=\\\"32\\\" width=\\\"84\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"248\\\" y=\\\"7\\\" width=\\\"84\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"248\\\" y1=\\\"32\\\" x2=\\\"332\\\" y2=\\\"32\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"255\\\" y=\\\"24.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"46.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">matricule</text>\\n\",\n       \"\\t<line x1=\\\"254\\\" y1=\\\"48.6\\\" x2=\\\"301\\\" y2=\\\"48.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"254\\\" y=\\\"60.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"496\\\" y=\\\"7\\\" width=\\\"72\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"496\\\" y=\\\"32\\\" width=\\\"72\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"496\\\" y=\\\"7\\\" width=\\\"72\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"496\\\" y1=\\\"32\\\" x2=\\\"568\\\" y2=\\\"32\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"24.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"46.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"502\\\" y1=\\\"48.6\\\" x2=\\\"561\\\" y2=\\\"48.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"502\\\" y=\\\"60.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"704\\\" y=\\\"7\\\" width=\\\"80\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"704\\\" y=\\\"32\\\" width=\\\"80\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"704\\\" y=\\\"7\\\" width=\\\"80\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"704\\\" y1=\\\"32\\\" x2=\\\"784\\\" y2=\\\"32\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"712\\\" y=\\\"24.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">SOCIÉTÉ</text>\\n\",\n       \"\\t<text x=\\\"710\\\" y=\\\"46.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"710\\\" y1=\\\"48.6\\\" x2=\\\"774\\\" y2=\\\"48.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"710\\\" y=\\\"60.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"96\\\" y=\\\"90\\\" width=\\\"124\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"96\\\" y=\\\"115\\\" width=\\\"124\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"96\\\" y=\\\"90\\\" width=\\\"124\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"96\\\" y1=\\\"115\\\" x2=\\\"220\\\" y2=\\\"115\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"107.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"129.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">num. département</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"131.6\\\" x2=\\\"194\\\" y2=\\\"131.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"143.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_6fea9945 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"600\\\" y=\\\"90\\\" width=\\\"72\\\" height=\\\"25\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"600\\\" y=\\\"115\\\" width=\\\"72\\\" height=\\\"39\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"600\\\" y=\\\"90\\\" width=\\\"72\\\" height=\\\"64\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"600\\\" y1=\\\"115\\\" x2=\\\"672\\\" y2=\\\"115\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.2\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"614\\\" y=\\\"107.75\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"14.4\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"606\\\" y=\\\"129.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"606\\\" y1=\\\"131.6\\\" x2=\\\"653\\\" y2=\\\"131.6\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.8\\\"/>\\n\",\n       \"\\t<text x=\\\"606\\\" y=\\\"143.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"12\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_6fea9945(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 125) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_6fea9945\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_6fea9945\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_6fea9945(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_6fea9945\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_6fea9945\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_6fea9945\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_6fea9945\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_6fea9945\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"32\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_6fea9945\\\" text-anchor=\\\"middle\\\" x=\\\"460\\\" y=\\\"19.2\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"12.8\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_6fea9945\\\" x=\\\"0\\\" y=\\\"129\\\" width=\\\"100%\\\" height=\\\"32\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_6fea9945\\\" text-anchor=\\\"middle\\\" x=\\\"460\\\" y=\\\"148.2\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"12.8\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange:wide=8 --scale 0.8\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ici, l'utilisateur a demandé $8$ boîtes en largeur (c'est aussi la valeur par défaut). L'algorithme commence par calculer le nombre de lignes minimal correspondant, sachant qu'il a $14$ boîtes à placer : c'est $\\\\lceil14/8\\\\rceil=2$. Il cherche donc un plongement sur une grille $8\\\\times2$.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Arrangement dans une grille équilibrée minimale\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"On peut chercher à faire tenir le MCD dans la plus petite grille possible, tout en maintenant entre hauteur et largeur un rapport « équilibré » (ou proche du [nombre d'or](https://fr.wikipedia.org/wiki/Nombre_d%27or)). Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles:\\n\",\n    \"\\n\",\n    \"- $13\\\\times1$;\\n\",\n    \"- $7\\\\times2$, ce qui laisse 1 case vide;\\n\",\n    \"- $5\\\\times3$, ce qui laisse 2 cases vides;\\n\",\n    \"- $4\\\\times4$, ce qui laisse 3 cases vides;\\n\",\n    \"- etc.\\n\",\n    \"\\n\",\n    \"Les deux premières grilles étant non équilibrées, on retiendra la plus petite des suivantes, de dimensions $5\\\\times3$.\\n\",\n    \"\\n\",\n    \"La table ci-dessous énumère les dimensions des grilles minimales d'équilibre supérieur à 0,5 pour tous les MCD comportant moins de 100 boîtes. On peut y vérifier par exemple que le MCD de taille 13 (en gras) se trouve effectivement aux coordonnées (5, 3).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"|  | **1** | **2** | **3** | **4** | **5** | **6** | **7** | **8** | **9** | **10** | **11** | **12** | **13** |\\n\",\n    \"|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\\n\",\n    \"| **1** | 1 | 2 | 3 |  |  |  |  |  |  |  |  |  |  |\\n\",\n    \"| **2** |  | 4 | 5, 6 |  |  |  |  |  |  |  |  |  |  |\\n\",\n    \"| **3** |  |  | 7, 8, 9 | 10, 11, 12 | **13**, 14, 15 |  |  |  |  |  |  |  |  |\\n\",\n    \"| **4** |  |  |  | 16 | 17, 18, 19, 20 | 21, 22, 23, 24 | 26, 27, 28 |  |  |  |  |  |  |\\n\",\n    \"| **5** |  |  |  |  | 25 | 29, 30 | 31, 32, 33, 34, 35 | 37, 38, 39, 40 | 43, 44, 45 |  |  |  |  |\\n\",\n    \"| **6** |  |  |  |  |  | 36 | 41, 42 | 46, 47, 48 | 50, 51, 52, 53, 54 | 57, 58, 59, 60 | 65, 66 |  |  |\\n\",\n    \"| **7** |  |  |  |  |  |  | 49 | 55, 56 | 61, 62, 63 | 67, 68, 69, 70 | 73, 74, 75, 76, 77 | 82, 83, 84 | 91 |\\n\",\n    \"| **8** |  |  |  |  |  |  |  | 64 | 71, 72 | 78, 79, 80 | 85, 86, 87, 88 | 92, 93, 94, 95, 96 |  |\\n\",\n    \"| **9** |  |  |  |  |  |  |  |  | 81 | 89, 90 | 97, 98, 99 |  |  |\\n\",\n    \"| **10** |  |  |  |  |  |  |  |  |  | 100 |  |  |  |\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le MCD d'accueil ayant déjà été arrangé avec l'option `-t arrange:balanced`, nous ne le reproduisons pas ici. Sachez cependant qu'au cas où, pour une raison ou une autre, la plus petite grille équilibrée ne convient pas, il est possible de passer à la $i^\\\\text{e}$ suivante en mettant $i$ en sous-sous-argument. Ici, pour $14$ boîtes, `balanced=1` permet donc de passer de la grille $5\\\\times3$ (prévue pour $13$, $14$ et $15$ boîtes) à la grille $4\\\\times4$ (prévue pour $16$ boîtes).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 119,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"613\\\" height=\\\"367\\\" viewBox=\\\"0 0 613 367\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"613\\\" height=\\\"367\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association EMPLOYER -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"47\\\" x2=\\\"86\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"86\\\" y1=\\\"138\\\" x2=\\\"86\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M130 18 a14 14 90 0 1 14 14 V46 h-116 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M144 46 v16 a14 14 90 0 1 -14 14 H42 a14 14 90 0 1 -14 -14 V46 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"28\\\" y=\\\"18\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"28\\\" y1=\\\"46\\\" x2=\\\"144\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"36\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"181\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"91\\\" y=\\\"92\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"47\\\" x2=\\\"395\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"47\\\" x2=\\\"395\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"395\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"382\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"441\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"441\\\" y1=\\\"65\\\" x2=\\\"459\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"313\\\" y=\\\"39\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"47\\\" x2=\\\"256\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"395\\\" y1=\\\"229\\\" x2=\\\"256\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M306 109 a14 14 90 0 1 14 14 V137 h-128 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M320 137 v16 a14 14 90 0 1 -14 14 H206 a14 14 90 0 1 -14 -14 V137 H128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"192\\\" y=\\\"109\\\" width=\\\"128\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"192\\\" y1=\\\"137\\\" x2=\\\"320\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"199\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TRAVAILLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"232\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"326\\\" y=\\\"210.51\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DIRIGER -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"47\\\" x2=\\\"395\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"395\\\" y1=\\\"229\\\" x2=\\\"395\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M427 109 a14 14 90 0 1 14 14 V137 h-92 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M441 137 v16 a14 14 90 0 1 -14 14 H363 a14 14 90 0 1 -14 -14 V137 H92\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"349\\\" y=\\\"109\\\" width=\\\"92\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"349\\\" y1=\\\"137\\\" x2=\\\"441\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"357\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIRIGER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"313\\\" y=\\\"78.07\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_449f4233(evt,'responsable')\\\" onmouseout=\\\"hide_449f4233(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"400\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"395\\\" y1=\\\"229\\\" x2=\\\"256\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"320\\\" x2=\\\"256\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M298 200 a14 14 90 0 1 14 14 V228 h-112 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M312 228 v16 a14 14 90 0 1 -14 14 H214 a14 14 90 0 1 -14 -14 V228 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"200\\\" y=\\\"200\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"200\\\" y1=\\\"228\\\" x2=\\\"312\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"208\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">REQUÉRIR</text>\\n\",\n       \"\\t\\t<text x=\\\"207\\\" y=\\\"246.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté requise</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"326\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"274\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CONTROLER -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M534 320 C495.33 283.67 495.33 253.33 534 229\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"507.13 257.99 508.65 271.32 504.39 265.51 497.38 267.21\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<path d=\\\"M534 320 C571.33 283.67 571.33 253.33 534 229\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M585 200 a14 14 90 0 1 14 14 V228 h-130 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M599 228 v16 a14 14 90 0 1 -14 14 H483 a14 14 90 0 1 -14 -14 V228 H130\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"469\\\" y=\\\"200\\\" width=\\\"130\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"469\\\" y1=\\\"228\\\" x2=\\\"599\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"476\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CONTRÔLER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"512\\\" y=\\\"274\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_449f4233(evt,'mère')\\\" onmouseout=\\\"hide_449f4233(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"537\\\" y=\\\"274\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_449f4233(evt,'filiale')\\\" onmouseout=\\\"hide_449f4233(evt)\\\" style=\\\"cursor: pointer;\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<path d=\\\"M256 320 C233.33 352 176.67 352 86 320\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M256 320 C233.33 288 176.67 288 86 320\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M132 291 a14 14 90 0 1 14 14 V319 h-120 V305 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M146 319 v16 a14 14 90 0 1 -14 14 H40 a14 14 90 0 1 -14 -14 V319 H120\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"26\\\" y=\\\"291\\\" width=\\\"120\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"26\\\" y1=\\\"319\\\" x2=\\\"146\\\" y2=\\\"319\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"33\\\" y=\\\"312.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMPOSER</text>\\n\",\n       \"\\t\\t<text x=\\\"33\\\" y=\\\"337.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"187\\\" y=\\\"335\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_449f4233(evt,'composée')\\\" onmouseout=\\\"hide_449f4233(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"187\\\" y=\\\"313\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" onmouseover=\\\"show_449f4233(evt,'composante')\\\" onmouseout=\\\"hide_449f4233(evt)\\\" style=\\\"cursor: pointer;\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association FOURNIR -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<line x1=\\\"395\\\" y1=\\\"229\\\" x2=\\\"395\\\" y2=\\\"320\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"320\\\" x2=\\\"395\\\" y2=\\\"320\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"534\\\" y1=\\\"320\\\" x2=\\\"395\\\" y2=\\\"320\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M431 291 a14 14 90 0 1 14 14 V319 h-100 V305 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M445 319 v16 a14 14 90 0 1 -14 14 H359 a14 14 90 0 1 -14 -14 V319 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"345\\\" y=\\\"291\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"345\\\" y1=\\\"319\\\" x2=\\\"445\\\" y2=\\\"319\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"353\\\" y=\\\"312.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">FOURNIR</text>\\n\",\n       \"\\t\\t<text x=\\\"352\\\" y=\\\"337.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">qté fournie</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"400\\\" y=\\\"283\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"306\\\" y=\\\"336\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"459\\\" y=\\\"336\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"204\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"204\\\" y1=\\\"39\\\" x2=\\\"308\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EMPLOYÉ</text>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">matricule</text>\\n\",\n       \"\\t<line x1=\\\"212\\\" y1=\\\"59\\\" x2=\\\"271\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"212\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom employé</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity AYANT_DROIT -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"464\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"464\\\" y=\\\"39\\\" width=\\\"140\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"464\\\" y=\\\"9\\\" width=\\\"140\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"464\\\" y1=\\\"39\\\" x2=\\\"604\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"472\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">AYANT-DROIT</text>\\n\",\n       \"\\t<text x=\\\"472\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom ayant-droit</text>\\n\",\n       \"\\t<line x1=\\\"472\\\" y1=\\\"59\\\" x2=\\\"573\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"472\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lien</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"100\\\" width=\\\"154\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"130\\\" width=\\\"154\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"100\\\" width=\\\"154\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"130\\\" x2=\\\"163\\\" y2=\\\"130\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"121.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DÉPARTEMENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"147.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. département</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"150\\\" x2=\\\"132\\\" y2=\\\"150\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom département</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"350\\\" y=\\\"191\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"350\\\" y=\\\"221\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"350\\\" y=\\\"191\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"350\\\" y1=\\\"221\\\" x2=\\\"440\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"359\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"358\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. projet</text>\\n\",\n       \"\\t<line x1=\\\"358\\\" y1=\\\"241\\\" x2=\\\"432\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"358\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom projet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"282\\\" width=\\\"90\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"312\\\" width=\\\"90\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"282\\\" width=\\\"90\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"211\\\" y1=\\\"312\\\" x2=\\\"301\\\" y2=\\\"312\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"228\\\" y=\\\"303.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"329.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. pièce</text>\\n\",\n       \"\\t<line x1=\\\"219\\\" y1=\\\"332\\\" x2=\\\"277\\\" y2=\\\"332\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"219\\\" y=\\\"346.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé pièce</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SOCIETE -->\\n\",\n       \"<g class=\\\"page_0_449f4233 diagram_page\\\" visibility=\\\"visible\\\">\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"282\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"312\\\" width=\\\"102\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"483\\\" y=\\\"282\\\" width=\\\"102\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"483\\\" y1=\\\"312\\\" x2=\\\"585\\\" y2=\\\"312\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"494\\\" y=\\\"303.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SOCIÉTÉ</text>\\n\",\n       \"\\t<text x=\\\"491\\\" y=\\\"329.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. société</text>\\n\",\n       \"\\t<line x1=\\\"491\\\" y1=\\\"332\\\" x2=\\\"571\\\" y2=\\\"332\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"491\\\" y=\\\"346.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">raison sociale</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Notes -->\\n\",\n       \"<script type=\\\"text/ecmascript\\\">\\n\",\n       \"<![CDATA[\\n\",\n       \"\\tfunction show_449f4233(evt, text) {\\n\",\n       \"\\t\\tvar pos = (evt.target.getAttribute(\\\"y\\\") < 322) ? \\\"bottom\\\" : \\\"top\\\";\\n\",\n       \"\\t\\tvar note = document.getElementById(pos + \\\"_note_449f4233\\\");\\n\",\n       \"\\t\\tnote.textContent = text;\\n\",\n       \"\\t\\tnote.setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t\\tdocument.getElementById(pos + \\\"_overlay_449f4233\\\").setAttributeNS(null, \\\"visibility\\\", \\\"visible\\\");\\n\",\n       \"\\t}\\n\",\n       \"\\tfunction hide_449f4233(evt) {\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_note_449f4233\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"top_overlay_449f4233\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_note_449f4233\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t\\tdocument.getElementById(\\\"bottom_overlay_449f4233\\\").setAttributeNS(null, \\\"visibility\\\", \\\"hidden\\\");\\n\",\n       \"\\t}\\n\",\n       \"]]>\\n\",\n       \"</script>\\n\",\n       \"<rect id=\\\"top_overlay_449f4233\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"top_note_449f4233\\\" text-anchor=\\\"middle\\\" x=\\\"306\\\" y=\\\"24\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<rect id=\\\"bottom_overlay_449f4233\\\" x=\\\"0\\\" y=\\\"327\\\" width=\\\"100%\\\" height=\\\"40\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\" opacity=\\\"0.7\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"<text id=\\\"bottom_note_449f4233\\\" text-anchor=\\\"middle\\\" x=\\\"306\\\" y=\\\"351\\\" fill=\\\"#FFFFFF\\\" font-family=\\\"Futura\\\" font-size=\\\"16\\\" visibility=\\\"hidden\\\"/>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ../examples/landing --select mcd --seed=1 -t arrange:balanced=1\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \" #### Limitations de la méthode exacte\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le réarrangement exact ne fonctionnera jamais sur les MCD non planaires ou n'admettant aucun plongement planaire dans les limites de la grille spécifiée (par les sous-options `current`, `wide` ou `balanced`).\\n\",\n    \"\\n\",\n    \"Rappelons qu'un graphe est dit [planaire](https://fr.wikipedia.org/wiki/Graphe_planaire) lorsqu'il en existe au moins un arrangement sans croisement. Le graphe non planaire comportant le plus petit nombre de liens est connu sous le doux nom de [$K_{3,3}$](https://www.rodhilton.com/2011/10/29/why-the-complete-bipartite-graph-k33-is-not-planar/) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 120,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"426\\\" height=\\\"194\\\" viewBox=\\\"0 0 426 194\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"426\\\" height=\\\"194\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RHONCUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"66\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"211\\\" y1=\\\"56\\\" x2=\\\"66\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"358\\\" y1=\\\"56\\\" x2=\\\"66\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M106 127 a14 14 90 0 1 14 14 V155 h-108 V141 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M120 155 v16 a14 14 90 0 1 -14 14 H26 a14 14 90 0 1 -14 -14 V155 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"12\\\" y=\\\"127\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"12\\\" y1=\\\"155\\\" x2=\\\"120\\\" y2=\\\"155\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"19\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">RHONCUS</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"93.95\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"275\\\" y=\\\"70.88\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SODALES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"211\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"211\\\" y1=\\\"56\\\" x2=\\\"211\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"358\\\" y1=\\\"56\\\" x2=\\\"211\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M248 127 a14 14 90 0 1 14 14 V155 h-102 V141 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M262 155 v16 a14 14 90 0 1 -14 14 H174 a14 14 90 0 1 -14 -14 V155 H102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"160\\\" y=\\\"127\\\" width=\\\"102\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"160\\\" y1=\\\"155\\\" x2=\\\"262\\\" y2=\\\"155\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"168\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SODALES</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"92.57\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"275\\\" y=\\\"93.34\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association QUIS_ENIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"358\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"211\\\" y1=\\\"56\\\" x2=\\\"358\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"358\\\" y1=\\\"56\\\" x2=\\\"358\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M400 127 a14 14 90 0 1 14 14 V155 h-112 V141 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M414 155 v16 a14 14 90 0 1 -14 14 H316 a14 14 90 0 1 -14 -14 V155 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"302\\\" y=\\\"127\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"302\\\" y1=\\\"155\\\" x2=\\\"414\\\" y2=\\\"155\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"309\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">QUIS ENIM</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"70.19\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"275\\\" y=\\\"93.34\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"363\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DIGNISSIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"123\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIGNISSIM</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nec sem</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"69\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nunc</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vulputate</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity IMPERDIET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"152\\\" y1=\\\"39\\\" x2=\\\"270\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"161\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">IMPERDIET</text>\\n\",\n       \"\\t<text x=\\\"160\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">a praesent</text>\\n\",\n       \"\\t<line x1=\\\"160\\\" y1=\\\"59\\\" x2=\\\"225\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"160\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nibh</text>\\n\",\n       \"\\t<text x=\\\"160\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">semper</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TINCIDUNT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"299\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"299\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"299\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"299\\\" y1=\\\"39\\\" x2=\\\"417\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"307\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TINCIDUNT</text>\\n\",\n       \"\\t<text x=\\\"307\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">faucibus</text>\\n\",\n       \"\\t<line x1=\\\"307\\\" y1=\\\"59\\\" x2=\\\"357\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"307\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">orci</text>\\n\",\n       \"\\t<text x=\\\"307\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cursus</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"DIGNISSIM: nec sem, nunc, vulputate\\n\",\n    \"IMPERDIET: a praesent, nibh, semper\\n\",\n    \"TINCIDUNT: faucibus, orci, cursus\\n\",\n    \"\\n\",\n    \"RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n    \"SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n    \"QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Son réarrangement par _Branch & bound_ échouera donc nécessairement :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 121,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.9 - Impossible de calculer un plongement planaire satisfaisant la contrainte\\n\",\n      \"donnée.\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --seed=1 -t arrange:balanced\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme on voit, Mocodo ne cherche pas à savoir si la non-planarité est intrinsèque au graphe, ou résulte des dimensions de la grille imposée pour le plongement. Pour en avoir le cœur net, tentez un arrangement non contraint :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 122,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.41 - Impossible de calculer un plongement planaire.\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --seed=1 -t arrange\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme exact (_Branch and Bound_) :\\n\",\n    \"\\n\",\n    \"- `call_limit` : nombre maximal d'appels pour une boîte de départ donnée (défaut: `10000`).\\n\",\n    \"- `min_objective` : meilleur objectif esthétique pour la mise en page (défaut: `0`).\\n\",\n    \"- `max_objective` : pire objectif esthétique pour la mise en page (défaut: `15`).\\n\",\n    \"\\n\",\n    \"Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Méthode heuristique (algorithme génétique)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans tous les cas où la méthode exacte ne produit pas de résultat satisfaisant, on pourra se rabattre sur une heuristique qui, au lieu d'interdire les croisements, cherchera simplement à en minimiser le nombre.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 123,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"418\\\" height=\\\"230\\\" viewBox=\\\"0 0 418 230\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"418\\\" height=\\\"230\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RHONCUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"206\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"350\\\" y1=\\\"56\\\" x2=\\\"206\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"206\\\" y1=\\\"174\\\" x2=\\\"206\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M246 27 a14 14 90 0 1 14 14 V55 h-108 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M260 55 v16 a14 14 90 0 1 -14 14 H166 a14 14 90 0 1 -14 -14 V55 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"152\\\" y=\\\"27\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"152\\\" y1=\\\"55\\\" x2=\\\"260\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"159\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">RHONCUS</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"48\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"267\\\" y=\\\"48\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"211\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SODALES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"66\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"350\\\" y1=\\\"56\\\" x2=\\\"66\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"206\\\" y1=\\\"174\\\" x2=\\\"66\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M103 145 a14 14 90 0 1 14 14 V173 h-102 V159 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M117 173 v16 a14 14 90 0 1 -14 14 H29 a14 14 90 0 1 -14 -14 V173 H102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"15\\\" y=\\\"145\\\" width=\\\"102\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"15\\\" y1=\\\"173\\\" x2=\\\"117\\\" y2=\\\"173\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"23\\\" y=\\\"166.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SODALES</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"267\\\" y=\\\"75.77\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"123\\\" y=\\\"190\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association QUIS_ENIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"56\\\" x2=\\\"350\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"350\\\" y1=\\\"56\\\" x2=\\\"350\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"206\\\" y1=\\\"174\\\" x2=\\\"350\\\" y2=\\\"174\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M392 145 a14 14 90 0 1 14 14 V173 h-112 V159 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M406 173 v16 a14 14 90 0 1 -14 14 H308 a14 14 90 0 1 -14 -14 V173 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"294\\\" y=\\\"145\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"294\\\" y1=\\\"173\\\" x2=\\\"406\\\" y2=\\\"173\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"301\\\" y=\\\"166.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">QUIS ENIM</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"74.94\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"355\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"270\\\" y=\\\"190\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DIGNISSIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"123\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIGNISSIM</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nec sem</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"69\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nunc</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vulputate</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity IMPERDIET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"291\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"291\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"291\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"291\\\" y1=\\\"39\\\" x2=\\\"409\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"300\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">IMPERDIET</text>\\n\",\n       \"\\t<text x=\\\"299\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">a praesent</text>\\n\",\n       \"\\t<line x1=\\\"299\\\" y1=\\\"59\\\" x2=\\\"364\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"299\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nibh</text>\\n\",\n       \"\\t<text x=\\\"299\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">semper</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TINCIDUNT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"147\\\" y=\\\"127\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"147\\\" y=\\\"157\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"147\\\" y=\\\"127\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"147\\\" y1=\\\"157\\\" x2=\\\"265\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"155\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TINCIDUNT</text>\\n\",\n       \"\\t<text x=\\\"155\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">faucibus</text>\\n\",\n       \"\\t<line x1=\\\"155\\\" y1=\\\"177\\\" x2=\\\"205\\\" y2=\\\"177\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"155\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">orci</text>\\n\",\n       \"\\t<text x=\\\"155\\\" y=\\\"208\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cursus</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox.mcd\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"%%mocodo --seed=1\\n\",\n      \"DIGNISSIM: nec sem, nunc, vulputate\\n\",\n      \"RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n      \"IMPERDIET: a praesent, nibh, semper\\n\",\n      \"\\n\",\n      \"SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n      \"TINCIDUNT: faucibus, orci, cursus\\n\",\n      \"QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --seed=1 -t arrange:algo=ga\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'amélioration ne saute pas forcément aux yeux, mais il n'y a plus que trois croisements au lieu de neuf. Ce plongement constitue en tout cas un bon point de départ pour un réarrangement manuel. Il ne reste en effet plus qu'à insérer quelques boîtes invisibles:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 124,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"484\\\" height=\\\"336\\\" viewBox=\\\"0 0 484 336\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"484\\\" height=\\\"336\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RHONCUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"109\\\" x2=\\\"240\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"416\\\" y1=\\\"109\\\" x2=\\\"240\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"240\\\" y1=\\\"280\\\" x2=\\\"240\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M280 9 a14 14 90 0 1 14 14 V37 h-108 V23 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M294 37 v16 a14 14 90 0 1 -14 14 H200 a14 14 90 0 1 -14 -14 V37 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"186\\\" y=\\\"9\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"186\\\" y1=\\\"37\\\" x2=\\\"294\\\" y2=\\\"37\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"193\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">RHONCUS</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"98.55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"333\\\" y=\\\"98.04\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"245\\\" y=\\\"225\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SODALES -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"109\\\" x2=\\\"66\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"416\\\" y1=\\\"109\\\" x2=\\\"66\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"240\\\" y1=\\\"280\\\" x2=\\\"66\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M103 180 a14 14 90 0 1 14 14 V208 h-102 V194 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M117 208 v16 a14 14 90 0 1 -14 14 H29 a14 14 90 0 1 -14 -14 V208 H102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"15\\\" y=\\\"180\\\" width=\\\"102\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"15\\\" y1=\\\"208\\\" x2=\\\"117\\\" y2=\\\"208\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"23\\\" y=\\\"201.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SODALES</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"333\\\" y=\\\"120.07\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"157\\\" y=\\\"268.73\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association QUIS_ENIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"109\\\" x2=\\\"416\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"416\\\" y1=\\\"109\\\" x2=\\\"416\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"240\\\" y1=\\\"280\\\" x2=\\\"416\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M458 180 a14 14 90 0 1 14 14 V208 h-112 V194 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M472 208 v16 a14 14 90 0 1 -14 14 H374 a14 14 90 0 1 -14 -14 V208 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"180\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"360\\\" y1=\\\"208\\\" x2=\\\"472\\\" y2=\\\"208\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"367\\\" y=\\\"201.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">QUIS ENIM</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"119.5\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"421\\\" y=\\\"172\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"304\\\" y=\\\"269.04\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DIGNISSIM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"62\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"92\\\" width=\\\"114\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"62\\\" width=\\\"114\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"92\\\" x2=\\\"123\\\" y2=\\\"92\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"83.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DIGNISSIM</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"109.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nec sem</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"112\\\" x2=\\\"69\\\" y2=\\\"112\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"126.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nunc</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"143\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">vulputate</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity IMPERDIET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"357\\\" y=\\\"62\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"357\\\" y=\\\"92\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"357\\\" y=\\\"62\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"357\\\" y1=\\\"92\\\" x2=\\\"475\\\" y2=\\\"92\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"366\\\" y=\\\"83.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">IMPERDIET</text>\\n\",\n       \"\\t<text x=\\\"365\\\" y=\\\"109.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">a praesent</text>\\n\",\n       \"\\t<line x1=\\\"365\\\" y1=\\\"112\\\" x2=\\\"430\\\" y2=\\\"112\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"365\\\" y=\\\"126.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nibh</text>\\n\",\n       \"\\t<text x=\\\"365\\\" y=\\\"143\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">semper</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TINCIDUNT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"181\\\" y=\\\"233\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"181\\\" y=\\\"263\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"181\\\" y=\\\"233\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"181\\\" y1=\\\"263\\\" x2=\\\"299\\\" y2=\\\"263\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"254.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">TINCIDUNT</text>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"280.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">faucibus</text>\\n\",\n       \"\\t<line x1=\\\"189\\\" y1=\\\"283\\\" x2=\\\"239\\\" y2=\\\"283\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"297.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">orci</text>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"314\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">cursus</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n    \"\\n\",\n    \"DIGNISSIM: nec sem, nunc, vulputate\\n\",\n    \":::\\n\",\n    \"IMPERDIET: a praesent, nibh, semper\\n\",\n    \"\\n\",\n    \"SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n    \":::\\n\",\n    \"QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\\n\",\n    \"\\n\",\n    \"TINCIDUNT: faucibus, orci, cursus\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme génétique :\\n\",\n    \"\\n\",\n    \"- `population_size` : nombre d'individus à faire évoluer (défaut: `1000`).\\n\",\n    \"- `crossover_rate` : taux de croisement, entre 0 et 1 (défaut: `0.9`).\\n\",\n    \"- `mutation_rate` : taux de mutation, entre 0 et 1 (défaut: `0.06`).\\n\",\n    \"- `sample_size` : taille de l'échantillon pour les tournois (défaut: `7`).\\n\",\n    \"- `max_generations` : nombre maximal de générations (défaut: `300`).\\n\",\n    \"- `plateau` : nombre maximal de générations consécutives sans amélioration (défaut: `30`).\\n\",\n    \"\\n\",\n    \"Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Amélioration du plongement\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Une entité liée à de nombreuses associations peut limiter ou même empêcher les possibilités de réarrangement sans croisements.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Par duplication d'entités réduites à leur identifiant\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Lorsque cette entité est indépendante et réduite à son identifiant, elle est vouée à disparaître lors du passage au relationnel. Il n'y a donc aucun inconvénient à en créer plusieurs, et cela peut avoir l'avantage de faciliter (ou même de rendre possible) l'obtention d'une bonne mise en page.\\n\",\n    \"\\n\",\n    \"Prenons comme exemple un MCD extrait d'une [étude de François de Sainte Marie](https://fsmrel.developpez.com/basesrelationnelles/ullman-cthrsg/), et présenté comme suit :\\n\",\n    \"\\n\",\n    \"![](examples/ullman_cthrsg_mcd_sans_cif_80.png)\\n\",\n    \"\\n\",\n    \"Le graphe sous-jacent étant non planaire, des croisements sont inévitables (ici entre certaines pattes des associations SHR, CT et THR). Cependant, cette non-planarité résulte elle-même de la mise en jeu d'une même entité Période dans quatre associations triples. La monnayer en quatre entités Période numérotées augmente l'ordre du graphe, mais le rend planaire, le tout sans impact sur le schéma relationnel :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 125,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"504\\\" height=\\\"461\\\" viewBox=\\\"0 0 504 461\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"504\\\" height=\\\"461\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association SHR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"451\\\" y1=\\\"47\\\" x2=\\\"351\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"351\\\" y1=\\\"230\\\" x2=\\\"351\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"47\\\" x2=\\\"351\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M364 18 a14 14 90 0 1 14 14 V46 h-54 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M378 46 v16 a14 14 90 0 1 -14 14 H338 a14 14 90 0 1 -14 -14 V46 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"18\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"324\\\" y1=\\\"46\\\" x2=\\\"378\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"331\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SHR</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"383\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"356\\\" y=\\\"184\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"114\\\" y=\\\"39\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CSG -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"138\\\" x2=\\\"157\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"230\\\" x2=\\\"157\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"47\\\" x2=\\\"157\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M170 109 a14 14 90 0 1 14 14 V137 h-54 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M184 137 v16 a14 14 90 0 1 -14 14 H144 a14 14 90 0 1 -14 -14 V137 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"130\\\" y=\\\"109\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"130\\\" y1=\\\"137\\\" x2=\\\"184\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"138\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CSG</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"192\\\" y=\\\"154\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"162\\\" y=\\\"184\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"82.62\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CHS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"322\\\" x2=\\\"59\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"230\\\" x2=\\\"59\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"47\\\" x2=\\\"59\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M72 201 a14 14 90 0 1 14 14 V229 h-54 V215 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M86 229 v16 a14 14 90 0 1 -14 14 H46 a14 14 90 0 1 -14 -14 V229 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"32\\\" y=\\\"201\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"32\\\" y1=\\\"229\\\" x2=\\\"86\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"39\\\" y=\\\"222.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CHS</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"64\\\" y=\\\"284\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"91\\\" y=\\\"246\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CHR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"322\\\" x2=\\\"256\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"351\\\" y1=\\\"230\\\" x2=\\\"256\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"230\\\" x2=\\\"256\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M270 201 a14 14 90 0 1 14 14 V229 h-56 V215 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M284 229 v16 a14 14 90 0 1 -14 14 H242 a14 14 90 0 1 -14 -14 V229 H56\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"228\\\" y=\\\"201\\\" width=\\\"56\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"228\\\" y1=\\\"229\\\" x2=\\\"284\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"236\\\" y=\\\"222.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CHR</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"284\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"289\\\" y=\\\"246\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"204\\\" y=\\\"246\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"230\\\" x2=\\\"157\\\" y2=\\\"322\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"414\\\" x2=\\\"157\\\" y2=\\\"322\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M163 293 a14 14 90 0 1 14 14 V321 h-40 V307 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M177 321 v16 a14 14 90 0 1 -14 14 H151 a14 14 90 0 1 -14 -14 V321 H40\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"137\\\" y=\\\"293\\\" width=\\\"40\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"137\\\" y1=\\\"321\\\" x2=\\\"177\\\" y2=\\\"321\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"314.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CT</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"162\\\" y=\\\"284\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"162\\\" y=\\\"368\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association THR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"451\\\" y1=\\\"414\\\" x2=\\\"351\\\" y2=\\\"414\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"351\\\" y1=\\\"230\\\" x2=\\\"351\\\" y2=\\\"414\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"157\\\" y1=\\\"414\\\" x2=\\\"351\\\" y2=\\\"414\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M364 385 a14 14 90 0 1 14 14 V413 h-54 V399 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M378 413 v16 a14 14 90 0 1 -14 14 H338 a14 14 90 0 1 -14 -14 V413 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"324\\\" y=\\\"385\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"324\\\" y1=\\\"413\\\" x2=\\\"378\\\" y2=\\\"413\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"332\\\" y=\\\"406.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THR</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"383\\\" y=\\\"430\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"356\\\" y=\\\"284\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"224\\\" y=\\\"430\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETUDIANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"109\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étudiant</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. étudiant</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"87\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom étudiant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERIODE3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"17\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"47\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"17\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"407\\\" y1=\\\"47\\\" x2=\\\"495\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"415\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Période</text>\\n\",\n       \"\\t<text x=\\\"415\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"67\\\" x2=\\\"452\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity NIVEAU -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"216\\\" y=\\\"108\\\" width=\\\"80\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"216\\\" y=\\\"138\\\" width=\\\"80\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"216\\\" y=\\\"108\\\" width=\\\"80\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"216\\\" y1=\\\"138\\\" x2=\\\"296\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"129.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Niveau</text>\\n\",\n       \"\\t<text x=\\\"224\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">niveau</text>\\n\",\n       \"\\t<line x1=\\\"224\\\" y1=\\\"158\\\" x2=\\\"264\\\" y2=\\\"158\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COURS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"115\\\" y=\\\"192\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"115\\\" y=\\\"222\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"115\\\" y=\\\"192\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"115\\\" y1=\\\"222\\\" x2=\\\"199\\\" y2=\\\"222\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"128\\\" y=\\\"213.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Cours</text>\\n\",\n       \"\\t<text x=\\\"123\\\" y=\\\"239.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. cours</text>\\n\",\n       \"\\t<line x1=\\\"123\\\" y1=\\\"242\\\" x2=\\\"177\\\" y2=\\\"242\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"123\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom cours</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SALLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"313\\\" y=\\\"192\\\" width=\\\"76\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"313\\\" y=\\\"222\\\" width=\\\"76\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"313\\\" y=\\\"192\\\" width=\\\"76\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"313\\\" y1=\\\"222\\\" x2=\\\"389\\\" y2=\\\"222\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"325\\\" y=\\\"213.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Salle</text>\\n\",\n       \"\\t<text x=\\\"321\\\" y=\\\"239.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. salle</text>\\n\",\n       \"\\t<line x1=\\\"321\\\" y1=\\\"242\\\" x2=\\\"367\\\" y2=\\\"242\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"321\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom salle</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERIODE2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"15\\\" y=\\\"292\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"15\\\" y=\\\"322\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"15\\\" y=\\\"292\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"15\\\" y1=\\\"322\\\" x2=\\\"103\\\" y2=\\\"322\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"23\\\" y=\\\"313.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Période</text>\\n\",\n       \"\\t<text x=\\\"23\\\" y=\\\"339.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t<line x1=\\\"23\\\" y1=\\\"342\\\" x2=\\\"60\\\" y2=\\\"342\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERIODE4 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"212\\\" y=\\\"292\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"212\\\" y=\\\"322\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"212\\\" y=\\\"292\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"212\\\" y1=\\\"322\\\" x2=\\\"300\\\" y2=\\\"322\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"220\\\" y=\\\"313.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Période</text>\\n\",\n       \"\\t<text x=\\\"220\\\" y=\\\"339.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t<line x1=\\\"220\\\" y1=\\\"342\\\" x2=\\\"257\\\" y2=\\\"342\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROFESSEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"95\\\" y=\\\"376\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"95\\\" y=\\\"406\\\" width=\\\"124\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"95\\\" y=\\\"376\\\" width=\\\"124\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"95\\\" y1=\\\"406\\\" x2=\\\"219\\\" y2=\\\"406\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"397.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Professeur</text>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"423.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. professeur</text>\\n\",\n       \"\\t<line x1=\\\"103\\\" y1=\\\"426\\\" x2=\\\"189\\\" y2=\\\"426\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"103\\\" y=\\\"440.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom professeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERIODE1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"384\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"414\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"407\\\" y=\\\"384\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"407\\\" y1=\\\"414\\\" x2=\\\"495\\\" y2=\\\"414\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"415\\\" y=\\\"405.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Période</text>\\n\",\n       \"\\t<text x=\\\"415\\\" y=\\\"431.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t<line x1=\\\"415\\\" y1=\\\"434\\\" x2=\\\"452\\\" y2=\\\"434\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **CHR** (<u>heure</u>, <u>_#id. salle_</u>, <u>_#id. cours_</u>)\\n\",\n       \"- **CHS** (<u>heure</u>, <u>_#id. cours_</u>, <u>_#id. étudiant_</u>)\\n\",\n       \"- **Cours** (<u>id. cours</u>, nom cours, _#id. professeur_)\\n\",\n       \"- **CSG** (<u>niveau</u>, <u>_#id. cours_</u>, <u>_#id. étudiant_</u>)\\n\",\n       \"- **Étudiant** (<u>id. étudiant</u>, nom étudiant)\\n\",\n       \"- **Professeur** (<u>id. professeur</u>, nom professeur)\\n\",\n       \"- **Salle** (<u>id. salle</u>, nom salle)\\n\",\n       \"- **SHR** (<u>heure</u>, <u>_#id. salle_</u>, <u>_#id. étudiant_</u>)\\n\",\n       \"- **THR** (<u>heure</u>, <u>_#id. salle_</u>, <u>_#id. professeur_</u>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Étudiant: id. étudiant, nom étudiant\\n\",\n    \":\\n\",\n    \":\\n\",\n    \"SHR, 0N Période3, 0N Salle, 0N Étudiant\\n\",\n    \"Période3: heure\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"CSG, 0N Niveau, 1N Cours, 1N Étudiant\\n\",\n    \"Niveau: niveau\\n\",\n    \":\\n\",\n    \"\\n\",\n    \"CHS, 0N Période2, 0N Cours, 0N Étudiant\\n\",\n    \"Cours: id. cours, nom cours\\n\",\n    \"CHR, 0N Période4, 0N Salle, 0N Cours\\n\",\n    \"Salle: id. salle, nom salle\\n\",\n    \"\\n\",\n    \"Période2: heure\\n\",\n    \"CT, 11 Cours, 1N Professeur\\n\",\n    \"Période4: heure\\n\",\n    \":\\n\",\n    \":\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Professeur: id. professeur, nom professeur\\n\",\n    \":\\n\",\n    \"THR, 0N Période1, 0N Salle, 0N Professeur\\n\",\n    \"Période1: heure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ce genre de problème (et sa solution) se présente typiquement lorsqu'une entité DATE réduite à un identifiant _date_ est associée à un grand nombre d'entités n'ayant rien à voir entre elles. \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Par suppression de ces mêmes entités\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Inversement, toujours étant donné que ce type d'entité est destiné à disparaître lors du passage au relationnel, on peut décider de les supprimer par anticipation. Pour cela, il faut accepter que les associations puissent être porteuses d'identifiants (ce qui n'est pas prévu par Merise). Cela permet d'obtenir un schéma conceptuel beaucoup plus lisible, toujours sans impact sur le schéma relationnel :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 126,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"449\\\" height=\\\"294\\\" viewBox=\\\"0 0 449 294\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"449\\\" height=\\\"294\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association CSG -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"47\\\" x2=\\\"59\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"247\\\" x2=\\\"59\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M72 18 a14 14 90 0 1 14 14 V46 h-54 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M86 46 v16 a14 14 90 0 1 -14 14 H46 a14 14 90 0 1 -14 -14 V46 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"32\\\" y=\\\"18\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"32\\\" y1=\\\"46\\\" x2=\\\"86\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"40\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CSG</text>\\n\",\n       \"\\t\\t<text x=\\\"39\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">niveau</text>\\n\",\n       \"\\t\\t<line x1=\\\"39\\\" y1=\\\"67\\\" x2=\\\"79\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"193\\\" y=\\\"39\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"47\\\" x2=\\\"378\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"147\\\" x2=\\\"378\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M384 18 a14 14 90 0 1 14 14 V46 h-40 V32 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M398 46 v16 a14 14 90 0 1 -14 14 H372 a14 14 90 0 1 -14 -14 V46 H40\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"358\\\" y=\\\"18\\\" width=\\\"40\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"358\\\" y1=\\\"46\\\" x2=\\\"398\\\" y2=\\\"46\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"366\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CT</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"306\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"383\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CHS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"47\\\" x2=\\\"165\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"247\\\" x2=\\\"165\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M178 118 a14 14 90 0 1 14 14 V146 h-54 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M192 146 v16 a14 14 90 0 1 -14 14 H152 a14 14 90 0 1 -14 -14 V146 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"118\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"138\\\" y1=\\\"146\\\" x2=\\\"192\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CHS</text>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t\\t<line x1=\\\"145\\\" y1=\\\"167\\\" x2=\\\"182\\\" y2=\\\"167\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"221.52\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"82.06\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association CHR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"247\\\" x2=\\\"259\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"47\\\" x2=\\\"259\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M273 118 a14 14 90 0 1 14 14 V146 h-56 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M287 146 v16 a14 14 90 0 1 -14 14 H245 a14 14 90 0 1 -14 -14 V146 H56\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"231\\\" y=\\\"118\\\" width=\\\"56\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"231\\\" y1=\\\"146\\\" x2=\\\"287\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"239\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CHR</text>\\n\",\n       \"\\t\\t<text x=\\\"238\\\" y=\\\"164.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t\\t<line x1=\\\"238\\\" y1=\\\"167\\\" x2=\\\"275\\\" y2=\\\"167\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SHR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"247\\\" x2=\\\"165\\\" y2=\\\"247\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"247\\\" x2=\\\"165\\\" y2=\\\"247\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M178 218 a14 14 90 0 1 14 14 V246 h-54 V232 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M192 246 v16 a14 14 90 0 1 -14 14 H152 a14 14 90 0 1 -14 -14 V246 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"218\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"138\\\" y1=\\\"246\\\" x2=\\\"192\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"239.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">SHR</text>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t\\t<line x1=\\\"145\\\" y1=\\\"267\\\" x2=\\\"182\\\" y2=\\\"267\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"197\\\" y=\\\"263\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"114\\\" y=\\\"263\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association THR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"247\\\" x2=\\\"378\\\" y2=\\\"247\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"147\\\" x2=\\\"378\\\" y2=\\\"247\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M391 218 a14 14 90 0 1 14 14 V246 h-54 V232 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M405 246 v16 a14 14 90 0 1 -14 14 H365 a14 14 90 0 1 -14 -14 V246 H54\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"351\\\" y=\\\"218\\\" width=\\\"54\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"351\\\" y1=\\\"246\\\" x2=\\\"405\\\" y2=\\\"246\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"359\\\" y=\\\"239.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">THR</text>\\n\",\n       \"\\t\\t<text x=\\\"358\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure</text>\\n\",\n       \"\\t\\t<line x1=\\\"358\\\" y1=\\\"267\\\" x2=\\\"395\\\" y2=\\\"267\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"302\\\" y=\\\"263\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"383\\\" y=\\\"201\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COURS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"217\\\" y1=\\\"39\\\" x2=\\\"301\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"230\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Cours</text>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. cours</text>\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"59\\\" x2=\\\"279\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom cours</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROFESSEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"316\\\" y=\\\"109\\\" width=\\\"124\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"316\\\" y=\\\"139\\\" width=\\\"124\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"316\\\" y=\\\"109\\\" width=\\\"124\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"316\\\" y1=\\\"139\\\" x2=\\\"440\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"324\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Professeur</text>\\n\",\n       \"\\t<text x=\\\"324\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. professeur</text>\\n\",\n       \"\\t<line x1=\\\"324\\\" y1=\\\"159\\\" x2=\\\"410\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"324\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom professeur</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETUDIANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"209\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"239\\\" width=\\\"100\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"209\\\" width=\\\"100\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"239\\\" x2=\\\"109\\\" y2=\\\"239\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étudiant</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. étudiant</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"259\\\" x2=\\\"87\\\" y2=\\\"259\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"273.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom étudiant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SALLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"221\\\" y=\\\"209\\\" width=\\\"76\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"221\\\" y=\\\"239\\\" width=\\\"76\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"221\\\" y=\\\"209\\\" width=\\\"76\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"221\\\" y1=\\\"239\\\" x2=\\\"297\\\" y2=\\\"239\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"233\\\" y=\\\"230.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Salle</text>\\n\",\n       \"\\t<text x=\\\"229\\\" y=\\\"256.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. salle</text>\\n\",\n       \"\\t<line x1=\\\"229\\\" y1=\\\"259\\\" x2=\\\"275\\\" y2=\\\"259\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"229\\\" y=\\\"273.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom salle</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **CHR** (<u>_#id. salle_</u>, <u>_#id. cours_</u>, <u>heure</u>)\\n\",\n       \"- **CHS** (<u>_#id. cours_</u>, <u>_#id. étudiant_</u>, <u>heure</u>)\\n\",\n       \"- **Cours** (<u>id. cours</u>, nom cours, _#id. professeur_)\\n\",\n       \"- **CSG** (<u>_#id. cours_</u>, <u>_#id. étudiant_</u>, <u>niveau</u>)\\n\",\n       \"- **Étudiant** (<u>id. étudiant</u>, nom étudiant)\\n\",\n       \"- **Professeur** (<u>id. professeur</u>, nom professeur)\\n\",\n       \"- **Salle** (<u>id. salle</u>, nom salle)\\n\",\n       \"- **SHR** (<u>_#id. salle_</u>, <u>_#id. étudiant_</u>, <u>heure</u>)\\n\",\n       \"- **THR** (<u>_#id. salle_</u>, <u>_#id. professeur_</u>, <u>heure</u>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"CSG, 1N Cours, 1N Étudiant: _niveau\\n\",\n    \":\\n\",\n    \"Cours: id. cours, nom cours\\n\",\n    \"CT, 11 Cours, 1N Professeur\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"CHS, 0N Cours, 0N Étudiant: _heure\\n\",\n    \"CHR, 0N Salle, 0N Cours: _heure\\n\",\n    \"Professeur: id. professeur, nom professeur\\n\",\n    \"    \\n\",\n    \"Étudiant: id. étudiant, nom étudiant\\n\",\n    \"SHR, 0N Salle, 0N Étudiant: _heure\\n\",\n    \"Salle: id. salle, nom salle\\n\",\n    \"THR, 0N Salle, 0N Professeur: _heure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notez qu'avec cette technique, les cardinalités minimales des pattes distinguées par les entités supprimées sont perdues dès le niveau conceptuel (sachant qu'elles l'auraient été de toute façon lors du passage au relationnel).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme la notion d'identifiant explicite d'association enfreint le standard Merise, et risque de semer la discorde entre professeurs et étudiants, elle est par défaut désactivée sous Mocodo online. En ligne de commande, elle est interdite à la demande :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 127,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Mocodo Err.52 - L'association « CSG » ne peut pas avoir d'identifiant.\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --no_assoc_ids\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Ajustement de l'aspect de certains éléments\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Format des cardinalités\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Par défaut, les cardinalités sont séparées par une virgule, et celles des entités faibles soulignées, mais cela peut être changé :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 128,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"412\\\" height=\\\"112\\\" viewBox=\\\"0 0 412 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"412\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"61\\\" y1=\\\"56\\\" x2=\\\"191\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"336\\\" y1=\\\"56\\\" x2=\\\"191\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"191\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"178\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"118\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">(1/N)</text>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">(1/1)(R)</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"113\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ŒUVRE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Cote œuvre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"94\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date parution</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"39\\\" width=\\\"134\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"269\\\" y1=\\\"39\\\" x2=\\\"403\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">EXEMPLAIRE</text>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. exemplaire</text>\\n\",\n       \"\\t<line x1=\\\"277\\\" y1=\\\"59\\\" x2=\\\"385\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">État du livre</text>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date d’achat</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo  --card_format=({min_card}/{max_card}) --strengthen_card=(1/1)(R)\\n\",\n    \"ŒUVRE: Cote œuvre, Titre, Date parution\\n\",\n    \"DF, 1N ŒUVRE, _11 EXEMPLAIRE\\n\",\n    \"EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Format des clés étrangères\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La mise en forme des clés étrangères affichées dans le diagramme relationnel peut être paramétrée, par exemple pour enlever le préfixe par défaut (`#`) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 129,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"ccp_mld.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0ZWQgYnkgTW9jb2RvIDQuMy4yIC0tPgo8c3ZnIHdpZHRoPSI2NzAiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNjcwIDEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjY3MCIgaGVpZ2h0PSIxMjgiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8IS0tIEVudGl0eSBDTElFTlQgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzgiIHk9IjkiIHdpZHRoPSI3OCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iMzkiIHdpZHRoPSI3OCIgaGVpZ2h0PSI4MCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzOCIgeT0iOSIgd2lkdGg9Ijc4IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIzOCIgeTE9IjM5IiB4Mj0iMTE2IiB5Mj0iMzkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjQ3IiB5PSIzMC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkNsaWVudDwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI1Ni4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+Cgk8bGluZSB4MT0iNDYiIHkxPSI1OSIgeDI9IjEwOCIgeTI9IjU5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iNDYiIHk9IjczLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk5vbTwvdGV4dD4KCTx0ZXh0IHg9IjQ2IiB5PSI5MC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5QcsOpbm9tPC90ZXh0PgoJPHRleHQgeD0iNDYiIHk9IjEwNyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+QWRyZXNzZTwvdGV4dD4KPC9nPgoKPCEtLSBFbnRpdHkgQ09NTUFOREUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjMwIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjE3NCIgeT0iMzkiIHdpZHRoPSIxMjQiIGhlaWdodD0iODAiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iMTc0IiB5PSI5IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjExMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgb3BhY2l0eT0iMSIvPgoJCTxsaW5lIHgxPSIxNzQiIHkxPSIzOSIgeDI9IjI5OCIgeTI9IjM5IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cgk8L2c+Cgk8dGV4dCB4PSIxODkiIHk9IjMwLjMiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJDb3BwZXJwbGF0ZSIgZm9udC1zaXplPSIxOCI+Q29tbWFuZGU8L3RleHQ+Cgk8dGV4dCB4PSIxODIiIHk9IjU2LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMTgyIiB5MT0iNTkiIHgyPSIyOTAiIHkyPSI1OSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjE4MiIgeT0iNzMuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+RGF0ZTwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iOTAuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+TW9udGFudDwvdGV4dD4KCTx0ZXh0IHg9IjE4MiIgeT0iMTA3IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBjbGllbnQ8L3RleHQ+CjwvZz4KCjwhLS0gRW50aXR5IElOQ0xVUkUgLS0+CjxnPgoJPGc+CgkJPHJlY3QgeD0iMzU2IiB5PSIxNyIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSIzNTYiIHk9IjQ3IiB3aWR0aD0iMTI0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMCIgb3BhY2l0eT0iMSIvPgoJCTxyZWN0IHg9IjM1NiIgeT0iMTciIHdpZHRoPSIxMjQiIGhlaWdodD0iOTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG9wYWNpdHk9IjEiLz4KCQk8bGluZSB4MT0iMzU2IiB5MT0iNDciIHgyPSI0ODAiIHkyPSI0NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIvPgoJPC9nPgoJPHRleHQgeD0iMzgyIiB5PSIzOC4zIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iQ29wcGVycGxhdGUiIGZvbnQtc2l6ZT0iMTgiPkluY2x1cmU8L3RleHQ+Cgk8dGV4dCB4PSIzNjQiIHk9IjY0LjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPk51bS4gY29tbWFuZGU8L3RleHQ+Cgk8bGluZSB4MT0iMzY0IiB5MT0iNjciIHgyPSI0NzIiIHkyPSI2NyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KCTx0ZXh0IHg9IjM2NCIgeT0iODEuMSIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UsOpZi4gcHJvZHVpdDwvdGV4dD4KCTxsaW5lIHgxPSIzNjQiIHkxPSI4NCIgeDI9IjQzOSIgeTI9Ijg0IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMSIvPgoJPHRleHQgeD0iMzY0IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UXVhbnRpdMOpPC90ZXh0Pgo8L2c+Cgo8IS0tIEVudGl0eSBQUk9EVUlUIC0tPgo8Zz4KCTxnPgoJCTxyZWN0IHg9IjUzOCIgeT0iMTciIHdpZHRoPSI5NCIgaGVpZ2h0PSIzMCIgZmlsbD0iI0ZGRkZGRiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjAiIG9wYWNpdHk9IjEiLz4KCQk8cmVjdCB4PSI1MzgiIHk9IjQ3IiB3aWR0aD0iOTQiIGhlaWdodD0iNjQiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBvcGFjaXR5PSIxIi8+CgkJPHJlY3QgeD0iNTM4IiB5PSIxNyIgd2lkdGg9Ijk0IiBoZWlnaHQ9Ijk0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBvcGFjaXR5PSIxIi8+CgkJPGxpbmUgeDE9IjUzOCIgeTE9IjQ3IiB4Mj0iNjMyIiB5Mj0iNDciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KCTwvZz4KCTx0ZXh0IHg9IjU0OSIgeT0iMzguMyIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkNvcHBlcnBsYXRlIiBmb250LXNpemU9IjE4Ij5Qcm9kdWl0PC90ZXh0PgoJPHRleHQgeD0iNTQ2IiB5PSI2NC4xIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iR2lsbCBTYW5zIiBmb250LXNpemU9IjE1Ij5Sw6lmLiBwcm9kdWl0PC90ZXh0PgoJPGxpbmUgeDE9IjU0NiIgeTE9IjY3IiB4Mj0iNjIxIiB5Mj0iNjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cgk8dGV4dCB4PSI1NDYiIHk9IjgxLjEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJHaWxsIFNhbnMiIGZvbnQtc2l6ZT0iMTUiPkxpYmVsbMOpPC90ZXh0PgoJPHRleHQgeD0iNTQ2IiB5PSI5OCIgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9IkdpbGwgU2FucyIgZm9udC1zaXplPSIxNSI+UHJpeCB1bml0YWlyZTwvdGV4dD4KPC9nPgoKPCEtLSBMaW5rIGZyb20gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDT01NQU5ERSkgdG8gJnF1b3Q7UsOpZi4gY2xpZW50JnF1b3Q7IChDTElFTlQpIC0tPgo8cGF0aCBkPSJNMTc0IDEwNC41IEMxNDUgNzkgMTU0LjY3IDUzLjUgMTE2IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMTE2IDUzLjUgMTI4IDQ3LjUgMTI0IDUzLjUgMTI4IDU5LjUiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIxNzQiIGN5PSIxMDQuNSIgcj0iMS41IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS41IiBmaWxsPSIjMDAwMDAwIi8+Cgo8IS0tIExpbmsgZnJvbSAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChJTkNMVVJFKSB0byAmcXVvdDtOdW0uIGNvbW1hbmRlJnF1b3Q7IChDT01NQU5ERSkgLS0+CjxwYXRoIGQ9Ik0zNTYgNjEuNSBDMzI3IDU3LjUgMzM2LjY3IDUzLjUgMjk4IDUzLjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+Cjxwb2x5Z29uIHBvaW50cz0iMjk4IDUzLjUgMzEwIDQ3LjUgMzA2IDUzLjUgMzEwIDU5LjUiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMCIvPgo8Y2lyY2xlIGN4PSIzNTYiIGN5PSI2MS41IiByPSIxLjUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9IiMwMDAwMDAiLz4KCjwhLS0gTGluayBmcm9tICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKElOQ0xVUkUpIHRvICZxdW90O1LDqWYuIHByb2R1aXQmcXVvdDsgKFBST0RVSVQpIC0tPgo8cGF0aCBkPSJNNDgwIDc4LjUgQzUwOSA3MCA0OTkuMzMgNjEuNSA1MzggNjEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEiLz4KPHBvbHlnb24gcG9pbnRzPSI1MzggNjEuNSA1MjYgNjcuNSA1MzAgNjEuNSA1MjYgNTUuNSIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+CjxjaXJjbGUgY3g9IjQ4MCIgY3k9Ijc4LjUiIHI9IjEuNSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgZmlsbD0iIzAwMDAwMCIvPgo8L3N2Zz4=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i ccp -t diagram --fk_format={label}\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Symbole de dépendance fonctionnelle\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il est possible d'activer l'encerclement d'un autre sigle que DF. C'est ce sigle qui devra alors apparaître en entrée, par exemple:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 130,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"588\\\" height=\\\"128\\\" viewBox=\\\"0 0 588 128\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"588\\\" height=\\\"128\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association CIF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"51\\\" y1=\\\"64\\\" x2=\\\"145\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"260\\\" y1=\\\"64\\\" x2=\\\"145\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"145\\\" cy=\\\"64\\\" r=\\\"23\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"129\\\" y=\\\"65.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"174\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association INCLURE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"260\\\" y1=\\\"64\\\" x2=\\\"401\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"529\\\" y1=\\\"64\\\" x2=\\\"401\\\" y2=\\\"64\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M436 35 a14 14 90 0 1 14 14 V63 h-98 V49 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M450 63 v16 a14 14 90 0 1 -14 14 H366 a14 14 90 0 1 -14 -14 V63 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"352\\\" y=\\\"35\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"352\\\" y1=\\\"63\\\" x2=\\\"450\\\" y2=\\\"63\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"360\\\" y=\\\"56.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">INCLURE</text>\\n\",\n       \"\\t\\t<text x=\\\"359\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"328\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"455\\\" y=\\\"80\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"80\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"47\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"17\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"197\\\" y1=\\\"47\\\" x2=\\\"323\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"206\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Num. commande</text>\\n\",\n       \"\\t<line x1=\\\"205\\\" y1=\\\"67\\\" x2=\\\"313\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"47\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"479\\\" y=\\\"17\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"479\\\" y1=\\\"47\\\" x2=\\\"579\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"488\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"487\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"487\\\" y1=\\\"67\\\" x2=\\\"562\\\" y2=\\\"67\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"487\\\" y=\\\"81.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Libellé</text>\\n\",\n       \"\\t<text x=\\\"487\\\" y=\\\"98\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --df CIF\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse\\n\",\n    \"CIF, 0N CLIENT, 11 COMMANDE\\n\",\n    \"COMMANDE: Num. commande, Date, Montant\\n\",\n    \"INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\\n\",\n    \"PRODUIT: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme le cercle est alors un peu plus grand, on peut vouloir régler (_a priori_ une fois pour toutes) le ratio défini dans l'objet `shapes` du fichier appelé par défaut `sandbox_geo.json`):\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"\\\"df_text_height_ratio\\\" : 1.00,\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Basculement des cardinalités et inflexion des pattes rectilignes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mocodo est capable de détecter certaines configurations de pattes dont les cardinalités présentent un risque élevé de collision. Il procède alors à deux types d'ajustements:\\n\",\n    \"\\n\",\n    \"1. [Issue 25](https://github.com/laowantong/mocodo/issues/25). Les cardinalités d'une patte verticale ou horizontale sont envoyées de l'autre côté de la patte. Par exemple, dans le plongement du MCD précédent, la présence de la patte oblique _BLANDIT-VIVAMUS_ envoie les cardinalités de _VELIT-BLANDIT_ à l'opposé de leur position par défaut (à droite d'une patte verticale ou en bas d'une patte horizontale).\\n\",\n    \"2. [Issue 27](https://github.com/laowantong/mocodo/issues/27). Les pattes obliques sont infléchies de façon à ménager plus d'espace pour afficher deux couples de cardinalités. Ici, l'inflexion de la patte _DF-CONGUE_ permet à ses cardinalités de coexister sans problème avec celles de l'association réflexive.\\n\",\n    \"\\n\",\n    \"Ces ajustements automatiques résolvent les problèmes les plus courants. Toutefois, étant antérieurs au tracé proprement dit, ils peuvent seulement réduire les risques de collision, et non les prévenir totalement. Ils peuvent même en produire d'autres. Ainsi, autour des entités monstrueusement pattues, des collisions qui ne se seraient pas produites par défaut seront parfois observées. L'utilisateur a alors deux possibilités:\\n\",\n    \"\\n\",\n    \"- diminuer la valeur du paramètre `--flex` (par défaut, `0.75`) pour réduire la courbure de l'inflexion automatique, en allant jusqu'à `0` pour la désactiver totalement ;\\n\",\n    \"- modifier à la main les positions des cardinalités en conflit, comme expliqué dans la section suivante.\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Positionnement des contraintes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### En ajoutant des liens invisibles\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La possibilité de rendre un trait invisible peut être exploitée pour « attirer » une contrainte vers telle ou telle boîte existante, soit en la répétant dans la définition de la contrainte, soit en l'y intégrant (fictivement) si elle n'en fait pas partie.\\n\",\n    \"\\n\",\n    \"Par exemple, ci-dessous, répéter l'association Stocker et intégrer l'entité Commande permet de réduire la largeur du MCD sans compromettre sa lisibilité :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 131,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"417\\\" height=\\\"276\\\" viewBox=\\\"0 0 417 276\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"417\\\" height=\\\"276\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint I_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<polygon points=\\\"320 151.28 310.25 160.49 312.34 153.59 306.78 149.0\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"277.86\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"277.86\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"277.86\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"229\\\" x2=\\\"277.86\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"138\\\" x2=\\\"277.86\\\" y2=\\\"164\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"277.86\\\" cy=\\\"164\\\" r=\\\"12\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"275.36\\\" y=\\\"168.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">I</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association LOUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M231 109 a14 14 90 0 1 14 14 V137 h-70 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M245 137 v16 a14 14 90 0 1 -14 14 H189 a14 14 90 0 1 -14 -14 V137 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"175\\\" y=\\\"109\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"175\\\" y1=\\\"137\\\" x2=\\\"245\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"182\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Louer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109.84\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"68.99\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association STOCKER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M394 109 a14 14 90 0 1 14 14 V137 h-88 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M408 137 v16 a14 14 90 0 1 -14 14 H334 a14 14 90 0 1 -14 -14 V137 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"320\\\" y=\\\"109\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"320\\\" y1=\\\"137\\\" x2=\\\"408\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stocker</text>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M248 200 a14 14 90 0 1 14 14 V228 h-104 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M262 228 v16 a14 14 90 0 1 -14 14 H172 a14 14 90 0 1 -14 -14 V228 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"158\\\" y=\\\"200\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"158\\\" y1=\\\"228\\\" x2=\\\"262\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"165\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Composer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPOT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"39\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"39\\\" x2=\\\"407\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"337\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Dépôt</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num dépôt</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"59\\\" x2=\\\"398\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">surface</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"120\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"129\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"121\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ARTICLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"221\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"221\\\" x2=\\\"407\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"330\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Article</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. article</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"241\\\" x2=\\\"393\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \":::\\n\",\n    \"Dépôt: num dépôt, surface\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Louer, 11 Commande, 0N Dépôt\\n\",\n    \":\\n\",\n    \"Stocker, 1N Dépôt, 1N Article: quantité\\n\",\n    \"\\n\",\n    \"Commande: num. commande, date\\n\",\n    \"Composer, 1N Commande, 0N Article\\n\",\n    \":\\n\",\n    \"Article: réf. article, prix\\n\",\n    \"\\n\",\n    \"(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande, Stocker\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### En ajoutant une boîte invisible\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ces réglages restent relativement fragiles. Une façon d'assurer qu'ils survivront à un réarrangement est de faire coïncider le centre d'une contrainte avec celui d'une boîte supplémentaire, que nous appelons ici « Z » :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 132,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"430\\\" height=\\\"276\\\" viewBox=\\\"0 0 430 276\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"430\\\" height=\\\"276\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint I_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<polygon points=\\\"333 138 321 144 325 138 321 132\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"138\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"47\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"138\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"291\\\" cy=\\\"138\\\" r=\\\"12\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"288.5\\\" y=\\\"142.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">I</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association LOUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"47\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M231 109 a14 14 90 0 1 14 14 V137 h-70 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M245 137 v16 a14 14 90 0 1 -14 14 H189 a14 14 90 0 1 -14 -14 V137 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"175\\\" y=\\\"109\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"175\\\" y1=\\\"137\\\" x2=\\\"245\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"182\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Louer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109.84\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"310\\\" y=\\\"66.68\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association Z -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"47\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M290 109 a14 14 90 0 1 14 14 V137 h-26 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M304 137 v16 a14 14 90 0 1 -14 14 H292 a14 14 90 0 1 -14 -14 V137 H26\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"278\\\" y=\\\"109\\\" width=\\\"26\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"278\\\" y1=\\\"137\\\" x2=\\\"304\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"285\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Z</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"217.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"339.3\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"\\t<text x=\\\"339.3\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association STOCKER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"47\\\" x2=\\\"377\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"229\\\" x2=\\\"377\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M407 109 a14 14 90 0 1 14 14 V137 h-88 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M421 137 v16 a14 14 90 0 1 -14 14 H347 a14 14 90 0 1 -14 -14 V137 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"333\\\" y=\\\"109\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"333\\\" y1=\\\"137\\\" x2=\\\"421\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"340\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stocker</text>\\n\",\n       \"\\t\\t<text x=\\\"340\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"382\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"382\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"377\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M248 200 a14 14 90 0 1 14 14 V228 h-104 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M262 228 v16 a14 14 90 0 1 -14 14 H172 a14 14 90 0 1 -14 -14 V228 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"158\\\" y=\\\"200\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"158\\\" y1=\\\"228\\\" x2=\\\"262\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"165\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Composer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"310\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPOT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"39\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"334\\\" y1=\\\"39\\\" x2=\\\"420\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"350\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Dépôt</text>\\n\",\n       \"\\t<text x=\\\"342\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num dépôt</text>\\n\",\n       \"\\t<line x1=\\\"342\\\" y1=\\\"59\\\" x2=\\\"411\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"342\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">surface</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"120\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"129\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"121\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ARTICLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"221\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"334\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"334\\\" y1=\\\"221\\\" x2=\\\"420\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"343\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Article</text>\\n\",\n       \"\\t<text x=\\\"342\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. article</text>\\n\",\n       \"\\t<line x1=\\\"342\\\" y1=\\\"241\\\" x2=\\\"406\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"342\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \":::\\n\",\n    \"Dépôt: num dépôt, surface\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Louer, 11 Commande, 0N Dépôt\\n\",\n    \"Z, XX Commande, XX Article, XX Dépôt\\n\",\n    \"Stocker, 1N Dépôt, 1N Article: quantité\\n\",\n    \"\\n\",\n    \"Commande: num. commande, date\\n\",\n    \"Composer, 1N Commande, 0N Article\\n\",\n    \":\\n\",\n    \"Article: réf. article, prix\\n\",\n    \"\\n\",\n    \"(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer: Z, Z\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il ne reste plus qu'à rendre invisibles l'association Z et ses pattes en préfixant Z d'un signe moins `-` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 133,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"417\\\" height=\\\"276\\\" viewBox=\\\"0 0 417 276\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"417\\\" height=\\\"276\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint I_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<polygon points=\\\"320 138 308 144 312 138 308 132\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"138\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"229\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"210\\\" y1=\\\"138\\\" x2=\\\"291\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"291\\\" cy=\\\"138\\\" r=\\\"12\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"288.5\\\" y=\\\"142.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">I</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association LOUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"210\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M231 109 a14 14 90 0 1 14 14 V137 h-70 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M245 137 v16 a14 14 90 0 1 -14 14 H189 a14 14 90 0 1 -14 -14 V137 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"175\\\" y=\\\"109\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"175\\\" y1=\\\"137\\\" x2=\\\"245\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"182\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Louer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"109.84\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"68.99\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association STOCKER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"47\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"364\\\" y2=\\\"138\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M394 109 a14 14 90 0 1 14 14 V137 h-88 V123 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M408 137 v16 a14 14 90 0 1 -14 14 H334 a14 14 90 0 1 -14 -14 V137 H88\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"320\\\" y=\\\"109\\\" width=\\\"88\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"320\\\" y1=\\\"137\\\" x2=\\\"408\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stocker</text>\\n\",\n       \"\\t\\t<text x=\\\"327\\\" y=\\\"155.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"369\\\" y=\\\"183\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"69\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"364\\\" y1=\\\"229\\\" x2=\\\"210\\\" y2=\\\"229\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M248 200 a14 14 90 0 1 14 14 V228 h-104 V214 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M262 228 v16 a14 14 90 0 1 -14 14 H172 a14 14 90 0 1 -14 -14 V228 H104\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"158\\\" y=\\\"200\\\" width=\\\"104\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"158\\\" y1=\\\"228\\\" x2=\\\"262\\\" y2=\\\"228\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"165\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Composer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"245\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPOT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"39\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"9\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"39\\\" x2=\\\"407\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"337\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Dépôt</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num dépôt</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"59\\\" x2=\\\"398\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">surface</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"221\\\" width=\\\"120\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"191\\\" width=\\\"120\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"221\\\" x2=\\\"129\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Commande</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"241\\\" x2=\\\"121\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ARTICLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"221\\\" width=\\\"86\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"191\\\" width=\\\"86\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"221\\\" x2=\\\"407\\\" y2=\\\"221\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"330\\\" y=\\\"212.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Article</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"238.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. article</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"241\\\" x2=\\\"393\\\" y2=\\\"241\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"255.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \":::\\n\",\n    \"Dépôt: num dépôt, surface\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Louer, 11 Commande, 0N Dépôt\\n\",\n    \"-Z, XX Commande, XX Article, XX Dépôt\\n\",\n    \"Stocker, 1N Dépôt, 1N Article: quantité\\n\",\n    \"\\n\",\n    \"Commande: num. commande, date\\n\",\n    \"Composer, 1N Commande, 0N Article\\n\",\n    \":\\n\",\n    \"Article: réf. article, prix\\n\",\n    \"\\n\",\n    \"(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer: Z, Z\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cette technique résiste très bien aux réarrangements automatiques.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Gouttière d'identifiants\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Elle apparaît automatiquement (`visibility=auto`) dès qu'il y a au moins un identifiant alternatif. Il est possible de l'en empêcher :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 134,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"102\\\" height=\\\"146\\\" viewBox=\\\"0 0 102 146\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"102\\\" height=\\\"146\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"93\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"79\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Mail</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --gutters ids:visibility=off\\n\",\n    \"CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"... ou au contraire de la forcer quand elle est superfétatoire :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 135,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"134\\\" height=\\\"146\\\" viewBox=\\\"0 0 134 146\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"134\\\" height=\\\"146\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"116\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"41\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"32\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"41\\\" y1=\\\"39\\\" x2=\\\"41\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.38\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"116\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"125\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"33\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ID</text>\\n\",\n       \"\\t<line x1=\\\"49\\\" y1=\\\"59\\\" x2=\\\"111\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\"/>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\"/>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\"/>\\n\",\n       \"\\t<text x=\\\"49\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Mail</text>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --gutters ids:visibility=on\\n\",\n    \"CLIENT: Réf. client, Nom, Prénom, Adresse, Mail\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Vous pouvez aussi préciser quelles chaînes dénoteront un identifiant fort (par défaut, `strong=ID`), un identifiant faible (par défaut, `weak=id`) ainsi que les numéros des groupes d'identifiants alternatifs (par défaut, `alts=123456789`, mais vous pouvez lister moins de 9 symboles) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 136,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"128\\\" height=\\\"146\\\" viewBox=\\\"0 0 128 146\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"128\\\" height=\\\"146\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"34\\\" y=\\\"39\\\" width=\\\"85\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"25\\\" height=\\\"98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"34\\\" y1=\\\"39\\\" x2=\\\"34\\\" y2=\\\"137\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.38\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"110\\\" height=\\\"128\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"119\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"30\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">CLIENT</text>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Réf. client</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">➤</text>\\n\",\n       \"\\t<line x1=\\\"42\\\" y1=\\\"59\\\" x2=\\\"104\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Nom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">❶</text>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Prénom</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">❶</text>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Adresse</text>\\n\",\n       \"\\t<text x=\\\"21\\\" y=\\\"107\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\"/>\\n\",\n       \"\\t<text x=\\\"42\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">Mail</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"124\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">❷</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --gutters ids:strong=➤,alts=❶❷❸❹\\n\",\n    \"CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Style et direction des pattes de l'héritage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le type de flèche spécifiant le mécanisme de passage au modèle relationnel (`<=`, `<-`, `->` ou `=>`) fait par défaut l'objet d'une visualisation dès le modèle conceptuel : la ou les pattes vers les entités de destination des attributs migrants sont orientées vers celles-ci ; et la ou les autres pattes sont doublées (pour `<=` et `=>`) ou non (pour `<-` et `->`).\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 137,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"296\\\" height=\\\"270\\\" viewBox=\\\"0 0 296 270\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"296\\\" height=\\\"270\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance PERSONNE_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"131\\\" y1=\\\"56\\\" x2=\\\"131\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"129\\\" y1=\\\"56\\\" x2=\\\"129\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"69.8 210 74.28 197.35 75.56 204.45 82.6 206.0\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"223\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"187.68 201 174.65 197.8 181.59 195.82 182.42 188.66\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"130 123.13 105 166.43 155 166.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"118\\\" y=\\\"158\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">XT</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERSONNE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"77\\\" y1=\\\"39\\\" x2=\\\"183\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"86\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Personne</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num SS</text>\\n\",\n       \"\\t<line x1=\\\"85\\\" y1=\\\"59\\\" x2=\\\"131\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prénom</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity HOMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"240\\\" width=\\\"78\\\" height=\\\"12\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"42\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"240\\\" x2=\\\"87\\\" y2=\\\"240\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"231.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Homme</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FEMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"231\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"159\\\" y1=\\\"231\\\" x2=\\\"287\\\" y2=\\\"231\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"222.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Femme</text>\\n\",\n       \"\\t<text x=\\\"167\\\" y=\\\"248.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom de jeune fille</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Femme** (<u>num SS</u>, nom, prénom, nom de jeune fille)\\n\",\n       \"- **Homme** (<u>num SS</u>, nom, prénom)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Personne: num SS, nom, prénom\\n\",\n    \"\\n\",\n    \"/XT\\\\ Personne => Homme, Femme: sexe\\n\",\n    \"\\n\",\n    \"Homme: \\n\",\n    \":\\n\",\n    \"Femme: nom de jeune fille\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cette visualisation n'est pas conventionnelle : on se borne normalement à ajouter une flèche dirigée vers l'entité-mère.\\n\",\n    \"\\n\",\n    \"Pour désactiver l'embellissement opéré par Mocodo, sans pour autant changer le mécanisme de passage au relationnel, prolongez simplement d'un caractère la flèche : `<==`, `<--`, `-->` ou `==>` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 138,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"296\\\" height=\\\"270\\\" viewBox=\\\"0 0 296 270\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"296\\\" height=\\\"270\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Inheritance PERSONNE_PARENT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"130\\\" y1=\\\"56\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"130 103 136 115 130 111 124 115\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"223\\\" y1=\\\"231\\\" x2=\\\"130\\\" y2=\\\"152\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<polygon points=\\\"130 123.13 105 166.43 155 166.43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"118\\\" y=\\\"158\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">XT</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PERSONNE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"77\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"77\\\" y1=\\\"39\\\" x2=\\\"183\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"86\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Personne</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num SS</text>\\n\",\n       \"\\t<line x1=\\\"85\\\" y1=\\\"59\\\" x2=\\\"131\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"85\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prénom</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity HOMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"240\\\" width=\\\"78\\\" height=\\\"12\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"210\\\" width=\\\"78\\\" height=\\\"42\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"240\\\" x2=\\\"87\\\" y2=\\\"240\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"231.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Homme</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FEMME -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"231\\\" width=\\\"128\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"159\\\" y=\\\"201\\\" width=\\\"128\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"159\\\" y1=\\\"231\\\" x2=\\\"287\\\" y2=\\\"231\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"222.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Femme</text>\\n\",\n       \"\\t<text x=\\\"167\\\" y=\\\"248.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom de jeune fille</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Femme** (<u>num SS</u>, nom, prénom, nom de jeune fille)\\n\",\n       \"- **Homme** (<u>num SS</u>, nom, prénom)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Personne: num SS, nom, prénom\\n\",\n    \"\\n\",\n    \"/XT\\\\ Personne ==> Homme, Femme: sexe\\n\",\n    \"\\n\",\n    \"Homme: \\n\",\n    \":\\n\",\n    \"Femme: nom de jeune fille\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Changement de la version 4.0.** Précédemment, `-->` et `==>` s'écrivaient respectivement `->>` et `=>>`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Retouches fines\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Lors du plongement, Mocodo génère systématiquement un fichier (intitulé par défaut `sandbox_geo.json`) répertoriant les positions les plus importantes du dessin. Les autres coordonnées sont calculées relativement à celles-ci.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 139,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"444\\\" height=\\\"242\\\" viewBox=\\\"0 0 444 242\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"444\\\" height=\\\"242\\\" fill=\\\"#f5f5f5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association VELIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"117\\\" x2=\\\"214\\\" y2=\\\"38\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"107 92.19 114.99 81.41 114.14 88.57 120.42 92.12\\\" fill=\\\"#bf812d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"117\\\" x2=\\\"214\\\" y2=\\\"38\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M241 9 a14 14 90 0 1 14 14 V37 h-82 V23 a14 14 90 0 1 14 -14\\\" fill=\\\"#dfc27d\\\" stroke=\\\"#dfc27d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M255 37 v16 a14 14 90 0 1 -14 14 H187 a14 14 90 0 1 -14 -14 V37 H82\\\" fill=\\\"#f6e8c3\\\" stroke=\\\"#f6e8c3\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"173\\\" y=\\\"9\\\" width=\\\"82\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"173\\\" y1=\\\"37\\\" x2=\\\"255\\\" y2=\\\"37\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"188\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">VELIT</text>\\n\",\n       \"\\t\\t<text x=\\\"180\\\" y=\\\"55.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">sollicitudin</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"112\\\" y=\\\"104.23\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"298\\\" y=\\\"101.77\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association VIVAMUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"117\\\" x2=\\\"214\\\" y2=\\\"196\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"117\\\" x2=\\\"214\\\" y2=\\\"196\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M249 159 a14 14 90 0 1 14 14 V187 h-98 V173 a14 14 90 0 1 14 -14\\\" fill=\\\"#dfc27d\\\" stroke=\\\"#dfc27d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M263 187 v32 a14 14 90 0 1 -14 14 H179 a14 14 90 0 1 -14 -14 V187 H98\\\" fill=\\\"#f6e8c3\\\" stroke=\\\"#f6e8c3\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"165\\\" y=\\\"159\\\" width=\\\"98\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"165\\\" y1=\\\"187\\\" x2=\\\"263\\\" y2=\\\"187\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"173\\\" y=\\\"180.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">VIVAMUS</text>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"205.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">eleifend</text>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"222.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">iaculis</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"140.23\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"112\\\" y=\\\"137.77\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BLANDIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"62\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#80cdc1\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"92\\\" width=\\\"98\\\" height=\\\"80\\\" fill=\\\"#c7eae5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"62\\\" width=\\\"98\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"92\\\" x2=\\\"107\\\" y2=\\\"92\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"83.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BLANDIT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"109.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"112\\\" x2=\\\"81\\\" y2=\\\"112\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"126.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"143.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nibh</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"160\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity NONUMMY -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"79\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#80cdc1\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"109\\\" width=\\\"114\\\" height=\\\"46\\\" fill=\\\"#c7eae5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"79\\\" width=\\\"114\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"109\\\" x2=\\\"435\\\" y2=\\\"109\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"330\\\" y=\\\"100.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">NONUMMY</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"126.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"129\\\" x2=\\\"393\\\" y2=\\\"129\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"143.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo --colors brewer+1\\n\",\n    \"VELIT, 1N> BLANDIT, 11 NONUMMY: sollicitudin\\n\",\n    \"\\n\",\n    \"BLANDIT: consequat, ligula, nibh, consequat\\n\",\n    \":::\\n\",\n    \"NONUMMY: consequat, ligula\\n\",\n    \"  \\n\",\n    \"VIVAMUS, 0N NONUMMY, 0N BLANDIT: eleifend, iaculis\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ouvrons le fichier de géométrie généré :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 140,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style>pre { line-height: 125%; }\\n\",\n       \"td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \".output_html .hll { background-color: #ffffcc }\\n\",\n       \".output_html { background: #f8f8f8; }\\n\",\n       \".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\\n\",\n       \".output_html .err { border: 1px solid #FF0000 } /* Error */\\n\",\n       \".output_html .k { color: #008000; font-weight: bold } /* Keyword */\\n\",\n       \".output_html .o { color: #666666 } /* Operator */\\n\",\n       \".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\\n\",\n       \".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\\n\",\n       \".output_html .cp { color: #9C6500 } /* Comment.Preproc */\\n\",\n       \".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\\n\",\n       \".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\\n\",\n       \".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\\n\",\n       \".output_html .gd { color: #A00000 } /* Generic.Deleted */\\n\",\n       \".output_html .ge { font-style: italic } /* Generic.Emph */\\n\",\n       \".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\\n\",\n       \".output_html .gr { color: #E40000 } /* Generic.Error */\\n\",\n       \".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\\n\",\n       \".output_html .gi { color: #008400 } /* Generic.Inserted */\\n\",\n       \".output_html .go { color: #717171 } /* Generic.Output */\\n\",\n       \".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\\n\",\n       \".output_html .gs { font-weight: bold } /* Generic.Strong */\\n\",\n       \".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\\n\",\n       \".output_html .gt { color: #0044DD } /* Generic.Traceback */\\n\",\n       \".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\\n\",\n       \".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\\n\",\n       \".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\\n\",\n       \".output_html .kp { color: #008000 } /* Keyword.Pseudo */\\n\",\n       \".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\\n\",\n       \".output_html .kt { color: #B00040 } /* Keyword.Type */\\n\",\n       \".output_html .m { color: #666666 } /* Literal.Number */\\n\",\n       \".output_html .s { color: #BA2121 } /* Literal.String */\\n\",\n       \".output_html .na { color: #687822 } /* Name.Attribute */\\n\",\n       \".output_html .nb { color: #008000 } /* Name.Builtin */\\n\",\n       \".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\\n\",\n       \".output_html .no { color: #880000 } /* Name.Constant */\\n\",\n       \".output_html .nd { color: #AA22FF } /* Name.Decorator */\\n\",\n       \".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\\n\",\n       \".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\\n\",\n       \".output_html .nf { color: #0000FF } /* Name.Function */\\n\",\n       \".output_html .nl { color: #767600 } /* Name.Label */\\n\",\n       \".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\\n\",\n       \".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\\n\",\n       \".output_html .nv { color: #19177C } /* Name.Variable */\\n\",\n       \".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\\n\",\n       \".output_html .w { color: #bbbbbb } /* Text.Whitespace */\\n\",\n       \".output_html .mb { color: #666666 } /* Literal.Number.Bin */\\n\",\n       \".output_html .mf { color: #666666 } /* Literal.Number.Float */\\n\",\n       \".output_html .mh { color: #666666 } /* Literal.Number.Hex */\\n\",\n       \".output_html .mi { color: #666666 } /* Literal.Number.Integer */\\n\",\n       \".output_html .mo { color: #666666 } /* Literal.Number.Oct */\\n\",\n       \".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\\n\",\n       \".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\\n\",\n       \".output_html .sc { color: #BA2121 } /* Literal.String.Char */\\n\",\n       \".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\\n\",\n       \".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\\n\",\n       \".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\\n\",\n       \".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\\n\",\n       \".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\\n\",\n       \".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\\n\",\n       \".output_html .sx { color: #008000 } /* Literal.String.Other */\\n\",\n       \".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\\n\",\n       \".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\\n\",\n       \".output_html .ss { color: #19177C } /* Literal.String.Symbol */\\n\",\n       \".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\\n\",\n       \".output_html .fm { color: #0000FF } /* Name.Function.Magic */\\n\",\n       \".output_html .vc { color: #19177C } /* Name.Variable.Class */\\n\",\n       \".output_html .vg { color: #19177C } /* Name.Variable.Global */\\n\",\n       \".output_html .vi { color: #19177C } /* Name.Variable.Instance */\\n\",\n       \".output_html .vm { color: #19177C } /* Name.Variable.Magic */\\n\",\n       \".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\\\"highlight\\\"><pre><span></span><span class=\\\"p\\\">{</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;width&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">444</span><span class=\\\"p\\\">,</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;height&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">242</span><span class=\\\"p\\\">,</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;cx&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">[</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VELIT&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">214</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;BLANDIT&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">58</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;NONUMMY&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">378</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VIVAMUS&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">214</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">]</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;cy&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">[</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VELIT&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">38</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;BLANDIT&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">117</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;NONUMMY&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">117</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VIVAMUS&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">196</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">]</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;shift&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">[</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VELIT,BLANDIT,0&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">0</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VELIT,NONUMMY,0&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">0</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VIVAMUS,NONUMMY,0&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">0</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VIVAMUS,BLANDIT,0&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mi\\\">0</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">]</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p\\\">],</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"nt\\\">&quot;ratio&quot;</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">[</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"p\\\">[</span><span class=\\\"w\\\"> </span><span class=\\\"s2\\\">&quot;VELIT,BLANDIT,0&quot;</span><span class=\\\"p\\\">,</span><span class=\\\"w\\\"> </span><span class=\\\"mf\\\">1.0</span><span class=\\\"w\\\"> </span><span class=\\\"p\\\">]</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p\\\">]</span>\\n\",\n       \"<span class=\\\"p\\\">}</span>\\n\",\n       \"</pre></div>\\n\"\n      ],\n      \"text/latex\": [\n       \"\\\\begin{Verbatim}[commandchars=\\\\\\\\\\\\{\\\\}]\\n\",\n       \"\\\\PY{p}{\\\\PYZob{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}width\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+m+mi}{444}\\\\PY{p}{,}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}height\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+m+mi}{242}\\\\PY{p}{,}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}cx\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{p}{[}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VELIT\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{214}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}BLANDIT\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{58}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}NONUMMY\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{378}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VIVAMUS\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{214}\\\\PY{+w}{ }\\\\PY{p}{]}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}cy\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{p}{[}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VELIT\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{38}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}BLANDIT\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{117}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}NONUMMY\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{117}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VIVAMUS\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{196}\\\\PY{+w}{ }\\\\PY{p}{]}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}shift\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{p}{[}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VELIT,BLANDIT,0\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{0}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VELIT,NONUMMY,0\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{0}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VIVAMUS,NONUMMY,0\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{0}\\\\PY{+w}{ }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VIVAMUS,BLANDIT,0\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mi}{0}\\\\PY{+w}{ }\\\\PY{p}{]}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p}{],}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{n+nt}{\\\\PYZdq{}ratio\\\\PYZdq{}}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{p}{[}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{p}{[}\\\\PY{+w}{ }\\\\PY{l+s+s2}{\\\\PYZdq{}VELIT,BLANDIT,0\\\\PYZdq{}}\\\\PY{p}{,}\\\\PY{+w}{ }\\\\PY{l+m+mf}{1.0}\\\\PY{+w}{ }\\\\PY{p}{]}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p}{]}\\n\",\n       \"\\\\PY{p}{\\\\PYZcb{}}\\n\",\n       \"\\\\end{Verbatim}\\n\"\n      ],\n      \"text/plain\": [\n       \"{\\n\",\n       \"  \\\"width\\\": 444,\\n\",\n       \"  \\\"height\\\": 242,\\n\",\n       \"  \\\"cx\\\": [\\n\",\n       \"    [ \\\"VELIT\\\", 214 ],\\n\",\n       \"    [ \\\"BLANDIT\\\", 58 ],\\n\",\n       \"    [ \\\"NONUMMY\\\", 378 ],\\n\",\n       \"    [ \\\"VIVAMUS\\\", 214 ]\\n\",\n       \"  ],\\n\",\n       \"  \\\"cy\\\": [\\n\",\n       \"    [ \\\"VELIT\\\", 38 ],\\n\",\n       \"    [ \\\"BLANDIT\\\", 117 ],\\n\",\n       \"    [ \\\"NONUMMY\\\", 117 ],\\n\",\n       \"    [ \\\"VIVAMUS\\\", 196 ]\\n\",\n       \"  ],\\n\",\n       \"  \\\"shift\\\": [\\n\",\n       \"    [ \\\"VELIT,BLANDIT,0\\\", 0 ],\\n\",\n       \"    [ \\\"VELIT,NONUMMY,0\\\", 0 ],\\n\",\n       \"    [ \\\"VIVAMUS,NONUMMY,0\\\", 0 ],\\n\",\n       \"    [ \\\"VIVAMUS,BLANDIT,0\\\", 0 ]\\n\",\n       \"  ],\\n\",\n       \"  \\\"ratio\\\": [\\n\",\n       \"    [ \\\"VELIT,BLANDIT,0\\\", 1.0 ]\\n\",\n       \"  ]\\n\",\n       \"}\"\n      ]\n     },\n     \"execution_count\": 140,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Code(\\\"sandbox_geo.json\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"On y trouve :\\n\",\n    \"\\n\",\n    \"- un couple de dimensions `width` et `height` définit la taille du MCD ;\\n\",\n    \"- deux listes de couples `cx` et `cy`, les abscisses et ordonnées des centres des boîtes ;\\n\",\n    \"- un dictionnaire `shift`, les positions relatives des cardinalités par rapport à leur position par défaut ;\\n\",\n    \"- une liste `ratio`, les positions des flèches éventuelles : leur valeur peuvent varier de `0.0` (flèche cachée sous la boîte d'origine) à `1.0` (par défaut, pointe de la flèche au contact du bord de la boîte de destination, compte non tenu de l'arrondi s'il s'agit d'une association).\\n\",\n    \"\\n\",\n    \"Copions-collons ce texte, apportons-lui quelques modifications et sauvegardons-le :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 141,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Overwriting sandbox_geo.json\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%file sandbox_geo.json\\n\",\n    \"{\\n\",\n    \"  \\\"width\\\": 444,\\n\",\n    \"  \\\"height\\\": 182,\\n\",\n    \"  \\\"cx\\\": [\\n\",\n    \"    [ \\\"VELIT\\\", 214 ],\\n\",\n    \"    [ \\\"BLANDIT\\\", 58 ],\\n\",\n    \"    [ \\\"NONUMMY\\\", 378 ],\\n\",\n    \"    [ \\\"VIVAMUS\\\", 214 ]\\n\",\n    \"  ],\\n\",\n    \"  \\\"cy\\\": [\\n\",\n    \"    [ \\\"VELIT\\\", 38 ],\\n\",\n    \"    [ \\\"BLANDIT\\\", 87 ],\\n\",\n    \"    [ \\\"NONUMMY\\\", 87 ],\\n\",\n    \"    [ \\\"VIVAMUS\\\", 136 ]\\n\",\n    \"  ],\\n\",\n    \"  \\\"shift\\\": [\\n\",\n    \"    [ \\\"VELIT,BLANDIT,0\\\", -30 ],\\n\",\n    \"    [ \\\"VELIT,NONUMMY,0\\\", -30 ],\\n\",\n    \"    [ \\\"VIVAMUS,NONUMMY,0\\\", 0 ],\\n\",\n    \"    [ \\\"VIVAMUS,BLANDIT,0\\\", 0 ]\\n\",\n    \"  ],\\n\",\n    \"  \\\"ratio\\\": [\\n\",\n    \"    [ \\\"VELIT,BLANDIT,0\\\", 0.5 ]\\n\",\n    \"  ]\\n\",\n    \"}\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il suffit maintenant d'ajouter l'option `--reuse_geo` pour appliquer ces modifications :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 142,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"444\\\" height=\\\"182\\\" viewBox=\\\"0 0 444 182\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"444\\\" height=\\\"182\\\" fill=\\\"#f5f5f5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association VELIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"87\\\" x2=\\\"214\\\" y2=\\\"38\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<polygon points=\\\"140 61.24 149.65 51.92 147.63 58.85 153.25 63.37\\\" fill=\\\"#bf812d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"87\\\" x2=\\\"214\\\" y2=\\\"38\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M241 9 a14 14 90 0 1 14 14 V37 h-82 V23 a14 14 90 0 1 14 -14\\\" fill=\\\"#dfc27d\\\" stroke=\\\"#dfc27d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M255 37 v16 a14 14 90 0 1 -14 14 H187 a14 14 90 0 1 -14 -14 V37 H82\\\" fill=\\\"#f6e8c3\\\" stroke=\\\"#f6e8c3\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"173\\\" y=\\\"9\\\" width=\\\"82\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"173\\\" y1=\\\"37\\\" x2=\\\"255\\\" y2=\\\"37\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"188\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">VELIT</text>\\n\",\n       \"\\t\\t<text x=\\\"180\\\" y=\\\"55.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">sollicitudin</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"112\\\" y=\\\"55.17\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"298\\\" y=\\\"53.65\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association VIVAMUS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"378\\\" y1=\\\"87\\\" x2=\\\"214\\\" y2=\\\"136\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"58\\\" y1=\\\"87\\\" x2=\\\"214\\\" y2=\\\"136\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M249 99 a14 14 90 0 1 14 14 V127 h-98 V113 a14 14 90 0 1 14 -14\\\" fill=\\\"#dfc27d\\\" stroke=\\\"#dfc27d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M263 127 v32 a14 14 90 0 1 -14 14 H179 a14 14 90 0 1 -14 -14 V127 H98\\\" fill=\\\"#f6e8c3\\\" stroke=\\\"#f6e8c3\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"165\\\" y=\\\"99\\\" width=\\\"98\\\" height=\\\"74\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"165\\\" y1=\\\"127\\\" x2=\\\"263\\\" y2=\\\"127\\\" stroke=\\\"#bf812d\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"173\\\" y=\\\"120.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">VIVAMUS</text>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"145.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">eleifend</text>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"162.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">iaculis</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"297\\\" y=\\\"98.35\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"112\\\" y=\\\"96.83\\\" fill=\\\"#01665e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BLANDIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"32\\\" width=\\\"98\\\" height=\\\"30\\\" fill=\\\"#80cdc1\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"62\\\" width=\\\"98\\\" height=\\\"80\\\" fill=\\\"#c7eae5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"32\\\" width=\\\"98\\\" height=\\\"110\\\" fill=\\\"none\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"62\\\" x2=\\\"107\\\" y2=\\\"62\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"53.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">BLANDIT</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"79.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"82\\\" x2=\\\"81\\\" y2=\\\"82\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"96.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"113.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nibh</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"130\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity NONUMMY -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"49\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#80cdc1\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"79\\\" width=\\\"114\\\" height=\\\"46\\\" fill=\\\"#c7eae5\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"321\\\" y=\\\"49\\\" width=\\\"114\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"321\\\" y1=\\\"79\\\" x2=\\\"435\\\" y2=\\\"79\\\" stroke=\\\"#35978f\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"330\\\" y=\\\"70.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">NONUMMY</text>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"96.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">consequat</text>\\n\",\n       \"\\t<line x1=\\\"329\\\" y1=\\\"99\\\" x2=\\\"393\\\" y2=\\\"99\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"113.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ligula</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --colors brewer+1 --reuse_geo\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Bien entendu, ce genre de manipulations doit rester exceptionnel. Il est en tout cas à réserver à la toute dernière étape de production d'un MCD, puisque la plupart des évolutions subséquentes de son texte-source frapperaient d'obsolescence votre fichier de géométrie.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** Étant donné que Mocodo produit des SVG, rien ne vous empêche de retoucher ceux-ci avec un logiciel de dessin vectoriel dédié, comme [Inkscape](https://www.inkscape.org/?lang=fr) (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc. Attention, le SVG généré n'est pas spécialement pensé pour cet usage. Certains éléments sont groupés pour permettre leur déplacement en bloc, mais les liens ne suivent pas ces déplacements, ce qui peut vite devenir fastidieux.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Conversion dans d'autres formats graphiques\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Avec l'option `--svg_to` suivie de `pdf` et/ou `png`, Mocodo convertit en PDF et/ou PNG le SVG généré pour le MCD.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 143,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%mocodo -i ccp --svg_to png pdf --select\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le premier format est prévu pour inclusion dans des documents qui ne gèrent pas les SVG :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 144,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"\\n\",\n       \"        <iframe\\n\",\n       \"            width=\\\"100%\\\"\\n\",\n       \"            height=\\\"100%\\\"\\n\",\n       \"            src=\\\"mocodo_notebook/ccp.pdf\\\"\\n\",\n       \"            frameborder=\\\"0\\\"\\n\",\n       \"            allowfullscreen\\n\",\n       \"            \\n\",\n       \"        ></iframe>\\n\",\n       \"        \"\n      ],\n      \"text/plain\": [\n       \"<IPython.lib.display.IFrame at 0x12ee2e400>\"\n      ]\n     },\n     \"execution_count\": 144,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.IFrame(\\\"mocodo_notebook/ccp.pdf\\\", width=\\\"100%\\\", height=\\\"100%\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Attention, seules les polices de caractères les plus courantes apparaîtront correctement sur toutes les plateformes.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le second est un format bitmap, donc avec une certaine perte de qualité :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 145,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAlIAAACACAIAAABP1BApAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO29eTzU3f//f2axZanIkolQoZBpF5HSolQira7i0hWlq0UrqksoLeq6VJJUpBRxlUIlVLSQCvW21tV10aKSipR9eH3/OL9ev/nM8jLGjBnm3P9wG+ec12vO67zOc85rOY/zIGEYBhAIBAKBkAzIoq4AAoFAIBDdBxr2EAgEAiFBoGEPgUAgEBIEGvYQCAQCIUGgYQ+BQCAQEgQa9hAIBAIhQaBhD4FAIBASBJVbxsaNG589e9adVREhdDo9JCRE1LVAIBAIhNDherf37NkzCRn2JOdIEQgEAsH1bg8AQKfTMzMzu6smIsPa2lrUVUAgEAhEN4He7SEQCARCgkDDHgKBQCAkCDTsIRAIBEKCQMMeAoFAICQINOwhEAgEQoIgmsmJQIgQiVKOig9Iw9qDQDFCAEFPRnd7CDEF6Sm7H9TmPQt0vrhB3DLobg8hvkiIclR8QBrWHgeKEY4Q92R0t4dAIBAICaKrd3t1dXWnT5/+3//+V15eTqFQtLW1zczM5s6dq6ysLCcnJ5AqIhAIBAIhKLp0txcbG6urq7t58+bo6Oh79+7dvXs3Ojp6zZo1WlpaoaGhgqoihmEZGRk8Fk5LS2tsbGRJbGxsvHfvnqDqg0AgEIieC//DXn5+/q+//vr161d9ff1jx45lZGRcvXrVy8tLWVlZV1d33bp1sNi2bdsGDRpkamra1NTEvpO0tDQtLS0tLa309HSYEhQUNOj/oqGh4enpCXP9/f1hYlZWFr4TDw+PQYMGHThwAABw9+5dLS0tlj1oaWndvHmT7yNFIBAIRK+B/4ec27Zta25utrS0zMjIkJaWhon29va//vprVVWVrKwsTJkxY0ZwcPDEiRPxFGZmzJjx8eNHGRmZ6dOnw5TBgwdXVlYaGRlZWFjAFAaD8e+//8LPJiYmlZWVAABXV9d79+5paWkBAOh0ekREhKGhIQBASUnJzs5OVlb22bNnjx8/Hj9+PJ1Ob2pqUlJS4vtIEQgEAtFr4HPYYzAYjx49AgAEBgbiYx7ExMTExMSki9WytraGj0nr6+vJZDLLa0IVFZWKioqpU6dmZWVpamoyZ/n4+MAPBw4cePz4saOj4/bt27tYGQQCgUD0Gvh8yPn169f6+noAgIaGhkDr8/8RGRk5dOjQoUOHDh48+OHDhyy5gYGBixYtevXq1dSpUz9+/CiMCiAQCASiV8LnsKempjZ48GAAQHJyMnsu/qKObwYPHmxhYWFhYWFiYsJyNwkAoFAoFy5cmD9//osXL2xsbKqrq7v4dQgEAoGQEPif0rJw4UIAgK+v76lTpxgMBkysra09ePDg7Nmzs7Ozu1ItGxub6Ojo6Ojou3fvWllZsRegUqmXLl2aPXt2SUmJn59fV74LgUAgEJID/1Na9u3bV1JScuPGDXd39+3bt+vr6zc0NJSWljIYDAqFcvXqVXNzc7xwQUHBzp078X/fvHmzePFiOzs7bju/f/8+c/nHjx+npaWxlJGWlr58+fLcuXN5lzcgJAGkJUUgmAkKCsrLy2NJVFNTmz59uo2NTd++fUVSK1GCcWHy5MmTJ0/mlgtpb29PTEy0sbGBb/hkZGSMjY19fX3Ly8vxMriSgYWYmBgMw1JTU0kkEplMTkpKguXxOSkc6wnnpyxduhTff319vYKCAgDA29ubuW4uLi4AgAULFhAfAo9Hiuh++DsvFy9eVFZWZu8/JBLp4MGD7OVbW1sFUFfxo729PT09vbNboVjoWfB4vuDsd47o6urW1NR09nu7LWpu3brV0NDAktjQ0JCVlUW8IXHLdGnYY6apqam9vZ3Hwt+/f+9UW1dUVPBeuLOgUBdP+DgveXl5MjIyAAB2Lamenl5jYyNe8vbt23Z2durq6mQyWUNDY+7cuXfv3sVzr1y5QqPRaDRabm4unnjz5k2YmJqa2qlikGPHjsH0v//+mzl99+7dMD0zMxNPdHd3p9Fo+/fvh//OmTOHxoS+vr6joyN+pYhh2N69e2n/FzU1tWHDhnWq9TAUCz0NHs/Xly9f4CDn4+Nz/Pjx48ePh4aGrl69GiZGR0djGLZlyxbm/qOlpWVmZrZr167a2lp8P8RR02Ev9fX1pdFoZmZmzHWbOXMmjUb7/fff4b+3bt2CYuu0tDQMw7y9vVVUVFj6toqKCstNTmdbRmBLUcOfGx6B92e8A6fPIBDE8KglPXLkyMaNG0kkkq2t7fDhw4uLi5OTk5OTk8PCwtasWQMAoNFo8AI5Ojp6/PjxcKvTp0/DRBqNBlN4LAZJT0+H6VevXl2wYAGe3qEUFQAwYcKElJQUMzOzkSNHYhhWU1OTkZFx5cqVP//808vLC3SkdkUgIIsWLaLT6fAzhmGXL1+urq5+8+YNAMDIyKiysnL48OGWlpYAgLq6upycnMDAwH/++Sc2NhbwEDUd9tLp06cHBQXNnDmTuUqWlpa3bt0aPXo0/JdFyS0sHTZ/o2VvQnKOtGfR2fPS2toqLy8PAGC+bWKnqqqKQqFISUkx342lpKRQqVQqlfrlyxcMw3Jzc2F0UKnUkpISDMOYVwUqLCyEW/FYDMOwwsJCEonk4OCgpqZGoVBevnyJZ12+fBkAoKKiAgAYOnRoZWUlhmFhYWEAgKtXr8IygYGBAIBDhw7hW5WXlysqKsrLy3/79g3DsJiYGADA2rVrYe6PHz/YHw3xAoqFnkVn7/aWLFni5eXl5eW1cePGadOmwUTYzaKiogAAHh4e+FawexsYGGC8RU2HvfTu3bsAADc3N+a67dmzBwAQGRmJp1CpVHl5eZZD2L9/PwAAf/7RxZZBDgyIXgKPWtJHjx61tbXZ2dkxX3XCfxkMBj6SAQAcHR3b29u3bt2KYdimTZvk5OQWL17MvkNeisFw9fX13bp1a1tbW1BQEEuBzkpRdXR0xo4dW19fX1xcjCcSq10RiLi4uL/++uuvv/4KCQnJyMgYMmTI9u3b7e3t8QIPHjxYu3bt2rVrf/nlFzhXf+rUqaAzUcMMx14qDiC/PdHQ1NR0586dx48ff/jw4f379xwXLBU5ZDJ5wIABI0aMmDx58sSJEykUiqhrRATUkr5+/To5OdnAwIAlNz09HT42gWIbKpW158MUXIoDADA2NlZQUDh37tzy5cvz8vJ27tzJ8TR1WKy8vPzSpUtKSkrZ2dmtra0AgJiYmF27dunp6eFloBS1paXl6tWrNjY2HMdXjrS1teGfBw8eDJ+1vnnzhl3tKrb0iFjgRs+KkdOnTw8bNgwAQCKR9PX11dXVWQqUl5d//vy5ra3t8+fPAICAgAA4i5D3qOEIcy9taWlhzmpububvWLoCutvrbgoKChYvXqyqqmpnZ7dnz56UlJQPHz6IulKcqaury83N3bVrl6Wlpba29p49e+DtlNjCi5Z0woQJAIDr168/fvwY3zA7OxtOKoa5OLt375aWlr5w4YK6ujrBKnfExYKDgxkMRl1d3YYNG3x9fQEADAZj3759LMU6JUV98+bN06dPpaWlR4wYgSd2qHYVN3pQLHCjZ8XImDFjrKysrKysLC0t2cc8AIC7u/vHjx8/ffoEH4G2tLTA66dORQ0OSy/t168fACApKenbt2+wQFtb28WLFwEA3SyiQHd73ce7d++8vb1jY2OVlZVXrFgxf/58a2trKSkpUderA759+5aenh4VFeXn53fq1Kljx47NmzdP1JXiDC9aUhqN5ufn5+/vP2nSpKVLlxoaGpaUlMTFxTEYjD179qipqTHvUFdX193dPTQ0NCAggGAeFkGxjx8/RkVFDRs2LDc3F94K1NbWGhkZRUdH79y5k2WuFrEU9ebNmzU1Ne3t7dXV1deuXfv+/bu3tzezWoMXtauY0ENjgRs9KEZ4gUQiRUVFmZiY7Nu3z9bW1sLCgveoIeilJiYmo0ePzs/PHzZs2NSpU2VlZe/cufP27VttbW34KLX74O+VYG+ie470wYMHampq8vLyO3fuhC94exw5OTmmpqYAgJUrV3aDcIe/88KLlrS9vT0uLs7MzExRUREAoKSkZG5unpCQgBeIi4sDAMyaNQvDsA8fPowfP57BYMAqAQBwBQIvxRwdHQGbfhTOpps3bx7GmxSV5dZNTk5u/PjxoaGh+CbEalfeQbHQRcQzRuAzBsA06YkdaO5maWmJpyxatAgAoKqq+uLFC4yHqOmwl2IYVl1d7eXlNXjwYAqFQiaTNTU1f/nll1evXuEF2JXcEN512BDiliFhGMYxYKytrZ8/fw5PYe8GHmZmZqbwviIuLs7V1VVXVzcpKQk+W++hMBiMwMDAwMDA2bNnx8fH9+nTR3jfZW1tDQDoynlpbm6WlpYmkUgEZZqamjhaYvUCXr9+3VnlT9fbvEN6TSxwo2fFCH90PWra2tra29uFd39P3DLo3Z7Qefjwoaur68SJE3Nycnp6nFOpVH9//5MnT6ampjo6OjK/qRZDZGRkiMc8AEBvHfOAWKpde1MscKNnxQh/dD1qoBxCIJXhA6J3e8K+BxIT4HWBkHj37p2jo6Ourm5iYiJ8o9sLWLVqFZlM/u233/7444+9e/eKujqInkGvjAVuoBgRZ9CUFuHi7e1dX1//4MGDXhbnK1eufPLkyb59+6ytraEwAIEgprfGAjdQjIgt6CGnECkoKIiNjfXy8uqVz3OOHj06bNiwzZs398rHOAjB0rtjgRsoRsQTNOwJkf379ysrK2/dulXUFREK0tLS+/btKywsPHfunKjrghB3encscAPFiHiChj1h0dTUdPPmzUWLFnV11VQxxtHRccyYMSdOnBB1RRBijSTEAjdQjIghfA57mpqaVCpVSkqKRqMtX778/fv3LAU8PT1VVVU/ffoE/y0rKxs6dCiJRMIVJB1SWVlJpVIjIyP5q6HIuX379vfv3x0cHERdEeHi7Oz85MkTtNg/ggAJiQVuoBgRN/ic0sJgMLS0tGbNmpWXlxcTE/P27VvmOZ/fv38/f/58VFQUrt738/N7/fr10qVLoasFL2AYBrUdJSUlRkZGwcHBW7Zs4a+2IuHJkycUCoXjGlG9yezYyclp06ZN169fX79+vcB3/vz5c6HOs0WwICSpLkEsRERE3Lp1CwDg4ODwyy+/CPyrxQEUI90PcU/mfyanvr5+WFhYe3v75MmTs7KyPn/+PGDAAJj15cuXkJAQJycnvHBOTs6UKVPg8mudZciQIatWrZo1a1ZnN2QwGOnp6XxsKBDev3+voaHBcUVgV1fXHTt2sKeHh4fr6urm5+fzPtWtubmZSqVyWwCXOBcHw7Dbt2/jRiSdQktLq3///uhKFkEAQSxMmjTJw8MDAHDgwAH+dt7a2ioOq5oRBBGKEXGjqwIGMpk8cuTIBw8efPnyBR/2dHR0bG1tGxsb5eTkYEpVVRVcpYkPZGRkIiIiOrsVhmFubm7y8vIiHPYGDhzIMQsXe/r4+AwaNAgAgGFYUVFReHh4eXl5UlLSihUrYIHQ0FBoNHXkyBFmb9KamhofH5+rV69WVVVRqdSRI0c6OjpaW1tDl1Hi3KCgIGjnhtPa2tq3b9+XL18CALZu3QpdJSFkMplGo02fPn3z5s3cbkOh7wGfzUSIhChHxQch3TcQxAI+FuIf/P39T506BQC4cOECXOYNAODh4XH9+vV169bhK30nJSWFhITk5+fX1dUNHjx42rRps2bNmjZtmpKS0rZt2y5evKiiopKbm8surN6xY0d0dLSWllZOTg6eaGtrW1RU5ODgcOzYMcBDFBAHETsoRroZ4p7cpSkt9fX1jx49unr1qrq6ur6+PkzMzs7W09MbNGgQ7H8AAEVFxZaWliNHjhCPQI8fPzY0NCSRSCQSydzcHE+vrKwkkUhnzpxh3j+JRJKSkoL7LykpIZFIdnZ2ioqKJBJp2rRp9fX127ZtO3/+fHh4OLQD7sph8ge+siIBixYt8vT09PT0XLt2bVhYmKqqKgAAmh1DoCV3ZWXl1atXmTdcuXLlyZMnR40a5ePjs3z58oaGhp07d0LDxg5zoRN3v3797H4yZ84cTU1NmAtNlqGpsZ2dnYWFxYcPHwIDA1evXs3tKPr164cvqY5AsMNLLOBAu/nKykpXV9e3b9/CRDqdXllZidvN+/r62tvb5+fnOzo6bt261cjIKCoqyt/fX0ZGBgAwY8aMyspKfX19jouJTJ8+vbKyktm5AgBgaWlZWVmJe3x3GAXEQcQOihGxgv+7vbS0NNiV+/bte+HCBbgK1Ldv3+bPnz9gwIDIyMinT58GBwc7OzsfOXJk5cqVtra2BI+2a2pq5syZ09zcvGHDBjk5ufT0dDwLrhoK/3LcP/R8Kioqio6Ozs/P37t3b0RExNChQ+Xl5UePHu3s7KylpcX3YQqVAwcOwKtgeLdXXV0NADAxMYG5RUVFycnJDg4ODx8+jI2N/eOPP6Dmqb29PSUlBQDg7u4+c+bMPn36YBh2+PBh6ABJnItjbW0dGhoKAKivryeTyfh9OcTKyio8PBx+fvz48YQJEwoKCoTcGAjE/4+KikpFRcXUqVOzsrJYhpPnz5/v27dPU1MzLy8PtxS+fv26rq4uHPYERYdRQBxECLGF/7s9PT09Dw8PRUVFaWlp+KQOAJCWllZdXe3g4KClpTV//nx5efnExEQ3NzcymTxmzBiCu72UlJTq6urDhw+HhITs27fv6dOnHItx3D/MCggIcHR09Pf3l5eXLy0t9fDw6NOnj5GRkYeHx+zZs/k+TKFCbHbMzZKbTCbDMo6OjgoKClpaWvPmzevbty+8gCXOxSF24uZmsoxAdA8EdvNZWVkAABcXF3zMAwDY2dmx9PCu02EUIDv7Hgr/d3tDhw4NDw9fvXq1paWlvb39//73PyUlpcrKSgDA3bt38/PzAQCWlpY8mudWVFQAAGxsbIiLEeyfTCYDACgUira2dk1NDd/H1Z0QmB0TW3LHxsba2dllZGQUFRW9evUqJSUlJSWlpKTkr7/+6jAXQuzEzc1kGYHoHgjs5tvb2wEPjt7E8OLx3WEU9FA7e0RX5ep0Ov3YsWOvX7+GgryRI0cCABYvXnzzJ7t27eJlP9ra2gCAmzdvEhfjZf/4ovsUCoWlc4sbBGbHxJbcv/7664gRI2JiYp49e/bt2zeobsQ9RYlzIcRO3NxMlsUHTU3NcePGNTY2sqTT6XSWx7mSxooVK/AX7T0abnbzkyZNAgCcPXv23bt3eGJGRsZvv/3Gy2559/juMArE3M6+G9TVXUGEHVUAS1G7uLhERkaGhYUtXbrUzMxMV1d3165dpaWldDr9/v37AIALFy7ghd+9e+fq6rpp0yaWB492dnYqKire3t4FBQV0Ov3hw4cHDx5k/y6O++d2kgYMGHDr1q2oqKgHDx7gM2J6BMSW3NLS0pcuXYqPj58zZ864ceMYDMbly5cBAFOmTAEAfPjwgSAXhxcnbnaTZWEfOO8wGIynT5+uXLmSRRXDYDAkfP3Dtra2Lt4JiQ8c7ebHjh3r6ekZFhY2cuRINzc3RUXF/Pz8GzduMBiMWbNm4ROeCwoKmHv4mzdvFi9ebGdn11mPb4IoEHM7+25QV3cF4o4qXLk2f+60ampqM2fOxP/9559/+vTpM3To0MbGxrKyMisrK3hZNGTIEOgxTaFQdu7ciWHYo0ePKBTKnj172Pf56NEjOp0OZ3IOGzYMXsqdPn0a/wCLse+/uLgYAHD+/HlYwMjIaOHChRiGJSQkwEeCRkZG3A6kwyPlG2tra2tra45ZHZodE1tyf/78+cyZMwsWLMD7q6amppeXV1NTE4ZhxLlYR07cHZosd+pIuwLxeYGzXgEABw4cYE43MjKysbEReGV6EMuWLdPV1eVv2+6PBVyu9+eff8IUXuzmGQzG6dOnTUxM4O+AmprakiVL7ty5U1tbi2HYunXrOPbwmJgYuHmHHt8dRkFn7exFFSMzZszAMKytrQ3eIldXV+O55eXl+I8qREtLa/r06QKvJDeIO2pTU9OqVauKiorgv62trTdu3OB958Qtw+ew1yENDQ0/fvzgmPXt2zeCDb9///79+/eu7J+Fmpoa4gLdH+oCpKmpqbW1lb9cZioqKviug6hC2sbGhkajkclk5niQ5GHvw4cP1dXVPWvY6yIMBqO5uZmXkt+/f2f/KWAwGC0tLYKqDEEQiXbYw34O5GVlZcwF3r1719DQgP8rLS29YcMGgVeSnc521Pb29uXLl69evZr3ryBuGWEtRS0nJycvL88xi3g5WgUFBV4kPgT7Z6F3m3vJyMhA/QYfucyIoRN3h2hqaiYlJcnKyi5btoxFJgylnH///Tf819DQcOnSpQCA/Px8Eom0cOFCKPF0dHRMT0/X0NAgkUiGhoZQQMINdl1pdXW1i4uLurq6goKClZVVbm4uLNnht/BSjezsbG1tbRKJpK6uDt9scdSnwm8sKioyNTUdOHCgqqpqfHw8TGRXuPY+KBQKj2+dFRQU2H8KBOvxLZ5BJEB1dU5ODuz/ffr0MTU1PXHiBJxeRCKRdu/ebW5uDrsl4B4aHDsqx2hllmsLXITNz7u93bt3d/2LRULPrTmCI6NHjz5//ryTk5O9vX1ubi5+RYUxaT3Bz0dPeEppaWlsbGxKSsrJkyczMjIOHTpUVVX1xx9/XLt2jdu0CHZdaUtLi42NTVlZ2fz585WVlS9dumRlZZWXl2dsbNzht4waNarDasBH9Nu3b7906VJAQMCSJUvgbln0qV5eXg0NDXPnzq2trd2+ffvYsWMDAwO/f//OUeEqjPU2EeKMYNXVsAe6uroOHDjw3r17np6eNTU18JXN3r17FyxYQKPRZGVluYWGnp4ee0cFXKKVOVHgImxkPITo2Tg6Ou7du7esrMzZ2Rlee3ZIUFDQnDlz4DXQb7/95u7uDpUhqamp3DZh15UmJiYWFhYePnw4Pj4+PDz84cOHLS0tzPOwOvwW4gIuLi63b99eu3YtHImrqqrgViz6VABAZmZmRUXFtm3b9u/f7+TkZGxsDAgVrgjJQbDqaoiDg0NQUFBWVpa5ufmRI0dgopmZWVxcXEJCwvnz57mFBseOygsCF2FL1t0eolfi4+NTWlp6/vx5FjULfv3IEQ0NDTk5OVzuoqOjwyKLZoZdV1pWVgYAmDdvHvx3xIgRw4cPh+NQp76FWwE6nZ6YmOjn5wdFY/j0VHZ9KpzzxbIIMt8KWkRvQrDqamYoFMrEiROzs7PhvzNmzMCzuIUGx46KQxytggXd7SF6A6dOnbKwsAgKCiopKQE/BVj46qbc7gLxwaZD2HWlOjo6gEkN+fbt2xcvXsBinf0WjgViYmKcnJwCAgKuXLlCvJWuri4A4MmTJ8y5fCtoEb0PQamrWUhLS1NWVoafmZc/5RYaHDsq4C1aBSvC5lO3p6mpSaPR7t27x7IMHZ1OV1dXhwZaiGfPnkmCFdbz58+huEKEyMjIJCYmjh8/Ht6W0Wg0eXn5CxcuGBoaZmVlvXr1asyYMbzsh3ddaVhY2KBBg7Zs2ZKfn6+pqXn27FkMw9auXSuoI8rMzJSVlTUyMoqLiwMAFBcXc5u7YW1tbWBgEBgY2NLSQqPR4M9HhwrabkZCYoEbIo8RgairIdeuXWtpaYmNjS0sLOQ4Vcre3p5jaFhaWrJ3VMBbtApWhM2/zWxvEgtXVFQI/Mkt/P2VEITUgPCykSNwRhlziqqqanJyMpxORiKRTpw4sW7dunnz5s2YMUNVVRUWZv7LshP4ubKyMjMzc8qUKSwBP2DAgOvXr69evRqG3NChQ/v165eWlrZ69eqIiIj29nY9Pb2EhASod+7wWzosAABwc3O7fv36uHHjHBwctLW1d+3ade7cOY5bSUlJpaamrl+/3t/fv7a2FgCgp6fXp0+fmzdvuru7R0VFtbS0DBkyhEdDOxQLQkK0MUIikSIjI01NTV1dXQsLCzn2Dbw8tyiAXLx4MTIyUk5Obt26dQEBAfj+8QIEocHeUeG27NHKEiN+fn7bt293c3MzMjLqeruRuD1RhZdm3Jyc1NTU4DTrAwcOMA/4xsbGGhoazEsqiD/W1tYVFRWurq6C3W10dLSOjs7du3cFu1sxZMqUKRUVFS4uLoLd7dmzZ3V0dLriJcZgMOrr6zvrVl9XV0egsfnx4wcAgFlj09jY2NzcLAydDLyIlJGRaWxsJJFIHG10OqSxsbG9vZ1HtQ+KBSEhnjFC0Dc4RkF2draFhcW1a9fMzc379+/foX91p0KDl2itra3lcW/E4xf/i5PBKao+Pj4mJiaisnIVFDo6OgK/EIPrxEsIwmjArptnUqnUzo55gAddKUuKnJyckBxnqFQqlF12Zf+d3RbFgpAQwxgh6BvEUYA7ine4f967Hy/RKqiLS/6HPU1NzYMHD1paWi5btiw3N5dlUdHq6uotW7akpqbW19ePHj06ODh4woQJAID8/PwxY8Y4OTmlpqb++PHDwcFhzZo1y5cvr6qqMjAwuH//Pr7oFALBDTSXuOugNuzdCOP8Qtff2NhYOAVUtHTlALs0kxOKhb99+2Zvb19XV4enQ7libGzs5MmTf/nll8LCQisrq6KiIvB/9cIeHh6JiYkLFiwICAgICAh48eLFtWvXulIfBAKBQAiJ/v3729rasnjF9ES66sAAxcK+vr7Ozs74oAXlikePHoVrwq5fv97IyOjgwYPwnTz4KdQdO3bsyZMnoVAXAHD27NnU1FQe3UMQkgy6U0EgiEExQoAAjIfYxcKCUvIiEAgEAiFYBCNXZxELC1DJi0BwREVFBc74kJKSUlVVpdPpPj4+cEETRM+ira1t//79w4cPl5KSIpFImpqay5Yt+/Dhg6jqw2K+2nPp27cv9Etip6CggEqlpqSk8LKfyspKKpUaGRmJf2DO7YnNJZhhD4qFdXR04Ks7XK64Zs2awMBA6LghQCVvN3D//v1BgwaRSKSxY8e+fv2aOaumpsbAwIB5tZem1nsAABSjSURBVP7W1lYqlRobG9vt1RRrXr161adPHwqFcuPGjc7mdgiDwaDRaKtWrXJ1dZ0yZcrHjx/3798/duxYXAOLEBQEZ6rrsdDU1DRp0iQfH59Pnz7NnTvX1dW1X79+sbGxRkZGjx49Etgx/AQu9n/o0CFuBaD56okTJ3C7SuEh7B8ZBoPB4uOKH357e3tbWxuPa9hiGAYL4x/wrO5sLgHC57DHTSwMLVGgXJFOp0dERPzxxx8AAN6VvHwfiQBpbGxcuHDhqFGjMjMzGxoaVq1axVLg5cuXs2bNgsuHQ3jvQ5JDe3t7WFgYjJbO5vICnU4/ceLEqVOn4uPj37596+np+fr1a/aThcNgMJhXF0PwCPGZ6mIsBAcHP3r0aNKkSSUlJVeuXImKiiouLg4ICKipqXF3dxfI2hfM533IkCGrVq3CBVfsXeLLly8hISFOTk5d/15iRPIjw3L4Xafbmkuw8PluD18PnhljY2N8Pufw4cOzsrLY5YqjR49mDh4o/oWIj8g9MTGxqqrq0KFDBgYGPj4+K1asePXq1dChQ5nL5OXlzZ8//8aNGzIyMqKqp5ijr6/fv39//nI7i5SUVGhoaGFhYVpa2ocPHwYOHMhSAMMwNzc3eXn5nq4x7X46PFN8x8KPHz/279/fv3//xMREXApGIpF27dpVVlZ28eLFuLg4Z2dn/qvOdt5lZGQiIiI4ZkF0dHRsbW0bGxuFpMXEEcmPDH74eXl5MKW+vv779+8aGhr87bDbmkuwCHcpajk5uZ7o8vry5UslJSWoRBw7diwA4J9//mEps2/fvoKCAt7NbhDChkQi+fj4AACysrLYPVrZnSolwYW1e+A7FoqKihoaGlavXs0uf965cycA4PHjxxw9SNnPL+Biw8ty3onNS9nNV4WHSH5kmA8fABAQEKCurj5w4MDp06dDNw/QmbjozuYSLMiBgQM1NTXwmTv4ubw9+1yJ4cOHX7t2LSUlBVrdi6CWCDZGjBgBAHj48CH0aA0NDTUwMAgICCgtLYVOlZaWluHh4evXr4dOm7KyspGRke7u7sHBwc+fPxd19XsqfMcCnAEHDQFYMDAwkJaWLikp4ehByn5+8TLQhnfHjh23b9+OiIhgOe/s5qWi6hIi+ZFhaczPnz/7+vrOnTs3IyNj+/bt4KcDLS+N0KMjCA17HNDQ0Pj333/h22AYUewPzQAAlpaWMTExZ86c2bFjR3dXEcEJKIBRUVFh92hlcapELqyChb9YgM9Ov379yp5VU1PT0tLCbREsbh68gM2Gl8ChVLRdQhx+ZI4ePerr65uUlDRq1KiEhATQGXfiHh1BAtDt9T4MDQ2bm5uLi4tNTU2fPn1KIpFYll7DcXJy+vPPPzdu3NjNNURwBJqnjBs3jptHKw5yYRU4fMQCnU6HDzDXrFnDMp0NWruMHj0a/styr0NwftlteHmkm7uEWP3IWFhYFBQUgM40Qo+OIDTscWDOnDk0Gm3jxo2bNm3au3evnZ2dtrb2zp07zc3N2Z04NmzY8Pbt28OHD4ukqj0Lbm0oEOLi4o4fP25hYTFr1qyYmBgXF5fLly9raGhMnDgRFmB2qsSdNjds2ABTGhoahFGrXomgYkFXV3f58uXnzp3buXNnQEAAvqJ/RkaGt7e3mpqah4cHnCXH4kHK8fyygI+jBA6lIuwSYvUjc+fOHXivybERON6O9+gI4nPYw7uUjIyMgYGBn5+fo6Mjt8Kenp4JCQnFxcU9RdshJSUVHx/v5OQ0b948Op0eFhZWXV0dHBwcHx+Pl2G+OA0ODobXPsz07dtXQjRkdXV1gwYN4pjF3ErEbcgHpaWlu3fvZjAY1dXVT548KSgo0NfXj46OJpPJ7B6tJiYmzE6Vx44dEysXVjGH9/PY2Vg4fPhwWVlZUFBQSkrKjBkzFBUVnzx5kpKSoqSkFBsbq6SkpKioyO5ByvH8cqs883n39/fnliXULsEeIwL5kemQ4uJiODkIAmfu4Fy+fPnTp09xcXElJSVQacbRgZajU6O4+Rh3DowLkydPnjx5MrdcAMDw4cN///33yZMnUygUKpVaXFzMsWRdXZ2CgkJCQgK3XYkcbkfa3t7+6dMn+PnQoUOmpqZQusSRpqamly9fMqesW7dORUVFoDUVU9TV1eErd2I6bEMWiHugsrIyhUKBfU9OTs7AwGD37t2NjY0w9+HDhxoaGn379nV1ddXW1lZSUiosLITzIAAARkZGGIaVlZVZWVlBy/IhQ4b8/fffPFasF0Pc5hCBx0JDQ4Ofnx88NZAVK1bAySyQc+fO9e3bl0QizZw5U1VVdcmSJRzPb3FxMQDg/PnzcCsjI6OFCxdiP+e/wPP+7t07AMDp06dhmW7rEtxipIs/MsTni91ILyYmBh7+f//9Z2hoCBMVFRW9vb2bm5vhVuyNgDcaS+uJcwR1MH7xuRkAv/32G/wcEhICANi/fz/HkuXl5XgziSe8hPrq1asvX77cqd3CZnn79i3/NesJNDU1USgUf3//Dkt2tg15OS8EtLa2NjU1YRjW0NCAD4cYhtXU1DAXa2ho+PHjB9/f0ssQYSy0t7efOXMGzmExNjbesWNHREREQUEBzG1tba2trWUuz+38coPlvBNkCbxL8BgjfDRsF2OkoaHh48eP3LJ4bATxjCDilhHATE742pl5HR1mcD1j179IhJw4cYLgKS5H5s6dSyKR4PyoXsydO3fa2tqgmSIxfLRhV6BSqVDkKycnx+xLziIklZOT49F5HAERUiyQSCQ3N7cXL17s27ePQqEcOHDg3r17+KNLdg9SbueXGwQCYmF3CR5jpJsDBAAgJyfHzUWI90boiRHU1WHv9evXoaGhAABzc3MSibR79274Ydq0aYCTnpGjpBTuqrq62sXFRV1dXUFBwcrKKjc3FwCQn59PIpEWLlwIyzs6Oqanp2toaJBIJENDQ25jrTigp6c3evToHvOwm1+SkpKUlJSmTJki6oogxBfeY0FZWdnb2/vZs2f19fXnzp3DJ7n0aFCMiBv8D3tnzpyRlpbW0dGJj4+fPXs2fFm6d+9ebW1tJyengQMHctQzYpwkpYC7My3Wk21pPT098/Lyrly5IuqKCIva2tr4+Hg7Ozv4fB+B4EZnY0FaWlpMVujtIihGxBH+no0CAExNTXft2hUeHn779u22tjaYOGnSJLwMnJLk6+ubnp6elpYmLy/v5+cHPdbPnj2LYRiDwZCXl1+1ahWGYXBG1tGjR+G28O308uXLnz59CgC4du0ahmHQi8TLywuW0dPTW7BgAc8Pe7nSxefjBDAYDGNjY319ffx1cS/D29ubTCbDqxmBI7zzguAGigWBg2JEJBC3DP+6vXHjxgUEBLAkzpgxA/9MoGdkl5Ty4kzb42xpKRTKn3/+OXPmzPXr14eHh4u6OgKmtLT0yJEjK1as4Li4FALBTO+OBW6gGBFPBLw4GfO7ZVzPePMnuP06DvMYBnhwpu1xzz2mT5/u4+Nz8uRJfPnX3sHXr1/t7e379esXFBQkkgrIysrq6+sz27IAAJ49e9anTx87OzuRVAlBTG+NBW6IPEZIP5GVlTU1Ne3Fb1s6ixDX5MT1jKtXrw4PD3d2dibwQusFzrTcCAgImDlzpoeHx+nTp0VdF8Hw9evX+fPnv3379sqVKxwXEuwGWltb//nnH+Ye0tDQsHTp0sbGRoGYtCGEQe+LBW6IQ4yAn+pqMzOz4uLixYsXw7W/menQd5dvOrVn4VWDI/wPexxvvJgT+/Tpc/PmzVGjRkVFRa1ZsyY3N9fR0ZGbzSw3Z9oeYUtLDIVCuXLliq2trbu7u5+fH4vfcY+jtLR0woQJT548OX/+vJmZmWgrc/78eXx+oJeXF3xUzh98m9Ai91re6WWxwA3xiRELC4tjx45lZmYePnyYwWAkJyezFBC48SzHPXcYI8KrBmf4eyXYKTqlZ2xoaCAQlgqD7nkt3Nra6ubmBgAwNTXNzs4W9tcJg5qaGm9vbzk5uYEDB+bk5Aj76zoQnJLJM2bMgCt0/Pvvv5cvXwYAODg4KCsrz5w5s7Pf1d7evnz5cl7WmhHUhuIJioUuIlYxApgWFbl37x4AYPPmzcKuEjsiiRGhrNLSm+jOI01KSho8eDCZTLa1tb106RLLwhPiSVNT082bNz08PJSVlclksouLy/v377vhezsc9pYuXZqTkyMlJWVqaqqsrKyjo1NTU6OiogKHvU+fPq1YsUJNTQ16qj169AhuCCcJz549W0FBAQBgY2Pz48ePLVu24BeCM2fOfPjwoZaWFgBATU3tjz/+4H1D4beKcEGxwB/iGSP4sFdRUbFo0SIAALw69PPzg+t329jYMK83Nn78eFlZWThaf/v2zdDQUEFBobS0FN8hDAF8pUkDA4MlS5ZgXEID3zMvwcVcDZYaYhj28OFDaElIpVK3bt3a9ZZBDgzdyty5c6dOnRoSEnLixInFixeTSCRdXV1VVVVFRUVRV40DNTU179+/r6qqam9vV1JSsrOz8/b2Fqs5aWZmZgcOHNi0aZOUlNTNmzfx5TagDLSsrGz+/PnKysqXLl2ysrLKy8szNjbGmJSj+fn5e/fuxc1IR48e7ezsrKWlBZdq3L59+6VLlwICApYsWTJ8+HBeNhRlW/Q0elYscEPMY+TMmTPR0dGtra0AAGZ19YIFC2g0mqysLMZkPHvt2rXx48fb29vn5OSsX7/+xYsXV65cwZfuBGwutfjgyjE0Fi5cCLN4Dy58z8w1hPrvAQMGREZGPn36NDg42NnZ2dTUtCvNgoa97kZeXn7Hjh0+Pj6PHj3KysoqLi7+/PmzeM7C0NTUHDt2rKam5oQJE6ZMmSKeelsvL6/s7OxJkyaNHz8eT0xMTCwsLDx69Oi6desAAOvXrzcyMjp48OC5c+dgAWhGam9vHxISUlpaGhERsWvXLug4CgDQ1NQ8dOgQhUJRVFS8f/9+VVXV8OHDedkQ0Sl6UCxwQ8xjZOTIkfPmzaPRaMOGDbO2tobKMTMzM6iTBgDA2yyIhoZGcnLypEmTRo4cWV9fv3fv3vnz5/P+XSyhgad7eHjwGFw4zDVMSEiorq5etWqVlpbWoEGDoqOjExMT0bDXIyGTyebm5ubm5qKuSG+AfbHHDmWgxGakwnAxRXADxYLw6FBdzYKpqemaNWuCg4NpNBpcTpId7P9a/uLwGBodWkADnvXffIOGPUQvBJeBQs0MlIFyvHTlaEYqKBdTBEIMIVi5+/Hjx8eOHVNVVa2srNywYcPx48eZc+Fq4CyWv+ywT7DvbHBx1H8L0M+2S8Meg8HQ0dExMDC4ffs2tzIrVqx49OjRy5cvu/JFCESnwGWg+fn5mpqacDE8Yhkos+MoVPjy4WIqIUJsRK/k/fv3cC7006dP/f39w8LChgwZsmnTJrwAjUZjt/zlZc98BxcQjp9tl+TqKSkplZWVd+7cYVdB4rS1tfVWdQ5ChHBTbcJ0bjJQ8PNSlF396efnJyMj4+bmlpub6+bmpqSkNG7cuP/++09bW3vXrl2fPn3iZcPuOHIEgmc6VFcz92oHB4evX79evXp14MCBx48fnzVr1tatW69fv85c+MSJE+Xl5fPmzSssLFRVVWXenCU0mBP5CC78Sznqv7vaLNwe1FpbWwMAMjMzCTaeNWtWamoqAMDT05PldhjH2dk5Jyfnv//+62JFhQcvR4rofgRyXhobG5ubmwm81liora2FhRkMRltbm4yMTGNjI7w+5XHDHg2KhZ6FSM4Xg8Gor69nsT/kBb6DC9LY2Nje3s6jtx9xy/B/t1deXn7r1i04/fTcuXN1dXUsBT5+/AhfWiIQokJOTq5ToxFeWIAupghEb4Ld8pdH+A4uiAD9bPkf9iIiIjAMW7ly5Zo1a378+IFPDQcAFBUVmZqaDhw4UFVVFdoPAQC4mdCSSCQpKSk4a6itrW3OnDlUKlVBQWHZsmUcUzhuiEAgEAgEL/A57LW2tkZFReno6NjY2Li4uMjLyx8/fhw+L21oaJg7d+6bN2+2b9+ekJAwYsQIfKsOTWivXbt2/fp1KOWpqKgAALCncNyw6w2BQCAQCEmAz2EvMTGxqqpKTk5u8+bNu3fvVlZWLisrg/M5MzMzKyoqtm3btn//ficnJ2NjY3wrKEJMSEg4f/58WlpadXW1g4ODlpbW/Pnz5eXlExMT9fT0AABpaWkLFizIzs4GALCncNyw6w2BQCAQCEmATwHDyZMnyWTy+/fvIyMj8cTQ0NBp06ZB2T98jMlChyJEOp0eGhq6devW0aNHnz59etmyZewpwlAvIhAIBEJC4GfYe/ny5d27d5ctWxYTE4Mnzps3Lzk5+fXr13DN0CdPnowbN45lww5FiK2trWvXrrW1tV26dKmrq+v06dP79evHkiIM9SICgUAgJAR+hj04meX3339nTty0aVNycvKJEycCAwMNDAwCAwNbWlpoNBou6WeBowjRxMSkoKBgyZIlOjo6+fn5P378OHPmDEuKMNSLCAQCgZAQ+Bn2zp49O2bMGBb7RGtr61GjRp05c2bPnj2pqanr16/39/evra0FP9/PAU4iRHd396ioqJaWliFDhhw4cEBeXj40NDQ+Pl5ZWXnnzp26urrwISdzCgCAfUP+GwCBQCAQkgQ/wx43NR582QYA0NHRSUpKYsll18UbGBhkZWWxiBDfvXv3+fPnfv36UalUAICtrS1LCrcNEQgEAoHoENEvRS0nJ8eSMmDAgA5TOG6IQCAQCAQxXVqTE4FAIBCInoXo7/YQCG48e/YMrq2H6B6ePXtGp9NFXQtEJ0AxwhHinoyGPYSYgn5/ux86nY6avQeBThY3iHsyGvYQYkpISIioq4BAiDUoRvgDvdtDIBAIhASBhj0EAoFASBBo2EMgEAiEBIGGPQQCgUBIEGjYQyAQCIQEQTSTU0IUIUirhEAgEJID12FPckYCpFVCIBAIyYHEvkI0AoFAIBC9FfRuD4FAIBASBBr2EAgEAiFBoGEPgUAgEBIEGvYQCAQCIUGgYQ+BQCAQEgQa9hAIBAIhQaBhD4FAIBASxP8DQtV/SNcGr9UAAAAASUVORK5CYII=\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"execution_count\": 145,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Image(\\\"ccp.png\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mentionnons une possibilité amusante, actuellement non intégrée à Mocodo : [Svg2Rough.js](https://fskpf.github.io) pourra donner à votre travail une touche finale plus informelle, dans un style « tracé à main levée ».\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 146,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAnIAAAB+CAMAAACXrQz1AAAA+VBMVEX///8AAAD9/f0HBwf6+vrv7+9MTEyfn58NDQ0hISFISEjn5+fd3d04ODjQ0NDY2NgsLCzGxsaGhoYmJiYXFxff39+urq5XV1e6urpAQEBERETV1dVmZmbs7OyioqISEhJjY2P19fVpaWlgYGCTk5N+fn56enrj4+P39/fCwsKQkJDz8/Orq6txcXFbW1uKiopUVFS/v7+NjY2ZmZlRUVExMTF0dHScnJyWlpYpKSnp6emxsbGBgYE0NDRubm63t7c8PDx3d3fx8fHKysrNzc2mpqYbGxvh4eG0tLSoqKi8vLykpKTa2tqDg4Nra2sdHR3S0tLFxcVdXV05thBaAAAszElEQVR42uzaZ2/aUBQG4PdcbPaGmL0aB8JeCVAgzLJCSUn+/4+pF47VFqmVoHFVP9+MEEaHY9/j9wKLxWKxWCwWy7+OEwuwWP6iI8VhxBUWfMZT2tx8DaT8X5ah1/ZzfDoSart91tHvDsRKMxwe3xXnvfrkJZ2/bcRiD3a7O5mY+Z4eg58jrnU050wvYLGcE6AtGP81NOqHJ7GZy0Z/wObMrV2R4OOTL5F02x9ijdv8p0m916AVLJZzbijhVvss+uhuTMaVQdeR3e9qwmgaf26XQ8sv/lTgq3dT8niGmQzPL6qFwj3HMYazvDSCxXJOich3e1iFPAyXkqIpLJZzhpTFhfmpDYvlHJ4cuLAQvcJiOadKXVxYmZawWM65JxEX9kx+WIyGW/zXPAEYMOrgwqYUgMXoQAz/HMa4+0J1wfOZoUcKajebksSjGA6HGQmvWPBqkOuVktyjEuWW2/H4dCuFuSslzE3hzQcjauLCRuSF2XD4SPUoTI7x3uV0L959arkTvmBk7bTRxRRhT8KIDj+eHSgx/GQ3rbwlffZiCDgWoOHxCzW6gcm8kjgVdtn+oBIeF3sv6bfYgzsxSygJdkuOsNNyhj0v3o0P4WZHHHT7Uji5qgnCaKvEk69yPuk/ygnlzaYkJZRyPskxrrDIDEs33kDKvwxJ1/Z2JJ3EIZ2lEz7cFXv1l/RtQ9qdcVMQZsWF82LdHiGVMzKTSiJVRC6IVI+xWg1HdlWT7Ha71Wq13++zEoeiL9FrNY3HT6UyVKrK4IvByHaHd16x9Zbb+WkMlfDgTtob84EHXjrx1sjNoNhSH2y2nrVirYdWflKMQ7YiD8wlo++WRL+5PgfV3RL5S9vd2l6dsln3LRrNOW02uqic6ylBSZhVkYhciUavs38+ehiuI/IJRs4idCuS1beUPr2XVDPcEDXEkdBJ56sdojAUewqCm5FuDVmWhjAZB+0XDL+PFeT5pKTMJym/NqA8KwPKaUIZDMRKRRz0tb2a7VS9wpVboXx9yzfCe45B5ovBrDb0xHBtufm5Q5EoLeQpL9ALVDfx9jdqNos1LCgHTZ9IS94CRPfgUu1pgz7FhWxXfdVBPEymTF/wgSJpmFYwj6ujMIzW9fffhQSAZQMrmkDnog0kC4pCI5CN1hlIGFEJsorxQ7tkun+SxCmFD5Sbw7RcL7i2Aokwck2gqrqof1qG6tDZKAOJhyLvv19jTkkOkigFtLW0B92ATPcXvA9+iKYwTCvaw7UNKfvr0a5ISQZFl+bQkdpAAcodXlq+tTOLZ8ozt3ojfKSjFsXdQlchDiazoxL+lKnj9sux3eHavCTAKJjWV9CjPtONccKIGCRb0mxRpjT4iBKu+LQFa0l26DrmCz4/9okmQw6YFoVxbX6Kw+jx9lSXHIOqSR3otJaL05NjuvQuAKXlELBRE0hoLfeVfNA1CWbT/3m8ZDirevZYtwhAwxUAFMoMJ9690HvwJRtdHpoN1WBWHFWgWdTEQZmDZMOzc91Twp8LUQhGTw0o2pSE5kAD6GzqMvn+FCsvrEoPUgVJbZYrGcPOsPlaTqR7/BQ/KiUMJ52RtxqDLPC5C8mrLYwfj3XdNiQsQmWoHr9zd6Z9iSNBGH+ehDNcQYKIIKdccohyjKhcHjiOB67f/8MsdBKM9Di4v9UdZ/+vbAYYUlS6q56uLuZ5wMPYtQsmOVoUYBHh191jdZR1JLhAvwJGpNrNiOtZs9ElWbiHxVMrD0FN24sXNU1rF7a+SzqtcJUn2Dg1owjpFv9+qJSd4V7WjOUaHL2kD8/mI+x4GLSmSP+XdrljKpDkRyEsmmjCvgX6XML0PgXyWOCl3wo3jFMIZtwGDJLGgTmTpqmXr8fecuLsTyggdCz6A+6PDKop+LmklwKwZqMMF7SjEDzyEoIifzRocSTrtNheS94mbQgUP5uK8tQmbwocA1AiYXOWq+frwA+mX9K/hGV+0nqzKlWsOFfx1dgiIMmPwAE5+nHztJ81AxqDDAOKj4xDGgsiKhkwb0R6FMveD8Cc5wPSJ5ysTC/kheWrUuE1LPwqoBwygSEjkZJBNQys2eiOyRzJhBAx2vadlODYdbTzwMlJqXwq67S4YwBOkt3VeklfllTv0OK37ydFgwzsdIdccoIUY0/xYCRcq+KORVsNIQN/hMstP5IkPyJMNqyHsgDiJL1i8eAO1scC19D+e0CVx1bkWgD8DChHGtk3Xe4PquZyZJNGFoDCGTReAq4cdQVrNrrlCHuHPs4iADy2y3WFTW7NSELSaWWhdtcDi5qfzBYrQJ8CNe1qWXuT11B0mnyDlyX7ne0lx+XPYUXp67lc2QdI8iN2V4bx0Q2ckcwBU5L7gDQW1xsrm68J8bvPdL4Mi8BAiDDfhIuO2PiDqrkiHMNCjYkgwIOkuEVcPsbXbGRF9IEhB3WHyyXFCtsxtVlJp5UlDE3DikDc/BjaJDHdr1WBvR/hUwWCYL89jOnDbgWBURwWQduWivLq+/1q9A1Akh9T9F3ARGcKKDHJGRSDaRYAeYy4yugOhb0mDNao3gv1KAHovLGcNI4WW9Oipvv0Kiy2v2A1l02YP1a5awiB6xkziPHGvNr4uo3OTEtcJDkCurbL6bwHcGDORLJOiwfiFR4NH8KXdrnRHJDkx20+w0RReQH0eKYyHmU2xRAgj9Flv3JNVRE3dhwdzm+AHSaAnhXtacygR5NB/msI0b/mkrWXcps5yaYI3/dS+1lqko3sgo8oDaBte6vBPREvHzre1fO2Q4jyuf+9yxX8gCQ/bq3WjDgNIEC6PbxusqmQeXmMDk2exJocBx7pr+CILUC3nOqEBYR43jhKBVxfRYjeVEl4uTIC1ViiBrhoknNLNjJnOZFS3SBnZR6npnR7bLqcrNOKG95JNwn8DpdTItslD/8lheuggneQHgCS/Hi4Wgn6LAIZhnDAXJZRhFiTxykuMNpDes2FFXDtMhb4i8+A33KqfZYxYEUSot3YTD665eMKdaZPdneTyeQkFAoNlwV9uj4YxGL+BfPZzDCMbDZrGLP53O9fPJpV+QpjK/5PD6qkbE3CTUEUso1u2bSnPDceLB87M016wgdHHqzL1l/Rnny4y2WxmfCQH0PCjc0UdUCSH39Qr9rSRwp4ZFlkpzMFfW7J4wb9O6dARgjhIZERXISof1+Os1ZO5uEOYlKF6gnr7/nuP5q2G5sZMwWTK45gyw+NJKl2FGDNRl6WrYUzBOyIlBbICTXZziplnRatIV6RCP0Gl3NtcZYL0Th2493Im1TVbY0LLrEJcdGS/Fj3s+UGkMqyKCauMVyqEDoanEhjpccTK+lwWfkG4O5RZQ5QWTV9S73AhHFp78OFDQhtoNhwi+rQwM3909VfP8bb197OonJ+2iwUE57dyXDgN3w+w6/3QkmtmyimR/3y+eHBiTfTOBv/qF2GU8GbgLsuykIrj1zwrGATZ7xfuVwTAoUEUhr57MKajazd9z2xw143eGDeKxXz4kv5uguyaIZ28ve7XL7LRI7ZD+gzFimQbEBGvkhJfkSY9OVKu6QnL9aKOOAhr0RY414fR+mrWz67A8wt3eN0IAJuslQL/tUnx0CCB8FgJFUL/oM6hyrJhzw+FKVMbk6VG4yvuxxIBVAeyOKajXDMYSbydKczWRVpEbWtnMoOUH1MZrnAyEN2OU17YwL472I5pc3nGcsX+AjiGnmy0eUmgCQ/AuEkSXE3A26hMV4zaSq9R+vjMx7YwmbG3AYUVHSeACGadEQibJJ9/w6gQn5GUuvyc4MI7TyoElxlCn5Tbd3JetZshDFNBnvm7WuQ9B2KeEWgDl2yTit2G5wUe4DiyteXxxUr8aA4ixiN1o6sk4iizP/g+HDrwWwqVyg8jpr9/rRcLi2PQ20dHh4vjwAsz0R5M5m769vGdleNbtpk91MP46NokNt4G3lqD8RhoYSvj8duCLziE0WFzWoFtzSuwCKiAHf7sHDVqoCykwv1PNOIeM/bxCQ20JPX79+OIangMzjhpmTZyz1Y3Cj2H0EIXMq6jbB34NGTreuqbb+boyvzVZfRe/EcWaeVj34UZ7rKTaiqz7fMj5bZkUiZRMbk8/nUJfLT3fgFQZLFPD6OGmV5X0rLfxubt2OmpILPYSS/tZxNfzZ6Ea/IzdqtYvqxOS09LELRb967RSy6cxRdBKP38cqpiEbfxfJs94WYKh/VU/yKNjn9WBPvyzfzh4mPnx9ppMg9fBIKWYLMf3hqQD5TiJwOiU+9qa/IkYKPJURV+bouNzU2eEUHn0Z8w934X5wamI8klfQj2Ry6hDhRHEWom5GLbd2Btde5N6QQmobfxOb+ELfS2vdGOwQFqAYgYZfxyl0VBAkmNlUSfi7yiZ5CDCauunMq6tXE95zpyE4ROPs3LndBVl4VoVrEz6uwUP7qHHw/hUlg+zBzqbwqtr1Xydg0shYn17+sy43m+AW0tipfCmtft0Nw1jG36bYVkIb1R+6bs4zX2VUBglOyuqGS8LPxlX/uckqMTHYUCMJqbM/MidUU5Gi3iuhuHDJVqXBA5oTaWhGqoB7jLUxqPdJW2+pTLukpzmLbBgVbeCFP3uFthlRfwxeWQ5/PsXs00PVebzgMhSbLriW7mubxdLvtdiLRahWLuVw6XXhcZO128Ju53f6+iH2vwpFgxRRiJR79eJuUPcm9FNa+bofgrGO2ywdQoQeCe07gKON1dlWASZbjDfPDe7swiVDdarJkdlmyuhiYbVvMZiSiG0m8Ugmcmp2lqy5FPf/5jnedfo/KYtWUO7Nxcw38VoVEny5sq2FI1NXM5huHDK4VoQoKtJXIDJnc8p7nogDcSRpp735z+qryccxifVsjy3ihRA/eJukvCc4tHpZsmTycl0rl8kIB6jebo8fHQjqdyxWLrVYi0W53l78woC33OicTe6tTbHTO5zPjje5EquHvTbREbjR9OO5ktse1SiGGt+nbl/FSWLvWDsFRxxyz5bswkxA8cQhnGe8Fs9L+wuSXgbdnmNTarfRoen64dW4278k9J9rdZbeWYU+P+Wc+/kt88Z/eggpzuChaX1w6amrIaUBmJMRpyLjZ33zCi1wvQrXLIUNYEiCPHNO+VoXA6XJR8SmjPu68mizwNpoHn4C9O5W6ih6Nz24znf3Dh3L/MdeyOmZZe+3+dAxvQ8YdYV1BbofgrGOe28Ltpe1yVwzBWcZ7QUM6UMNfZtPTVlebDAfzrCrEMEP8rkJokrR+VsHZkmohwHYcTVjsPktPywlvqeXafeVur+1fCRGKLrULOBn5YaImAMVjXpMZjQb5bc3C4QsAj4TAft7FiUuJVoBghOlUYFNESq4XoS5wG+yQeWFMpxDvYVOBwFlsW2PbXKKbeGGTy/0e8oH78E168B57mIW1cjsEZx2zwdM1lzuiB84y3gAl/yY3ZNOfgdw1U3Y5hUXxbXqBI53ZQl7Z8nAW67qw4sZPti+QJuD1wH4evvNMJ69SXGIoG/Jucr0IdUGTmhKiObXOyGRxa0exOu7M2yNvHHAW226zYL6oiBfIL5s+5PR3uZxdWLvWDkHUMTuKwQVXtsudsQhHGa+jq8L7LNOc4bNxcf/n6ZRbzBnn9CJMNa1zf88g55NnF2xcPbX0zB3kCORU2M/DmGSBU+UwzVh/H9hnfpOJnUWowoBqJKxZm5iVcogLhnERUyeyXHAAZ7Fth+f5yrhN1v5nLmcW1q61Q3DUMWOVfYY5WZ0ycJbxOrsq2JDKhmz6c8nz5Of/Z5x/U3clWqnkQLRuutn3fRcBZRFEUVFRcEHccPf/P2ZIIKSxhYZ5MMs9Z47K9LNjdXVSublVVbo8dsNlowQqtnfsUfUaNTLgBS9EOaKSRpTI0/S6J/73tfm0h+3x8lC3NrESoRJV2uBQBFK9theVulLmbXwDSaPY9g0C0Qb9P1yutKTLCWGtqRwC1zGbLvbCJXcfB0YZr6qqoAAl4LPaTZuxiaL7+x/yveF49xBph0dONHWi5KwULS0SicfuZnep6+65d6R6fN5vWh/bAUqEOsGJmNVKyJOCxxjSneLdKLYtg8NetY5YzAkeOV2dO28IeotMyglre0hhrakcgkHHrENTpJBOHEF8KRmvqqpgxBw5ieLIrHlZa9QKC1qLnP2+mPvxAGhxseLBLYafhPgi4SxNPOSBKNVR152hQXTDzRo9HM/1uYUmZkqEKhnB8qdOFBX0iYekut5L9b4Mq9+NYtsu9m+dgNu7vMvJp3YhWdZEijaFe1T+pss5sGsuh2DQMffxoM5w4sInkGdGGa+qqqAA1GguskGy5mWtUVeL54SzrVq7XAA7j2UN27oO193YbYezY/24IYF0hCjdoel1e9xV3FFOtdmtawUD+g9F4CXyYnwJ7PAfTif6wgdGwWhATIguxI1i2wPsUeFMg9PwRrDFLicdLIbJ35/YXA3tHVz8HZdTwtrZcggGHXMFPfEMa3XaQadCxFK4mpXxDs3EFnBtsehb8bLWiCm34pyt5GiNNSjMLufFgXi4CTpBOJQ8xBdNYjlvRbK1b/74zROf0MTCKq87wiNRCYwokh6/nY80HxoKP1zOjaNJrOgT6/vN7nH2Q2TFN+HcPu6mgaZuFNvuQagCO0DGeMq6jHgpB2iesdsOaUMIo7C6yxmFtT/KISgdcwa91v2uD9inahD5/XAbndysjFdVVVAWX1SF57tH1rysNTJ4pimY5GgXu1zBi4NCVbcdOvWLNABtl9E9/GKJi5CAzccN8kknJ0T7aSJ53Ra8RG/81XY1rUtW5mH7IUINRsefFB74UO7z4Ejd8cEmwOHs6jNi2+fxLF4vGRb+yiKXUzlFVUTRHPt3XPfzP+qCKreMeYlY3cxBSgPSrpdiVXHK/vPyAuMcrpdiAzb+mcoQd6ou5XJqdlbC2h/lEJSO2QMBoW/tZ9W+Xsl4DVUVLFxOSfSX5WVDhslyrKtg0qr6AEnyCKaG/w/F0aoimmaXO41yvaUsVR/94AR0B+5Ec7t4ky7vhoWWbrcYvhzWki1e1v/Rc2HzX38yokKLW5p7ckv42tMCwaRiM5UItd+XM5UYI/PG9+LyN9RD545h/YfYloV0UwORAJy0hGEZsrtoiEG+PMMrdPgO+H04PNJwTiYOko6CWqlKOex1kb+MwM1mLw/54LyqMpzuQ/jJ8QcivShRzg6k/UuQJLp0OSWsNZVDUDrmo5S9+NbwTmzjT16YZLyqqoLFwqpexmV5WV/n9KGzRXT7/uSCj8hWyj8c88DPB42ffxz2iAo44pyt5GgXuJwC453OZfuM61ry+rJxz5tnHPDeGVfZ0WGO3Z2+8fGzN94kQXZT8ImRqXJi8/GwmTxiP9pLZXihqPucFWHbAx4ApIJ0AB/yQASamYPswhnFLb2OL9E+8DRzeRLO0xRqBOAkEuVhnNZ0IUh6EPYT+JZwuQJAGwaQtAg5luNlg4JJ9dMJEPUhV20jAoTIC7jTQIDaPiIPwpyzlRytpcutDpk24blYuuJ9dDMS2BZOyAzz0oZ38mptG4XgOEWBuJ2OgcYBuqyL158cpAfteiHVGX3FdwapCz8OjJdXP5wxOkCFAdvsCLaC010n24OPGnAwh+ZbQpJY/ydcrmWxl1+Ol03hku5wTnYUWRwXfPnPcA+DlyiLGOUPibzY4SSa5GjnuNw66WfrcmrMuZlZ7gVXS/H/KPJYMF0dYOsWutjxvOCAHPBSEsOfHGScs5hh2PrwVW04Iqa9Gy8f4Ej87zrgpWN4P0Xw405R0dnoIRJYwuVs/4TL3VmT5Na8rNgyMi1L9ocCsRYl4CGKnIz3jA54KNok+oSDXyc42rkud/WxbpJ0sOitcgARd7Z7du1fb/ueI4QXTMSK8ERWnM42/bg/QJ0o4qYzfFIcA8rA8ZOD3OFGdyCWwxvpPFjrzFweR5KH+P0LJPi13jGR6b4hN+By6Ipu/Zdd7tPC5ZbjZQ+jnClLkd1HHDf8x3SPcCoea4XaJyRsmOqQ4GgtXG6dJGlmUezQb/dui26D9lFIH7O3ZZGyyKWPMmNRpCwejQQzImVxmrPYGCU6nh3v7I3EXeXb/ffiFDtxngM5Fs1wzQwXf4lfOlLfJFwyRhPzPWsijWcHX0g7aeIkzxeeKIfdnxzkJc6J7ND5ekH5bSK3y3h5i398j5gXR9zqoQBuSRzElMAd7tVr7XI54PlFDfqtO8ndzG6XmolpQ7tyeSweEtqh++dJN7uvkD/jreT6VUaLgEUUZNpOy/KyJSdRBSXpck1UKIdvCn4w4lM8udvC5ThnKzjauSTJlWvdJOkrLhcaoOPErxDqXJG7+MDVuR2uzlXiXIODfk+0uVfcQW9lSq0/JlsJThWpBV1nbCb7oD8OMappID7EfiPsTFMYHgrAIfZs/cEMB+nRPrZukaUAX2CDbqIsmOHyCwRrAzu2XrFDXFDDeti/3kaU7nFyHepq+0u5nPHPF9pkVyQihMm8AI7QhIo0znyep3DOMV3+I9hL2ROl4ulueO94q/E0DPkDMY9NFxa30Vyk7LQsL1vCaTiKa+lyL7A33EjSAdzxPQ0hKuJlq4izycIaSVu43DpJ0kecYRHc++HjRstfKRAH6z9+1p7i9w4ucNy9vSqWeONKX5sX4Mg/RIK9m3EBjvf9EVVztHMssh6HE21gJuCNjXvPppFcpqShZzKT9X3IsDSEMPQZAfLweaqTond8znCQ9wB6F1RHmCjV5vSjx3j5Dr9Kc9v4jxmc0WsQgE8j2gUAe4U4PrPRRiPOodpHirG/jt4PP5DJ1XVaAazaz3keR3Tv3bhuyflReJcLQ0dm6wVdUQ0zcH4Adg43lzenUyOId1i8woeJ/Il0DCExWsTLlgAgPM1DZwmI7FA9C6CtDSkm7rwjOFvJ0XLY4DBJCUwkqWT5FOu5CjxwqI6kRSFqtrtTnFjpuD6i2ExF+jRCi4SIeZrgPEYC4u/yJ3N3T8RajHTfJdFXnL5OCyTAao4v7gix5xb/ZGAjeisS5Q6Y8XKKPQ31QI1CfB6Je4h0f7IijokvvkJ1FcsZCSjuLZmRjParNkw+xR1AnNYMve+JZe5q1/Gt46O32yugVqt9fYVCobu7kbMP/H7/gKt4v7iMNzgNuQLVKdf5Osww7gnjhOQ9h1xYK37+d3ol0x+6/5w0F/QzHpnXh3dVB7crCY527hlr0WUmSSXLZyJJLaBuMR/YzI61h8wqyct67vUu+Xz+tp8dTar2dGr0PrgeeMpNlPdrvUm7TzgJzksb8XXq+TJZuxMLVYH9OufEAp+DUC05nqxHk87tfnG7WZLrWfbf3j7QHFj07WQ2+hHL/S30cWxSr5hIUsnyGVjPtbWs2lBqemfhkcfuxFrsvORzwoD8aOX2TWT+2eIoaJfL+kfUiRWg6hC6E9nT7tHxffy6xv4rJMmiV7WpxEv8COCVvzxfvIE236adj96f7ugFuhq9QYkoRq/mjaFTN69OM9Oo+17kRAyrFhLNbMRMkkqWz0iSLg+Gg4UGsNEGEEFmiQICTEQ3vubt3k/siI2x2Bk7tvjemG+Oefh1efn0dD2KwZLDYas1WqBGiTVx3vP7nvf7djjO+MlMt8yntXH39F4wMnJXDUFmEAj9y1QwzUf7e0qXjEJn1/QN/OZz/ChvUoTPW/e8aog9ejcQiTVfohtyPP5sLJKkNtrNisUUlO2YSVLJ8hlJ0hWgdRcaoE4bQAeDpbI1WYz+GSiP2/iBVz9RtnQ56w7AdWbwkgDNgr1UydZ4VbdbAQx7JmLeRJJKls9Ekq7W8ZZdyLB5/EXJ99eP3nT7oOvmZm9vmsp39V0yU8b3ZlFqq5Epa5iO9Uk/T7gi23GaAzXWgr2hfhEVfEhauNz8x9HJTo+FdpXCshs1nSg1iKIJdbs/WfW2g2aSVLJ8ZpLUGqqr8HUeDwNBUfi4oeKHShW8frjlkUft4Ux8Pdcyv5VBKAHoNEwZ3xvFd1uNTFnDJC0dBIHIB1CeYyA11pwzzLlYu9Tlv1gsrPMfh6qKpONKKSxNGRFfiBPlE/J2f9Z/s9Q2k6SS5TOwnqu3a7dhz7brYmLqPBBMPpMG2ABKuJS6ubNJLnbgN5fbxuAGOGWmjO8NotlTI5u1htEetrzojeV3mh6peaxMvGV5Etg6sorl5j8O1XS8in0VErxHaBY1bl5nU93uTwKt77aZJJUsn5H1NMFq453scFbYL/aLWozID9sGXa482RaxYUo82Is7/DrLZcGYQ8PuhOCYURPaGG0ECZ8a2aw1jPa4mqSJfyE1rr3EvNMx+p+oXysYx0o5r9sZeJVi0EUAFjyOB+loBeOLV+xQoW9Mjx9yNlUrydv9WRmcZs9MkkqWz8h6mmB1btctEjHtkj/wRDHNKAbPBl3OMbVY+3kyH1R+60pchE50p3Hb5741uANSTSgTwTeAwxs1MoM1fub1RgpSJFTp40j0YZqMkUrRpIZgVY7V236lDji+pBh0AYC5j0PF3VSH+G6cFV/Ml4C0R6XHJ3Eton11u5Vi+41WRFeyvwTfGouw6eC77tojDyobdLka3DKSvJ4cu/V/c7kr6CIadpPtA4krXEk1oUwE3wDsKTWyH9ZQ9mhNCdNj1F6xw78GJmOkbSBygpAc6zWGlHz/wNWuR4pBFwCY/zjUDGSD+G6cFV8EEqLEiUqPTwpOQ95uJTzsb9Tl1FpdDhMxtMTfSHe4zG10lnucCtEneV8ZMKPLqdImVbH2a2wfDhKPlrBNKhF8A3C71ch+WEPZY2e65b7G8xcaxDdvcowlRHNebMmxNsS1WRApMeh8APMfh4qzKgjTNE353ZnhLh83pMe3OHMrb7dq4daNdrdRBxr3J0QxkXkTbhKdI7lRl1M7P/jFl4H2a63I7Pi7W1RcPe6XW1JNKIWJG0Darkb2wxrKHmdTleETtkKIE3WRk2M8AZ+W9uRYt+CXFbCkGHQBgEWPIzxVkuwpJeZ+UET33alV4vgiHacWt7Pg/kzi94vaMMBoBjtt/e+3ogxgaEv0RMCc4A9ZQ26DLqdiIi3OxLE8Kr+5XAljuzpFxlwML0JNqISJm0DqRI3shzXUuO9QJvJkvdyVAgG8CNWKHGNas1EFR1L5eIyMeG0KJMWgiwDMfxyKM/uUCztXWJ4Gx0vt1CovGFAf5QW3szxUM4vfWR6A73U2IfP9T4oF7wDRDNF37JTTjazk1P8Bl/MAqNFO/BLQCr+43KEYW0Y7Ib481LE3URMqYeL64UsYR6asMVuJqoNPGuDhMQ4Xy40V7jk5xl6Pe8CtVD6eCZfrwkZKDDofwPzHoU9DiZDMROUKy3JQzKUvU6vwQ4ELdNXtVsHN4e+BRh37rbLmqhtbdZ4wWh3qARe8jGgQ1b1jR87Rpl1OCumrPBRhvy6sdu1OZyEXQmSH4/UA9omaUAkT14/et3Fkyhqz1HgIzri+jzycAWKaL35+gws5Rp48xdAUY50urF1ckBKDWp/imh+H8cg9icvHWjjVY3xhLWvdpyvtozC1yg5e6REH6narx7Lmn/s8km4YD1NfS31aFeZe6peOTStJzIqM2Pvcut9XEIgT+aMAXNOM76kwcf0Ibs8fGQEZaSknEJ0kPZ+B41GO0d4moZmfjLWlPYqzO52UGHQunpEi0+MwC82+IJAVCkvxS4MZZZV7LUc57V7dbnUGwxzbXsBBFIMYUV14BavTbCI6W1K1+bKoKAnQoA3gbWEQsKe2r4NyIhv2CnO34p76C5NqQilMXD9cRZqPiCJmHt/sqdMwtCS38/Wr7YjJMcYCPBqokRwrGysjiaQYdAGwSLyam6bCsLft8nHLNv7lhVw/FGBGq3jFf+p2q1Ph5p5eMTxzZwmFHgJuaAFi3TzaZ6QS0UXeupVq07qX/AEitAEAFxYu9+/hYX9hFPJAM0hquKf14XHhoXbF4l4bKemYOpQ7lhd/WIsU7gHY4aA3RLJOxGQiusxbt1BtWqfre4AMrR1PwL/YUMOafZ+PiqkBmf+jR+sDFqqAYojTxnHl+n07EQIAV4C24MrVtTObZmf+NrwyEV3mrS+j2vzC3eImabRuMCCwmsvptBGsrh+kkqlIfsFGa8PZYmsH8EQmkmzduM3/Ln5PYrvbqBJtoUU06A+xtw3tjGQiusxbt1BtWudOkw680ZrxgBQt6XLMzuecWPScTFAStPUK6hC22Ph80qbgt2j0+okkmUkyKZtbCFW50OrfdLXfXe5yst5t4VGW07v1EMlEdJm3bqXalK/O4qUkSWtFGWDLulwIKPDgLkgmKAkarVNQp2PPKijQaTMIAGcWlRVqZCbJpGxuDkyVCy3+zQHYr9RwHAGjy13i20NUqMlEdJm3voxqM2axKW0B17RGHAAXtKzL7QF+oubvTurOzxGprbE8sxltbKhD5SVwYl0/Zg5JxsgCzGwaZtmA08hTxvE6cbmYiPK1h/vBi8spE9Fl3rqValMWoViILeBQp3XhBgjQ0i63DTSIRWWZcKaIIIMEjQrmFip/Gzk4rPucB2jt8CaACLMqWOWneSQZUWvAR3cgxiYrFkrtnoAyzUy2pUc3yA/NxaPbE9eR58zP8Ki+6ZGkTESXeetWqk2ZuLgYQ6yNnrsDELOeB9UrBpxSAEBIEj+SCJpK0NjeB4L3phYqfxcVPFs3TUW3sOY1NQvAbvVLr5GhX0kyIZtLa69Eu+MJRFYslNq9mcqForKj+EgWPDTKDxuI/epy5PlRQr46GPKPZCK6yFu3Um2q4MUCNhcA5zNb3B6P6Xq1WuWFReZcWN8HENFpeZfTcaPxknJFbE2JnwkRJCVoVES7nHeaWqisvUaLwmMHQOK6SmtCtZEGgB1pNisK1UySCdncF3r6OW6EfWXFQqndM1QulJUd+Uey4KGSHyq/NpzGrB0IkyU+sSbckTXCUMHLbhpVO15RJkn8SCJoIkH7wolO7RtTC5XVoXaFVmBbMEKL3By+82pL42JLL7zWkmzJpuo08UJN5bJIHy01x2U4XFBoPpIlnlGhX0mycWHCHfhw0ycBWbFQavdU5UJZ2ZF/JAseGuWHNdxt3OW03aXC6stv/CHyuwGilVwujGQX17CTM02S+JFE0ESCtsu/69hnW6j8Ae6W0gpUA2dprA2u85ZnOf1+jn4lycb1k1gEQUkSyoqFUrunKhfKyo78I1nw0Cg/9KO1nMs9BtbQ2XotYHrBJmoNffrveL2lQCWnotUVXS4NWxIdOMit6ZL4kUTQRIKWAOeO7LMtVP4ALQxoBbD6RSwwqF03HHtvt8Wm/Sb4oMESzk4qcfUmK1otB9X8ykySUaojfkBUuq6sWCi1e6pyoazsKD4SpcCk/NAcWcjcWYV7FaGd3NDKUIms/y2oRtjOINkAeGgXA0n8SCJoIkG7QozoxEczLVT+AE/r2Y4y/t7FXjP+u9rw+rIhSp6F/JnXWCVns3gDLQ6fTSSZlM3FETmWlS5lxUKp3TNULpSVHSktXW5WfujBy3yX8yOiOOI0/V0Es/TfwpT/vkCWKIgUf6uPJPEjiaCJBG0L24GnKHIzLVT+ALz1yn8VYRCZSDKpR0/CVRFZrwKyYqHU7qnKhbKyo/hIuJySH0picp7LMZ+hfEPnkFaGopf/W9jVpmz7ObezKIl7KIkfSQRNJGhVN4AgHDMtVCxgFS/9VyGroJlJsv007fQ8RHpKY8QhKxZK7Z6qXCgrO/KPZMFDo/yQ4WCuyz1DyjxYnT6yJGlBlS+buRK9ZW07EbvxY7Py+L+FqWX1Z52Iib+xkZTEjySCpASNDeKf9FSZaaHyB+D9af+r4Gkqc0gyRrKjCQnIioVSu6cqF04rOxJTBQ+N8kNneZ7LVT80ETJTf1uDW7slSQvKfNlYCkCJqqcAwOTHv6Y0/bfwV3tn25Q2EATg24QAAYJA2sibKC8FJQ6giAQKFXAq0lGo/v8f091AlNbgaIeQ07nnAx9umIFJNsndZvee8SHzjxRIjFdKOtsB6nxTyNXhvEaZUWkEvYYMKbZKCz71y6pwYWgtNgDdqoLpDLv6K/iCLma/oFsst5Q7bAcMGxtCTgnLxoBm1leUtk5DxUkLOv2yU4hMyLilUdFwlDnDrjsi8MV7dN6f68fX8e1MRSLuISflgZCl5bpNgbaTFnT6ZcmCF4nTkwL0wmtdu40h44uSynyDlKfcshsD/L7mHnJTkIOpq0vIsfyhncyzVjma537ZvhWB8FcWmB3JEHKGXTji7SDne8w3qMGJW3az0Cup7iFnQdvOW3ZZCq4ZlYs4IbfeLzuzv8X64czzsNuklC/KHeYfGd4WUy+KOrymGnYPOV1W7JtbluVgYRkJGDtpQadftnrx/aQE1lmnmwyB9jT8AWYv79vr50Oe1i2sJT3jHCS3d6yTVUfCEWmdZYCwPnfSgk6/bB2QRP9OBuTsaZizBSLjbT2z4O3134vmM68JgeIWcs6OBQGKMuXkwZyYdlpwvT23dvWTmoAmD4Vk0Rn+EGkBP7M2VFfDLfKA7QADYl4XL32TGV/4mZuW4Jzxitf/zb2WJuHBTOOes5CLLkaKeRyQmB/Qth+8Qi0Db+MY1TcxMt9QGYvxs7B036OdFI1ULdtI1SNLSTZIJip0/I1RRdWsW12y/JlxSHs9uU0B4wljTUB5+EXVEx1thFqg1n55qXAZUPGtXXt7SwVBaOuK1fpUELQVpnDKeIXKil4imdFY/CF9GqqkxvPHi0xHDcPfyGjxXNCBHGorwdLjkW2QbQUjWTQEDhM9dPyQzROQwhRmL4w6W6bJ11tF8xSgvZIn2j6qcqNFrjiSJ+rqDR4ZcEeW6cj2OiToXF2+ZK26b6JlqEvGqtu0HaK/0dGJQTopBiT3OnRekX4V6VOZ5pJXs3azWmpEtPX4kr/ow2yr/KOaqoTQnYeO12nflN73E0pNMsHyutCoDgHGFbP4mySn9qPjmqRpxuzfR8fIVsQeukSn+x2g1+vpiKra1TncchDUw2sSPY2sd/eVkJFO5qbK1s7iIMbW0DwIuQocs0+LJB2bCoYnaVWxMj55ckYOtVNSqFm2f/3bsgMGKSHzefAyyrhFyefHqfYsndyLFtmO0PbZ1rE4rhAT+M7Ig5CjbTQFgh2+2O2CwgSCzTvEvwL1yxfNiaIc9KM4ffkau9ujGQyKYK9R1Y6a9tze3h0u12rR/oEyMYsBe80Wj3C2fBDwQ2AOEMS8CiYNVhmVTiKhq4sbJ6nyH4QXVSYQbCBwCZDNZEakTH9yppdImj5eWtOb53UygKP/G+XfM3Snozwdpd9nJw/J5Vrtu0FbFtCOBY7uel4qMIFgIzmOk0YCgUAgEAgEAoFAIBAIBALBZ+MPi2jQvTDed8sAAAAASUVORK5CYII=\\n\",\n      \"text/plain\": [\n       \"<IPython.core.display.Image object>\"\n      ]\n     },\n     \"execution_count\": 146,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Image(\\\"../examples/svg2roughjs.png\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Annexe A : Miscellanées académiques\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Décompositions d'un MCD\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Aussi surprenant que cela puisse paraître, tout MCD peut être transformé en un MCD équivalent dont les seules associations sont des dépendances fonctionnelles binaires non porteuses d'attributs, telles que celle ci-dessous :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 147,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"316\\\" height=\\\"112\\\" viewBox=\\\"0 0 316 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"316\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"59\\\" y1=\\\"56\\\" x2=\\\"158\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"257\\\" y1=\\\"56\\\" x2=\\\"158\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"158\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"145\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"114\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">?,1</text>\\n\",\n       \"\\t<text x=\\\"184\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">     </text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_1_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"109\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ENTITÉ 1</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 1 1</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"53\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 1 2</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 1 3</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTITE_2_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"207\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"207\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"207\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"207\\\" y1=\\\"39\\\" x2=\\\"307\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"216\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">ENTITÉ 2</text>\\n\",\n       \"\\t<text x=\\\"215\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 2 1</text>\\n\",\n       \"\\t<line x1=\\\"215\\\" y1=\\\"59\\\" x2=\\\"251\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"215\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 2 2</text>\\n\",\n       \"\\t<text x=\\\"215\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">at 2 3</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo \\n\",\n    \"ENTITÉ 1_: at 1 1, at 1 2, at 1 3\\n\",\n    \"DF, ?1 ENTITÉ 1_, XX ENTITÉ 2_\\n\",\n    \"ENTITÉ 2_: at 2 1, at 2 2, at 2 3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La transformation peut demander jusqu'à trois opérations que Mocodo appelle _drain_, _split_ et _explode_, et que nous allons découvrir dans la suite.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Vider les DF de leurs attributs\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 148,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"876\\\" height=\\\"112\\\" viewBox=\\\"0 0 876 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"876\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PROPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"68\\\" y1=\\\"56\\\" x2=\\\"215\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"345\\\" y1=\\\"56\\\" x2=\\\"215\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M260 27 a14 14 90 0 1 14 14 V55 h-118 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M274 55 v16 a14 14 90 0 1 -14 14 H170 a14 14 90 0 1 -14 -14 V55 H118\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"27\\\" width=\\\"118\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"55\\\" x2=\\\"274\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Proposer</text>\\n\",\n       \"\\t\\t<text x=\\\"163\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date proposition</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"280\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ATTRIBUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"601\\\" y1=\\\"56\\\" x2=\\\"469\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"345\\\" y1=\\\"56\\\" x2=\\\"469\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M508 27 a14 14 90 0 1 14 14 V55 h-106 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M522 55 v16 a14 14 90 0 1 -14 14 H430 a14 14 90 0 1 -14 -14 V55 H106\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"416\\\" y=\\\"27\\\" width=\\\"106\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"416\\\" y1=\\\"55\\\" x2=\\\"522\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"423\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Attribuer</text>\\n\",\n       \"\\t\\t<text x=\\\"423\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date signature</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"528\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"392\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SOUTENIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"601\\\" y1=\\\"56\\\" x2=\\\"729\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"837\\\" y1=\\\"56\\\" x2=\\\"729\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M764 27 a14 14 90 0 1 14 14 V55 h-98 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M778 55 v16 a14 14 90 0 1 -14 14 H694 a14 14 90 0 1 -14 -14 V55 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"680\\\" y=\\\"27\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"680\\\" y1=\\\"55\\\" x2=\\\"778\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"687\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Soutenir</text>\\n\",\n       \"\\t\\t<text x=\\\"687\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">note stage</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"656\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"783\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTREPRISE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"127\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entreprise</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom entreprise</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"114\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">téléphone</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity STAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"303\\\" y=\\\"18\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"303\\\" y=\\\"48\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"303\\\" y=\\\"18\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"303\\\" y1=\\\"48\\\" x2=\\\"387\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"319\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stage</text>\\n\",\n       \"\\t<text x=\\\"311\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. stage</text>\\n\",\n       \"\\t<line x1=\\\"311\\\" y1=\\\"68\\\" x2=\\\"378\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"311\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">sujet</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETUDIANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"551\\\" y=\\\"18\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"551\\\" y=\\\"48\\\" width=\\\"100\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"551\\\" y=\\\"18\\\" width=\\\"100\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"551\\\" y1=\\\"48\\\" x2=\\\"651\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"560\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étudiant</text>\\n\",\n       \"\\t<text x=\\\"559\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num étudiant</text>\\n\",\n       \"\\t<line x1=\\\"559\\\" y1=\\\"68\\\" x2=\\\"642\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"559\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"807\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"807\\\" y=\\\"56\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"807\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"807\\\" y1=\\\"56\\\" x2=\\\"867\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"816\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"815\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"815\\\" y1=\\\"76\\\" x2=\\\"843\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Entreprise** (<u>nom entreprise</u>, adresse, téléphone)\\n\",\n       \"- **Étudiant** (<u>num étudiant</u>, nom, _#num. stage_, date signature, date, note stage)\\n\",\n       \"- **Stage** (<u>num. stage</u>, sujet, _#nom entreprise_, date proposition)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Entreprise: nom entreprise, adresse, téléphone\\n\",\n    \"Proposer, 0N Entreprise, 11 Stage: date proposition\\n\",\n    \"Stage: num. stage, sujet\\n\",\n    \"Attribuer, 11 Étudiant, 01 Stage: date signature\\n\",\n    \"Étudiant: num étudiant, nom\\n\",\n    \"Soutenir, 01 Étudiant, 0N Date: note stage\\n\",\n    \"Date: date\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le MCD ci-dessus comporte trois associations de dépendance fonctionnelle porteuses d'attributs. Certains auteurs considèrent cela comme une anomalie. En tout état de cause, Mocodo peut les déplacer dans les entités distinguées par les cardinalités 11. Nous appelons cette opération un « drainage des dépendances fonctionnelles » (option `-t drain`). Notez bien que ces deux MCD sont strictement équivalents, et produisent le même MLD.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 149,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"900\\\" height=\\\"112\\\" viewBox=\\\"0 0 900 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"900\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PROPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"68\\\" y1=\\\"56\\\" x2=\\\"207\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"207\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M244 27 a14 14 90 0 1 14 14 V55 h-102 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M258 55 v16 a14 14 90 0 1 -14 14 H170 a14 14 90 0 1 -14 -14 V55 H102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"27\\\" width=\\\"102\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"55\\\" x2=\\\"258\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"164\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Proposer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"264\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association ATTRIBUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"623\\\" y1=\\\"56\\\" x2=\\\"489\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"489\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M528 27 a14 14 90 0 1 14 14 V55 h-106 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M542 55 v16 a14 14 90 0 1 -14 14 H450 a14 14 90 0 1 -14 -14 V55 H106\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"436\\\" y=\\\"27\\\" width=\\\"106\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"436\\\" y1=\\\"55\\\" x2=\\\"542\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"443\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Attribuer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"548\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"412\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association SOUTENIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"623\\\" y1=\\\"56\\\" x2=\\\"753\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"861\\\" y1=\\\"56\\\" x2=\\\"753\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M788 27 a14 14 90 0 1 14 14 V55 h-98 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M802 55 v16 a14 14 90 0 1 -14 14 H718 a14 14 90 0 1 -14 -14 V55 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"704\\\" y=\\\"27\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"704\\\" y1=\\\"55\\\" x2=\\\"802\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"711\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Soutenir</text>\\n\",\n       \"\\t\\t<text x=\\\"711\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">note stage</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"680\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"807\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ENTREPRISE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"118\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"118\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"127\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Entreprise</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom entreprise</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"114\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">téléphone</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity STAGE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"287\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"287\\\" y=\\\"39\\\" width=\\\"120\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"287\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"287\\\" y1=\\\"39\\\" x2=\\\"407\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"321\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Stage</text>\\n\",\n       \"\\t<text x=\\\"295\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. stage</text>\\n\",\n       \"\\t<line x1=\\\"295\\\" y1=\\\"59\\\" x2=\\\"362\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"295\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">sujet</text>\\n\",\n       \"\\t<text x=\\\"295\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date proposition</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity ETUDIANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"571\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"571\\\" y=\\\"39\\\" width=\\\"104\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"571\\\" y=\\\"9\\\" width=\\\"104\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"571\\\" y1=\\\"39\\\" x2=\\\"675\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"582\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Étudiant</text>\\n\",\n       \"\\t<text x=\\\"579\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num étudiant</text>\\n\",\n       \"\\t<line x1=\\\"579\\\" y1=\\\"59\\\" x2=\\\"662\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"579\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom</text>\\n\",\n       \"\\t<text x=\\\"579\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date signature</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"831\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"831\\\" y=\\\"56\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"831\\\" y=\\\"26\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"831\\\" y1=\\\"56\\\" x2=\\\"891\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"840\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"839\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"839\\\" y1=\\\"76\\\" x2=\\\"867\\\" y2=\\\"76\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Entreprise** (<u>nom entreprise</u>, adresse, téléphone)\\n\",\n       \"- **Étudiant** (<u>num étudiant</u>, nom, date signature, _#num. stage_, date, note stage)\\n\",\n       \"- **Stage** (<u>num. stage</u>, sujet, date proposition, _#nom entreprise_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --mld -t drain\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La première version peut être préférée pour des raisons de localité sémantique (_date proposition_ dans PROPOSER), ou honnie parce qu'elle complique la définition d'identifiant d'association. Mocodo n'a pas d'opinion sur la question. Par contre, il se refuse à procéder au drainage _via_ les cardinalités 01. Dans le MCD ci-dessus, le placement de _note stage_ dans SOUTENIR indique qu'un étudiant peut ne pas se voir attribuer de note de stage ; si elle était mise dans ÉTUDIANT, la connaissance du fait que ce champ autorise la valeur `NULL` serait perdue.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Décomposer les DF n-aires\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"De même, d'aucuns regardent de travers les dépendances fonctionnelles d'arité $n$ supérieure à 2 :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 150,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"386\\\" height=\\\"212\\\" viewBox=\\\"0 0 386 212\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"386\\\" height=\\\"212\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RECOLTER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"320\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"57\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"184\\\" y1=\\\"156\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M220 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M234 55 v16 a14 14 90 0 1 -14 14 H148 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"134\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"134\\\" y1=\\\"55\\\" x2=\\\"234\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"142\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Récolter</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"239\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"110\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BATAILLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"96\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"105\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Bataille</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom bataille</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"93\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lieu</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity VILLAGEOIS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"263\\\" y1=\\\"39\\\" x2=\\\"377\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"272\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Villageois</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom villageois</text>\\n\",\n       \"\\t<line x1=\\\"271\\\" y1=\\\"59\\\" x2=\\\"359\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">fonction</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TROPHEE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"109\\\" width=\\\"92\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"139\\\" width=\\\"92\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"138\\\" y=\\\"109\\\" width=\\\"92\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"138\\\" y1=\\\"139\\\" x2=\\\"230\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Trophée</text>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">numéro</text>\\n\",\n       \"\\t<line x1=\\\"146\\\" y1=\\\"159\\\" x2=\\\"196\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">type</text>\\n\",\n       \"\\t<text x=\\\"146\\\" y=\\\"190\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">état</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Bataille** (<u>nom bataille</u>, lieu, date)\\n\",\n       \"- **Trophée** (<u>numéro</u>, type, état, _#nom villageois_, _#nom bataille_)\\n\",\n       \"- **Villageois** (<u>nom villageois</u>, adresse, fonction)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Bataille: nom bataille, lieu, date\\n\",\n    \"Récolter, 0N Villageois, 0N Bataille, 11 Trophée\\n\",\n    \"Villageois: nom villageois, adresse, fonction\\n\",\n    \"\\n\",\n    \"Trophée: numéro, type, état\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Toute DF de ce type peut en effet être « fendue » en $n-1$ DF. L'option `-t split` génère le MCD équivalent :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 151,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"636\\\" height=\\\"112\\\" viewBox=\\\"0 0 636 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"636\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RECOLTER1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"309\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"57\\\" y1=\\\"56\\\" x2=\\\"184\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M220 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M234 55 v16 a14 14 90 0 1 -14 14 H148 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"134\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"134\\\" y1=\\\"55\\\" x2=\\\"234\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"142\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Récolter</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"240\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"110\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association RECOLTER0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"309\\\" y1=\\\"56\\\" x2=\\\"434\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"570\\\" y1=\\\"56\\\" x2=\\\"434\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M470 27 a14 14 90 0 1 14 14 V55 h-100 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M484 55 v16 a14 14 90 0 1 -14 14 H398 a14 14 90 0 1 -14 -14 V55 H100\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"384\\\" y=\\\"27\\\" width=\\\"100\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"384\\\" y1=\\\"55\\\" x2=\\\"484\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"392\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Récolter</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"360\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"489\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity BATAILLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"96\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"96\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"105\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Bataille</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom bataille</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"93\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">lieu</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TROPHEE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"92\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"39\\\" width=\\\"92\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"263\\\" y=\\\"9\\\" width=\\\"92\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"263\\\" y1=\\\"39\\\" x2=\\\"355\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Trophée</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">numéro</text>\\n\",\n       \"\\t<line x1=\\\"271\\\" y1=\\\"59\\\" x2=\\\"321\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">type</text>\\n\",\n       \"\\t<text x=\\\"271\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">état</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity VILLAGEOIS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"513\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"513\\\" y=\\\"39\\\" width=\\\"114\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"513\\\" y=\\\"9\\\" width=\\\"114\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"513\\\" y1=\\\"39\\\" x2=\\\"627\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"522\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Villageois</text>\\n\",\n       \"\\t<text x=\\\"521\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom villageois</text>\\n\",\n       \"\\t<line x1=\\\"521\\\" y1=\\\"59\\\" x2=\\\"609\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"521\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">adresse</text>\\n\",\n       \"\\t<text x=\\\"521\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">fonction</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Bataille** (<u>nom bataille</u>, lieu, date)\\n\",\n       \"- **Trophée** (<u>numéro</u>, type, état, _#nom bataille_, _#nom villageois_)\\n\",\n       \"- **Villageois** (<u>nom villageois</u>, adresse, fonction)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --seed=3 --mld -t split arrange:wide\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Décomposer les associations n-aires non DF\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Toute association non DF d'arité $n$ peut être décomposée en un ensemble de $n$ associations DF : elle-même se voit alors remplacée par une entité liée aux $n$ entités originales. Cette nouvelle entité est appelée « entité-intersection », « entité-associative » ou « Gerund », cf. Song, Il-Yeol & Evans, Mary & Park, Eui Kyun. _A Comparative Analysis of Entity-Relationship Diagrams_. Journal of Computer and Software Engineering. 3 (1995). Dans les cours de [Laurent Audibert](https://laurent-audibert.developpez.com/Cours-BD/?page=conception-des-bases-de-donnees-modele-a#L2-3-3-b) ou de [Patrick Bergougnoux](https://gestion.pumbo.fr/boutique/livre/modelisation-conceptuelle-de-donnees), l'opération est illustrée à l'aide du MCD suivant :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 152,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"230\\\" viewBox=\\\"0 0 310 230\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"230\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association PROJETER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"262\\\" y1=\\\"56\\\" x2=\\\"145\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"145\\\" y1=\\\"174\\\" x2=\\\"145\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"38\\\" y1=\\\"56\\\" x2=\\\"145\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M180 27 a14 14 90 0 1 14 14 V55 h-98 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M194 55 v16 a14 14 90 0 1 -14 14 H110 a14 14 90 0 1 -14 -14 V55 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"96\\\" y=\\\"27\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"96\\\" y1=\\\"55\\\" x2=\\\"194\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"104\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projeter</text>\\n\",\n       \"\\t\\t<text x=\\\"103\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"199\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"150\\\" y=\\\"119\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"72\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FILM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"58\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"58\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"67\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Film</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. film</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"59\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SALLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"223\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"223\\\" y1=\\\"48\\\" x2=\\\"301\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"236\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Salle</text>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. salle</text>\\n\",\n       \"\\t<line x1=\\\"231\\\" y1=\\\"68\\\" x2=\\\"293\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"231\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">capacité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CRENEAU -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"127\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"157\\\" width=\\\"102\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"94\\\" y=\\\"127\\\" width=\\\"102\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"94\\\" y1=\\\"157\\\" x2=\\\"196\\\" y2=\\\"157\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"106\\\" y=\\\"148.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Créneau</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"174.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. créneau</text>\\n\",\n       \"\\t<line x1=\\\"102\\\" y1=\\\"177\\\" x2=\\\"187\\\" y2=\\\"177\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"191.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"208\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure début</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Créneau** (<u>num. créneau</u>, date, heure début)\\n\",\n       \"- **Film** (<u>id. film</u>, titre, durée)\\n\",\n       \"- **Projeter** (<u>_#num. salle_</u>, <u>_#num. créneau_</u>, <u>_#id. film_</u>, tarif)\\n\",\n       \"- **Salle** (<u>num. salle</u>, capacité)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Film: id. film, titre, durée\\n\",\n    \"Projeter, 1N Salle, 1N Créneau, 1N Film: tarif\\n\",\n    \"Salle: num. salle, capacité\\n\",\n    \"\\n\",\n    \"Créneau: num. créneau, date, heure début\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La décomposition est invoquée par l'option `-t explode` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 153,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"284\\\" height=\\\"330\\\" viewBox=\\\"0 0 284 330\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"284\\\" height=\\\"330\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"137\\\" y1=\\\"47\\\" x2=\\\"38\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"38\\\" y1=\\\"156\\\" x2=\\\"38\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"38\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"25\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"64\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"43\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"137\\\" y1=\\\"47\\\" x2=\\\"236\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"236\\\" y1=\\\"156\\\" x2=\\\"236\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"236\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"223\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"192\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"241\\\" y=\\\"110\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"137\\\" y1=\\\"47\\\" x2=\\\"137\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"137\\\" y1=\\\"274\\\" x2=\\\"137\\\" y2=\\\"156\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"137\\\" cy=\\\"156\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"160.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"142\\\" y=\\\"101\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"142\\\" y=\\\"219\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJETER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"87\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"87\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"87\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"87\\\" y1=\\\"39\\\" x2=\\\"187\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"96\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projeter</text>\\n\",\n       \"\\t<text x=\\\"95\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. projeter</text>\\n\",\n       \"\\t<line x1=\\\"95\\\" y1=\\\"59\\\" x2=\\\"166\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"95\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FILM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"58\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"139\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"109\\\" width=\\\"58\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"139\\\" x2=\\\"67\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Film</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. film</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"159\\\" x2=\\\"59\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"173.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"190\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SALLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"118\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"148\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"118\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"197\\\" y1=\\\"148\\\" x2=\\\"275\\\" y2=\\\"148\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"210\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Salle</text>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"165.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. salle</text>\\n\",\n       \"\\t<line x1=\\\"205\\\" y1=\\\"168\\\" x2=\\\"267\\\" y2=\\\"168\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"182.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">capacité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CRENEAU -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"86\\\" y=\\\"227\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"86\\\" y=\\\"257\\\" width=\\\"102\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"86\\\" y=\\\"227\\\" width=\\\"102\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"86\\\" y1=\\\"257\\\" x2=\\\"188\\\" y2=\\\"257\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"98\\\" y=\\\"248.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Créneau</text>\\n\",\n       \"\\t<text x=\\\"94\\\" y=\\\"274.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. créneau</text>\\n\",\n       \"\\t<line x1=\\\"94\\\" y1=\\\"277\\\" x2=\\\"179\\\" y2=\\\"277\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"94\\\" y=\\\"291.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"94\\\" y=\\\"308\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure début</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Créneau** (<u>num. créneau</u>, date, heure début)\\n\",\n       \"- **Film** (<u>id. film</u>, titre, durée)\\n\",\n       \"- **Projeter** (<u>id. projeter</u>, tarif, _#id. film_, _#num. salle_, _#num. créneau_)\\n\",\n       \"- **Salle** (<u>num. salle</u>, capacité)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --seed=8 --mld -t explode arrange:balanced\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le nouveau MCD a vocation à être retouché pour :\\n\",\n    \"- se rapprocher du plongement initial ;\\n\",\n    \"- nommer judicieusement les nouveaux identifiant, entité et associations créés.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 154,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"662\\\" height=\\\"303\\\" viewBox=\\\"0 0 662 303\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"662\\\" height=\\\"303\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association CONCERNER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"300\\\" y1=\\\"56\\\" x2=\\\"154\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"38\\\" y1=\\\"56\\\" x2=\\\"154\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M198 27 a14 14 90 0 1 14 14 V55 h-116 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M212 55 v16 a14 14 90 0 1 -14 14 H110 a14 14 90 0 1 -14 -14 V55 H116\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"96\\\" y=\\\"27\\\" width=\\\"116\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"96\\\" y1=\\\"55\\\" x2=\\\"212\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"104\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Concerner</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"218\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"72\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association AVOIR_LIEU_DANS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"300\\\" y1=\\\"56\\\" x2=\\\"467\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"614\\\" y1=\\\"56\\\" x2=\\\"467\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M532 27 a14 14 90 0 1 14 14 V55 h-158 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M546 55 v16 a14 14 90 0 1 -14 14 H402 a14 14 90 0 1 -14 -14 V55 H158\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"388\\\" y=\\\"27\\\" width=\\\"158\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"388\\\" y1=\\\"55\\\" x2=\\\"546\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"396\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Avoir lieu dans</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"364\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"551\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association AVOIR_LIEU_PENDANT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"300\\\" y1=\\\"56\\\" x2=\\\"300\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"300\\\" y1=\\\"247\\\" x2=\\\"300\\\" y2=\\\"147\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M380 118 a14 14 90 0 1 14 14 V146 h-188 V132 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M394 146 v16 a14 14 90 0 1 -14 14 H220 a14 14 90 0 1 -14 -14 V146 H188\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"206\\\" y=\\\"118\\\" width=\\\"188\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"206\\\" y1=\\\"146\\\" x2=\\\"394\\\" y2=\\\"146\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"213\\\" y=\\\"139.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Avoir lieu pendant</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"110\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"192\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity FILM -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"58\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"58\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"58\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"67\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Film</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. film</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"59\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">titre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJECTION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"18\\\" width=\\\"118\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"48\\\" width=\\\"118\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"18\\\" width=\\\"118\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"241\\\" y1=\\\"48\\\" x2=\\\"359\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"250\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projection</text>\\n\",\n       \"\\t<text x=\\\"249\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. projection</text>\\n\",\n       \"\\t<line x1=\\\"249\\\" y1=\\\"68\\\" x2=\\\"333\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"249\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SALLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"575\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"575\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"575\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"575\\\" y1=\\\"48\\\" x2=\\\"653\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"588\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Salle</text>\\n\",\n       \"\\t<text x=\\\"583\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. salle</text>\\n\",\n       \"\\t<line x1=\\\"583\\\" y1=\\\"68\\\" x2=\\\"645\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"583\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">capacité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CRENEAU -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"249\\\" y=\\\"200\\\" width=\\\"102\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"249\\\" y=\\\"230\\\" width=\\\"102\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"249\\\" y=\\\"200\\\" width=\\\"102\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"249\\\" y1=\\\"230\\\" x2=\\\"351\\\" y2=\\\"230\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"261\\\" y=\\\"221.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Créneau</text>\\n\",\n       \"\\t<text x=\\\"257\\\" y=\\\"247.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. créneau</text>\\n\",\n       \"\\t<line x1=\\\"257\\\" y1=\\\"250\\\" x2=\\\"342\\\" y2=\\\"250\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"257\\\" y=\\\"264.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"257\\\" y=\\\"281\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">heure début</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Créneau** (<u>num. créneau</u>, date, heure début)\\n\",\n       \"- **Film** (<u>id. film</u>, titre, durée)\\n\",\n       \"- **Projection** (<u>id. projection</u>, tarif, _#id. film_, _#num. salle_, _#num. créneau_)\\n\",\n       \"- **Salle** (<u>num. salle</u>, capacité)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Film: id. film, titre, durée\\n\",\n    \"Concerner, 11 Projection, 1N Film\\n\",\n    \"Projection: id. projection, tarif\\n\",\n    \"Avoir lieu dans, 11 Projection, 1N Salle\\n\",\n    \"Salle: num. salle, capacité\\n\",\n    \"\\n\",\n    \"Avoir lieu pendant, 11 Projection, 1N Créneau\\n\",\n    \"\\n\",\n    \"Créneau: num. créneau, date, heure début\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Décomposer les associations binaires non DF\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Considérons le MCD suivant, qui comporte deux associations binaires non DF, l'une porteuse d'attribut, l'autre non :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 155,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"714\\\" height=\\\"112\\\" viewBox=\\\"0 0 714 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"714\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association LIGNE_COM_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"72\\\" y1=\\\"56\\\" x2=\\\"226\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"367\\\" y1=\\\"56\\\" x2=\\\"226\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M274 27 a14 14 90 0 1 14 14 V55 h-124 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M288 55 v16 a14 14 90 0 1 -14 14 H178 a14 14 90 0 1 -14 -14 V55 H124\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"164\\\" y=\\\"27\\\" width=\\\"124\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"164\\\" y1=\\\"55\\\" x2=\\\"288\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"171\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">LIGNE COM.</text>\\n\",\n       \"\\t\\t<text x=\\\"171\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"140\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"293\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DISPONIBILITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"367\\\" y1=\\\"56\\\" x2=\\\"522\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"666\\\" y1=\\\"56\\\" x2=\\\"522\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M584 27 a14 14 90 0 1 14 14 V55 h-152 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M598 55 v16 a14 14 90 0 1 -14 14 H460 a14 14 90 0 1 -14 -14 V55 H152\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"446\\\" y=\\\"27\\\" width=\\\"152\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"446\\\" y1=\\\"55\\\" x2=\\\"598\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"454\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DISPONIBILITÉ</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"422\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"603\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"135\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"121\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"317\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"317\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"317\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"317\\\" y1=\\\"39\\\" x2=\\\"417\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"326\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"325\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"325\\\" y1=\\\"59\\\" x2=\\\"397\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"325\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé</text>\\n\",\n       \"\\t<text x=\\\"325\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PAYS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"627\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"627\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"627\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"627\\\" y1=\\\"48\\\" x2=\\\"705\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"642\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PAYS</text>\\n\",\n       \"\\t<text x=\\\"635\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">code pays</text>\\n\",\n       \"\\t<line x1=\\\"635\\\" y1=\\\"68\\\" x2=\\\"697\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"635\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom pays</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **COMMANDE** (<u>num. commande</u>, date, montant)\\n\",\n       \"- **DISPONIBILITÉ** (<u>_#réf. produit_</u>, <u>_#code pays_</u>)\\n\",\n       \"- **LIGNE COM.** (<u>_#num. commande_</u>, <u>_#réf. produit_</u>, quantité)\\n\",\n       \"- **PAYS** (<u>code pays</u>, nom pays)\\n\",\n       \"- **PRODUIT** (<u>réf. produit</u>, libellé, prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"COMMANDE: num. commande, date, montant\\n\",\n    \"LIGNE COM., 1N COMMANDE, 0N PRODUIT: quantité\\n\",\n    \"PRODUIT: réf. produit, libellé, prix unitaire\\n\",\n    \"DISPONIBILITÉ, 1N PRODUIT, 0N PAYS\\n\",\n    \"PAYS: code pays, nom pays\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Par souci de concision, quand on parle d'associations $n$-aires dans ce document, c'est par opposition aux associations binaires ; mais bien sûr, la règle de décomposition énoncée à la section précédente est également valable pour $n=2$, même si par défaut elle ne s'applique qu'aux associations d'arité minimale 3. En réduisant la valeur de `arity` à 2, toutes les associations binaires non DF seront également décomposées :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 156,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"900\\\" height=\\\"102\\\" viewBox=\\\"0 0 900 102\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"900\\\" height=\\\"102\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"267\\\" y1=\\\"51\\\" x2=\\\"165\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<line x1=\\\"64\\\" y1=\\\"51\\\" x2=\\\"165\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"165\\\" cy=\\\"51\\\" r=\\\"18\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"153\\\" y=\\\"56.7\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"189\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"125\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"267\\\" y1=\\\"51\\\" x2=\\\"369\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<line x1=\\\"459\\\" y1=\\\"51\\\" x2=\\\"369\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"369\\\" cy=\\\"51\\\" r=\\\"18\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"357\\\" y=\\\"56.7\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"329\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"392\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"663\\\" y1=\\\"51\\\" x2=\\\"549\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<line x1=\\\"459\\\" y1=\\\"51\\\" x2=\\\"549\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"549\\\" cy=\\\"51\\\" r=\\\"18\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"537\\\" y=\\\"56.7\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"573\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"509\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"663\\\" y1=\\\"51\\\" x2=\\\"777\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<line x1=\\\"857\\\" y1=\\\"51\\\" x2=\\\"777\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"777\\\" cy=\\\"51\\\" r=\\\"18\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"765\\\" y=\\\"56.7\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"737\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"800\\\" y=\\\"66.3\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"9.9\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"8\\\" y=\\\"8\\\" width=\\\"112\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"8\\\" y=\\\"35\\\" width=\\\"112\\\" height=\\\"59\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"8\\\" y=\\\"8\\\" width=\\\"112\\\" height=\\\"86\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"8\\\" y1=\\\"35\\\" x2=\\\"120\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"15\\\" y=\\\"27.45\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"15\\\" y=\\\"50.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"15\\\" y1=\\\"53.3\\\" x2=\\\"108\\\" y2=\\\"53.3\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<text x=\\\"15\\\" y=\\\"66.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">date</text>\\n\",\n       \"\\t<text x=\\\"15\\\" y=\\\"82.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">montant</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity LIGNE_COM_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"210\\\" y=\\\"16\\\" width=\\\"114\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"210\\\" y=\\\"43\\\" width=\\\"114\\\" height=\\\"43\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"210\\\" y=\\\"16\\\" width=\\\"114\\\" height=\\\"70\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"210\\\" y1=\\\"43\\\" x2=\\\"324\\\" y2=\\\"43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"218\\\" y=\\\"35.45\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">LIGNE COM.</text>\\n\",\n       \"\\t<text x=\\\"217\\\" y=\\\"58.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">id. ligne com.</text>\\n\",\n       \"\\t<line x1=\\\"217\\\" y1=\\\"61.3\\\" x2=\\\"291\\\" y2=\\\"61.3\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<text x=\\\"217\\\" y=\\\"74.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">quantité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"414\\\" y=\\\"8\\\" width=\\\"90\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"414\\\" y=\\\"35\\\" width=\\\"90\\\" height=\\\"59\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"414\\\" y=\\\"8\\\" width=\\\"90\\\" height=\\\"86\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"414\\\" y1=\\\"35\\\" x2=\\\"504\\\" y2=\\\"35\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"422\\\" y=\\\"27.45\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"421\\\" y=\\\"50.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"421\\\" y1=\\\"53.3\\\" x2=\\\"486\\\" y2=\\\"53.3\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<text x=\\\"421\\\" y=\\\"66.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">libellé</text>\\n\",\n       \"\\t<text x=\\\"421\\\" y=\\\"82.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DISPONIBILITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"594\\\" y=\\\"24\\\" width=\\\"138\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"594\\\" y=\\\"51\\\" width=\\\"138\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"594\\\" y=\\\"24\\\" width=\\\"138\\\" height=\\\"54\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"594\\\" y1=\\\"51\\\" x2=\\\"732\\\" y2=\\\"51\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"602\\\" y=\\\"43.45\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">DISPONIBILITÉ</text>\\n\",\n       \"\\t<text x=\\\"601\\\" y=\\\"66.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">id. disponibilité</text>\\n\",\n       \"\\t<line x1=\\\"601\\\" y1=\\\"69.3\\\" x2=\\\"686\\\" y2=\\\"69.3\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PAYS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"822\\\" y=\\\"16\\\" width=\\\"70\\\" height=\\\"27\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"822\\\" y=\\\"43\\\" width=\\\"70\\\" height=\\\"43\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"822\\\" y=\\\"16\\\" width=\\\"70\\\" height=\\\"70\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"822\\\" y1=\\\"43\\\" x2=\\\"892\\\" y2=\\\"43\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.35\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"836\\\" y=\\\"35.45\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"16.2\\\">PAYS</text>\\n\",\n       \"\\t<text x=\\\"829\\\" y=\\\"58.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">code pays</text>\\n\",\n       \"\\t<line x1=\\\"829\\\" y1=\\\"61.3\\\" x2=\\\"885\\\" y2=\\\"61.3\\\" stroke=\\\"#000000\\\" stroke-width=\\\"0.9\\\"/>\\n\",\n       \"\\t<text x=\\\"829\\\" y=\\\"74.4\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"13.5\\\">nom pays</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **COMMANDE** (<u>num. commande</u>, date, montant)\\n\",\n       \"- **DISPONIBILITÉ** (<u>id. disponibilité</u>, _#réf. produit_, _#code pays_)\\n\",\n       \"- **LIGNE COM.** (<u>id. ligne com.</u>, quantité, _#num. commande_, _#réf. produit_)\\n\",\n       \"- **PAYS** (<u>code pays</u>, nom pays)\\n\",\n       \"- **PRODUIT** (<u>réf. produit</u>, libellé, prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i=sandbox --seed=1 --scale=0.9 --mld -t explode:arity=2 arrange:wide=9\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cette décomposition devient un peu extrême ! Vous pouvez conserver certaines associations binaires non DF, à savoir celles qui ne portent aucun attribut, en mettant `arity` à `2.5` (à lire comme « intermédiaire entre `2` et `3` ») :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 157,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"854\\\" height=\\\"112\\\" viewBox=\\\"0 0 854 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"854\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DISPONIBILITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"192\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"192\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M254 27 a14 14 90 0 1 14 14 V55 h-152 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M268 55 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V55 H152\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"27\\\" width=\\\"152\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"55\\\" x2=\\\"268\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DISPONIBILITÉ</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"273\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"558\\\" y1=\\\"56\\\" x2=\\\"446\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"446\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"446\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"433\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"472\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"402\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"558\\\" y1=\\\"56\\\" x2=\\\"670\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"782\\\" y1=\\\"56\\\" x2=\\\"670\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"670\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"657\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"626\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"695\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PAYS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"48\\\" x2=\\\"87\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PAYS</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">code pays</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"68\\\" x2=\\\"79\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom pays</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"297\\\" y1=\\\"39\\\" x2=\\\"397\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"306\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"305\\\" y1=\\\"59\\\" x2=\\\"377\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé</text>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity LIGNE_COM_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"18\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"48\\\" width=\\\"126\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"18\\\" width=\\\"126\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"495\\\" y1=\\\"48\\\" x2=\\\"621\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">LIGNE COM.</text>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">id. ligne com.</text>\\n\",\n       \"\\t<line x1=\\\"503\\\" y1=\\\"68\\\" x2=\\\"585\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"39\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"719\\\" y1=\\\"39\\\" x2=\\\"845\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"728\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"727\\\" y1=\\\"59\\\" x2=\\\"831\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">montant</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **COMMANDE** (<u>num. commande</u>, date, montant)\\n\",\n       \"- **DISPONIBILITÉ** (<u>_#réf. produit_</u>, <u>_#code pays_</u>)\\n\",\n       \"- **LIGNE COM.** (<u>id. ligne com.</u>, quantité, _#réf. produit_, _#num. commande_)\\n\",\n       \"- **PAYS** (<u>code pays</u>, nom pays)\\n\",\n       \"- **PRODUIT** (<u>réf. produit</u>, libellé, prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i=sandbox --mld -t explode:arity=2.5 arrange:wide --seed=1\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Décomposer en créant des entités faibles\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ci-dessus, le processus de modification a créé un identifiant _id. ligne com._ qui peut sembler superfétatoire. Si l'on a introduit la notion d'entité faible, on aura ici avantage à utiliser l'option `weak` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 158,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"854\\\" height=\\\"112\\\" viewBox=\\\"0 0 854 112\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"854\\\" height=\\\"112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DISPONIBILITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"192\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"56\\\" x2=\\\"192\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M254 27 a14 14 90 0 1 14 14 V55 h-152 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M268 55 v16 a14 14 90 0 1 -14 14 H130 a14 14 90 0 1 -14 -14 V55 H152\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"116\\\" y=\\\"27\\\" width=\\\"152\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"116\\\" y1=\\\"55\\\" x2=\\\"268\\\" y2=\\\"55\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"124\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DISPONIBILITÉ</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"273\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"558\\\" y1=\\\"56\\\" x2=\\\"446\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"347\\\" y1=\\\"56\\\" x2=\\\"446\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"446\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"433\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"472\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"472\\\" y1=\\\"74\\\" x2=\\\"490\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"402\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"558\\\" y1=\\\"56\\\" x2=\\\"670\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"782\\\" y1=\\\"56\\\" x2=\\\"670\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"670\\\" cy=\\\"56\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"657\\\" y=\\\"60.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"626\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"626\\\" y1=\\\"74\\\" x2=\\\"644\\\" y2=\\\"74\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"695\\\" y=\\\"72\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PAYS -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"48\\\" x2=\\\"87\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"24\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PAYS</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">code pays</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"68\\\" x2=\\\"79\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"82.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom pays</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PRODUIT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"39\\\" width=\\\"100\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"297\\\" y=\\\"9\\\" width=\\\"100\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"297\\\" y1=\\\"39\\\" x2=\\\"397\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"306\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PRODUIT</text>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. produit</text>\\n\",\n       \"\\t<line x1=\\\"305\\\" y1=\\\"59\\\" x2=\\\"377\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">libellé</text>\\n\",\n       \"\\t<text x=\\\"305\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">prix unitaire</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity LIGNE_COM_ -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"26\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"56\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"495\\\" y=\\\"26\\\" width=\\\"126\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"495\\\" y1=\\\"56\\\" x2=\\\"621\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"47.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">LIGNE COM.</text>\\n\",\n       \"\\t<text x=\\\"503\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">quantité</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMMANDE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"39\\\" width=\\\"126\\\" height=\\\"64\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"719\\\" y=\\\"9\\\" width=\\\"126\\\" height=\\\"94\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"719\\\" y1=\\\"39\\\" x2=\\\"845\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"728\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMMANDE</text>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. commande</text>\\n\",\n       \"\\t<line x1=\\\"727\\\" y1=\\\"59\\\" x2=\\\"831\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<text x=\\\"727\\\" y=\\\"90\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">montant</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **COMMANDE** (<u>num. commande</u>, date, montant)\\n\",\n       \"- **DISPONIBILITÉ** (<u>_#réf. produit_</u>, <u>_#code pays_</u>)\\n\",\n       \"- **LIGNE COM.** (<u>_#num. commande_</u>, <u>_#réf. produit_</u>, quantité)\\n\",\n       \"- **PAYS** (<u>code pays</u>, nom pays)\\n\",\n       \"- **PRODUIT** (<u>réf. produit</u>, libellé, prix unitaire)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i=sandbox --mld -t explode:arity=2.5,weak arrange:wide --seed=1\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Cas des agrégats.** Comme on sait, la notion d'entité faible peut souvent permettre de se passer de celle d'agrégat. Ainsi, le MCD ci-dessous :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 159,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"432\\\" height=\\\"197\\\" viewBox=\\\"0 0 432 197\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"432\\\" height=\\\"197\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RESERVATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"324\\\" cy=\\\"56\\\" r=\\\"6\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1\\\" fill=\\\"#c0d4ff55\\\"/>\\n\",\n       \"\\t<line x1=\\\"372\\\" y1=\\\"56\\\" x2=\\\"227\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"71\\\" y1=\\\"56\\\" x2=\\\"227\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"227\\\" y1=\\\"149\\\" x2=\\\"227\\\" y2=\\\"56\\\" stroke=\\\"#726f83\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L289 13 a7 7 0 0 1 7 7 L296 177 a7 7 0 0 1 -7 7 L165 184 a7 7 0 0 1 -7 -7 L158 106 a7 7 0 0 0 -7 -7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.3\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L289 13 a7 7 0 0 1 7 7 L296 177 a7 7 0 0 1 -7 7 L165 184 a7 7 0 0 1 -7 -7 L158 106 a7 7 0 0 0 -7 -7 L20 99 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M277 27 a14 14 90 0 1 14 14 V55 h-128 V41 a14 14 90 0 1 14 -14\\\" fill=\\\"#b2bba4\\\" stroke=\\\"#b2bba4\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M291 55 v16 a14 14 90 0 1 -14 14 H177 a14 14 90 0 1 -14 -14 V55 H128\\\" fill=\\\"#ccd6ba\\\" stroke=\\\"#ccd6ba\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"163\\\" y=\\\"27\\\" width=\\\"128\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"163\\\" y1=\\\"55\\\" x2=\\\"291\\\" y2=\\\"55\\\" stroke=\\\"#85956b\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"171\\\" y=\\\"48.3\\\" fill=\\\"#27360c\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réservation</text>\\n\",\n       \"\\t\\t<text x=\\\"170\\\" y=\\\"73.1\\\" fill=\\\"#607734\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"301\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"134\\\" y=\\\"77\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"237\\\" y=\\\"106\\\" fill=\\\"#726f83\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"48\\\" width=\\\"106\\\" height=\\\"46\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"106\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"48\\\" x2=\\\"124\\\" y2=\\\"48\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"31\\\" y=\\\"39.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"65.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"68\\\" x2=\\\"115\\\" y2=\\\"68\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"82.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"330\\\" y=\\\"18\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"330\\\" y=\\\"48\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"330\\\" y=\\\"18\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"330\\\" y1=\\\"48\\\" x2=\\\"414\\\" y2=\\\"48\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"342\\\" y=\\\"39.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"338\\\" y=\\\"65.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. client</text>\\n\",\n       \"\\t<line x1=\\\"338\\\" y1=\\\"68\\\" x2=\\\"397\\\" y2=\\\"68\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"338\\\" y=\\\"82.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom client</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"119\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#97b8ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"149\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#c0d4ff\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"197\\\" y=\\\"119\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"197\\\" y1=\\\"149\\\" x2=\\\"257\\\" y2=\\\"149\\\" stroke=\\\"#578dff\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"206\\\" y=\\\"140.3\\\" fill=\\\"#131114\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"205\\\" y=\\\"166.1\\\" fill=\\\"#3e3c42\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"205\\\" y1=\\\"169\\\" x2=\\\"233\\\" y2=\\\"169\\\" stroke=\\\"#3e3c42\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Chambre** (<u>num. chambre</u>, tarif)\\n\",\n       \"- **Client** (<u>réf. client</u>, nom client)\\n\",\n       \"- **Réservation** (<u>_#num. chambre_</u>, <u>date</u>, _#réf. client_, durée)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t --colors ocean\\n\",\n    \"Chambre: num. chambre, tarif\\n\",\n    \"Réservation, /1N Client, 1N Chambre, 0N Date: durée\\n\",\n    \"Client: réf. client, nom client\\n\",\n    \"\\n\",\n    \"Date: date\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"... se verra décomposé de la même façon que sans agrégat, à ceci près que la patte distinguée par le `\\\"/\\\"` produira une cardinalité `11` au lieu d'une cardinalité `_11` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 160,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"534\\\" height=\\\"178\\\" viewBox=\\\"0 0 534 178\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"534\\\" height=\\\"178\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"47\\\" x2=\\\"164\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"47\\\" x2=\\\"164\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"164\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"151\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"190\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"190\\\" y1=\\\"65\\\" x2=\\\"208\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"47\\\" x2=\\\"392\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"483\\\" y1=\\\"47\\\" x2=\\\"392\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"392\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"379\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"348\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"47\\\" x2=\\\"278\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"164\\\" y1=\\\"139\\\" x2=\\\"278\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"278\\\" cy=\\\"139\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"265\\\" y=\\\"143.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"283\\\" y=\\\"93\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"283\\\" y1=\\\"95\\\" x2=\\\"301\\\" y2=\\\"95\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"199\\\" y=\\\"155\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"115\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"106\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESERVATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"17\\\" width=\\\"130\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"47\\\" width=\\\"130\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"17\\\" width=\\\"130\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"213\\\" y1=\\\"47\\\" x2=\\\"343\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"222\\\" y=\\\"38.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réservation</text>\\n\",\n       \"\\t<text x=\\\"221\\\" y=\\\"64.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"441\\\" y1=\\\"39\\\" x2=\\\"525\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"453\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"449\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. client</text>\\n\",\n       \"\\t<line x1=\\\"449\\\" y1=\\\"59\\\" x2=\\\"508\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"449\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom client</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DATE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"134\\\" y=\\\"109\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"134\\\" y=\\\"139\\\" width=\\\"60\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"134\\\" y=\\\"109\\\" width=\\\"60\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"134\\\" y1=\\\"139\\\" x2=\\\"194\\\" y2=\\\"139\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"143\\\" y=\\\"130.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Date</text>\\n\",\n       \"\\t<text x=\\\"142\\\" y=\\\"156.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"142\\\" y1=\\\"159\\\" x2=\\\"170\\\" y2=\\\"159\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Chambre** (<u>num. chambre</u>, tarif)\\n\",\n       \"- **Client** (<u>réf. client</u>, nom client)\\n\",\n       \"- **Réservation** (<u>date</u>, <u>_#num. chambre_</u>, durée, _#réf. client_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --mld -t explode:weak arrange:wide=5 --seed 21\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cette décomposition peut quelquefois se simplifier. Ici, on remarque que l'entité DATE est indépendante et réduite à son identifiant. Si l'on anticipe sur le passage au relationnel, on peut donc la supprimer, après avoir pris soin, bien sûr, de déplacer dans RÉSERVATION son unique attribut. Celui-ci renforçant une entité faible, il doit garder son caractère identifiant.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 161,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"534\\\" height=\\\"94\\\" viewBox=\\\"0 0 534 94\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"534\\\" height=\\\"94\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"47\\\" x2=\\\"164\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"62\\\" y1=\\\"47\\\" x2=\\\"164\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"164\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"151\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"190\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"190\\\" y1=\\\"65\\\" x2=\\\"208\\\" y2=\\\"65\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"278\\\" y1=\\\"47\\\" x2=\\\"392\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"483\\\" y1=\\\"47\\\" x2=\\\"392\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"392\\\" cy=\\\"47\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"379\\\" y=\\\"51.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"348\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"417\\\" y=\\\"63\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CHAMBRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"106\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"106\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"115\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"22\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Chambre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">num. chambre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"106\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">tarif</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESERVATION -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"9\\\" width=\\\"130\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"39\\\" width=\\\"130\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"213\\\" y=\\\"9\\\" width=\\\"130\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"213\\\" y1=\\\"39\\\" x2=\\\"343\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"222\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Réservation</text>\\n\",\n       \"\\t<text x=\\\"221\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">date</text>\\n\",\n       \"\\t<line x1=\\\"221\\\" y1=\\\"59\\\" x2=\\\"249\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"\\t<text x=\\\"221\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">durée</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CLIENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"46\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"441\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"76\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"441\\\" y1=\\\"39\\\" x2=\\\"525\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"453\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Client</text>\\n\",\n       \"\\t<text x=\\\"449\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">réf. client</text>\\n\",\n       \"\\t<line x1=\\\"449\\\" y1=\\\"59\\\" x2=\\\"508\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"449\\\" y=\\\"73.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">nom client</text>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Chambre** (<u>num. chambre</u>, tarif)\\n\",\n       \"- **Client** (<u>réf. client</u>, nom client)\\n\",\n       \"- **Réservation** (<u>_#num. chambre_</u>, <u>date</u>, durée, _#réf. client_)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Chambre: num. chambre, tarif\\n\",\n    \"DF, _11 Réservation, 1N Chambre\\n\",\n    \"Réservation: date, durée\\n\",\n    \"DF, 11 Réservation, 1N Client\\n\",\n    \"Client: réf. client, nom client\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Conclusion sur ces décompositions\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Comme l'indique le nom que nous leur avons malicieusement attribué, certaines de ces décompositions peuvent littéralement faire _exploser_ la taille du MCD. Cependant :\\n\",\n    \"\\n\",\n    \"- elles sont intéressantes d'un point de vue <s>terroriste</s> théorique ;\\n\",\n    \"- elles peuvent permettre la détection d'erreurs de conception ;\\n\",\n    \"- elles peuvent conduire à des améliorations fines du MCD (c'est ce qu'on a fait sur celui des réservations de chambre) ;\\n\",\n    \"- elles décrivent le MCD dans un langage volontairement appauvri, ce qui le rendra plus aisément portable dans une autre notation, comme UML ou _crow's foot_.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Équivalences avec la convention _Look Across_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La convention _Look Across_ s'oppose à la convention _Look Here_ de Merise. Elle est plus répandue internationalement. \\n\",\n    \"Nous allons l'étudier par le biais du formalisme graphique de Chen, auquel cette section pourra du même coup servir d'introduction pour les personnes familières avec Merise.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Associations binaires en _Look Across_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Cardinalités minimale et maximale\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Considérons un MCD Merise avec une association de dépendance fonctionnelle :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 162,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"418\\\" height=\\\"78\\\" viewBox=\\\"0 0 418 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"418\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association TRAVAILLER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"342\\\" y1=\\\"39\\\" x2=\\\"189\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"56\\\" y1=\\\"39\\\" x2=\\\"189\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M232 10 a14 14 90 0 1 14 14 V38 h-114 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M246 38 v16 a14 14 90 0 1 -14 14 H146 a14 14 90 0 1 -14 -14 V38 H114\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"10\\\" width=\\\"114\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"38\\\" x2=\\\"246\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"139\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Travailler</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"252\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"103\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Employé</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">employé</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"71\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity DEPARTEMENT -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"275\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"275\\\" y=\\\"39\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"275\\\" y=\\\"9\\\" width=\\\"134\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"275\\\" y1=\\\"39\\\" x2=\\\"409\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"283\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Département</text>\\n\",\n       \"\\t<text x=\\\"283\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">département</text>\\n\",\n       \"\\t<line x1=\\\"283\\\" y1=\\\"59\\\" x2=\\\"364\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Employé: employé\\n\",\n    \"Travailler, 11 Département, 1N Employé\\n\",\n    \"Département: département\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans le formalisme graphique de Chen, cela donnera :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 163,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjQ4MHB0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNDc5LjY1IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDQ3NS42NSwtNTQuNCA0NzUuNjUsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNzguMjUsLTQzLjIgMCwtNDMuMiAwLC03LjIgNzguMjUsLTcuMiA3OC4yNSwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzOS4xMiIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkVtcGxvecOpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjE5LjcsLTUwLjQgMTUwLjI1LC0yNS4yIDIxOS43LDAgMjg5LjE1LC0yNS4yIDIxOS43LC01MC40Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIxOS43IiB5PSItMjAuNTMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+VHJhdmFpbGxlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik03OC4zMSwtMjQuMkM5OC45NSwtMjQuMiAxMjQuOSwtMjQuMiAxNDguOTIsLTI0LjIiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzguMzEsLTI2LjJDOTguOTUsLTI2LjIgMTI0LjksLTI2LjIgMTQ4LjkyLC0yNi4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEzMC44IiB5PSItMjguOTgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjQ3MS42NSwtNDMuMiAzNjEuMTUsLTQzLjIgMzYxLjE1LC03LjIgNDcxLjY1LC03LjIgNDcxLjY1LC00My4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjQxNi40IiB5PSItMjAuNTMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+RMOpcGFydGVtZW50PC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTM2MC44MiwtMjYuMkMzMzkuMDEsLTI2LjIgMzEzLjcxLC0yNi4yIDI5MC42MSwtMjYuMiIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0zNjAuODIsLTI0LjJDMzM5LjAxLC0yNC4yIDMxMy43MSwtMjQuMiAyOTAuNjEsLTI0LjIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzA4LjczIiB5PSItMTIuMDciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le 1 et le N correspondent aux cardinalités maximales du MCD Merise. Comme on voit, elles sont permutées. Merise suit la convention _Look Here_ (LH) ; la notation de Chen, _Look Across_ (LA). Comme cette dernière est la plus répandue dans le monde anglo-saxon, nous parlerons par commodité d'« ERD » (_Entity-relationship diagram_) pour les modèles conceptuels selon Chen, et toujours de « MCD » pour ceux de Merise.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Considérons maintenant les deux versions d'une association avec des cardinalités minimales distinctes :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 164,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"310\\\" height=\\\"78\\\" viewBox=\\\"0 0 310 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"310\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association RECEVOIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"259\\\" y1=\\\"39\\\" x2=\\\"140\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"36\\\" y1=\\\"39\\\" x2=\\\"140\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M174 10 a14 14 90 0 1 14 14 V38 h-96 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M188 38 v16 a14 14 90 0 1 -14 14 H106 a14 14 90 0 1 -14 -14 V38 H96\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"96\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"92\\\" y1=\\\"38\\\" x2=\\\"188\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"99\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Recevoir</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,1</text>\\n\",\n       \"\\t<text x=\\\"68\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity MER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"54\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"63\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Mer</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">mer</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"43\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RIVIERE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"39\\\" width=\\\"84\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"217\\\" y=\\\"9\\\" width=\\\"84\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"217\\\" y1=\\\"39\\\" x2=\\\"301\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"226\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Rivière</text>\\n\",\n       \"\\t<text x=\\\"225\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">rivière</text>\\n\",\n       \"\\t<line x1=\\\"225\\\" y1=\\\"59\\\" x2=\\\"266\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Mer: mer\\n\",\n    \"Recevoir, 01 Rivière, 1N Mer\\n\",\n    \"Rivière: rivière\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 165,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjQwMXB0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNDAwLjg3IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDM5Ni44NywtNTQuNCAzOTYuODcsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNTQsLTQzLjIgMCwtNDMuMiAwLC03LjIgNTQsLTcuMiA1NCwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyNyIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk1lcjwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjE4OS45MywtNTAuNCAxMjYsLTI1LjIgMTg5LjkzLDAgMjUzLjg3LC0yNS4yIDE4OS45MywtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODkuOTMiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5SZWNldm9pcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01NC4yNywtMjQuMkM3My41NywtMjQuMiAxMDAuMjksLTI0LjIgMTI0LjkxLC0yNC4yIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTU0LjI3LC0yNi4yQzczLjU3LC0yNi4yIDEwMC4yOSwtMjYuMiAxMjQuOTEsLTI2LjIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTA2Ljc5IiB5PSItMjguOTgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjM5Mi44NywtNDMuMiAzMjUuODcsLTQzLjIgMzI1Ljg3LC03LjIgMzkyLjg3LC03LjIgMzkyLjg3LC00My4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM1OS4zNyIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJpdmnDqHJlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTMyNS40OSwtMjUuMkMzMDUuMywtMjUuMiAyNzkuMDEsLTI1LjIgMjU0Ljk2LC0yNS4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI3My4wOCIgeT0iLTEyLjA3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPC9nPgo8L3N2Zz4K\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les cardinalités maximales sont toujours permutées ; par contre, les cardinalités minimales ne le sont pas. Dans l'ERD, elles sont figurées par un trait simple (0) ou double (1). On les appelle aussi des « participations » : une rivière peut ne participer (directement) à l'alimentation d'aucune mer (ce n'est pas un fleuve) ; toute mer participe à la réception d'une rivière (un fleuve) minimum. Les conventions sont donc les suivantes :\\n\",\n    \"\\n\",\n    \"| Cardinalités | MCD Merise | ERD Chen |\\n\",\n    \"|:--|:--:|:--:|\\n\",\n    \"| minimale | LH | LH |\\n\",\n    \"| maximale | LH | LA |\\n\",\n    \"\\n\",\n    \"La notation Merise a l'avantage de la cohérence ; celle de Chen en a d'autres, que nous verrons un peu plus loin.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Avant cela, voyons un dernier point de détail : lorsque deux cardinalités N se trouvent de part et d'autre d'une association binaire, l'une est notée M :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 166,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"497\\\" height=\\\"78\\\" viewBox=\\\"0 0 497 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"497\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association REQUERIR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"53\\\" y1=\\\"39\\\" x2=\\\"182\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"303\\\" y1=\\\"39\\\" x2=\\\"182\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M224 10 a14 14 90 0 1 14 14 V38 h-112 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M238 38 v16 a14 14 90 0 1 -14 14 H140 a14 14 90 0 1 -14 -14 V38 H112\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"126\\\" y=\\\"10\\\" width=\\\"112\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"126\\\" y1=\\\"38\\\" x2=\\\"238\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"134\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">REQUÉRIR</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"102\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"243\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association COMPOSER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<path d=\\\"M303 39 C328.67 7 370.33 7 428 39\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<path d=\\\"M303 39 C328.67 71 370.33 71 428 39\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M474 10 a14 14 90 0 1 14 14 V38 h-120 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M488 38 v16 a14 14 90 0 1 -14 14 H382 a14 14 90 0 1 -14 -14 V38 H120\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"368\\\" y=\\\"10\\\" width=\\\"120\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"368\\\" y1=\\\"38\\\" x2=\\\"488\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"375\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">COMPOSER</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"344\\\" y=\\\"32\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"344\\\" y=\\\"54\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"88\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"88\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"97\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PROJET</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"56\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PIECE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"267\\\" y=\\\"9\\\" width=\\\"72\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"267\\\" y=\\\"39\\\" width=\\\"72\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"267\\\" y=\\\"9\\\" width=\\\"72\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"267\\\" y1=\\\"39\\\" x2=\\\"339\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"275\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">PIÈCE</text>\\n\",\n       \"\\t<text x=\\\"275\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">pièce</text>\\n\",\n       \"\\t<line x1=\\\"275\\\" y1=\\\"59\\\" x2=\\\"308\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"PROJET: projet\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE\\n\",\n    \"PIÈCE: pièce\\n\",\n    \"COMPOSER, 0N PIÈCE, 0N PIÈCE\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 167,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjY4N3B0IiBoZWlnaHQ9IjU4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNjg2Ljc5IDU4LjQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDU0LjQpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC01NC40IDY4Mi43OSwtNTQuNCA2ODIuNzksNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNzIuMjUsLTQzLjIgMCwtNDMuMiAwLC03LjIgNzIuMjUsLTcuMiA3Mi4yNSwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNi4xMiIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlBST0pFVDwvdGV4dD4KPC9nPgo8IS0tIDIgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MjwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIyMy41LC01MC40IDE0NC4yNSwtMjUuMiAyMjMuNSwwIDMwMi43NiwtMjUuMiAyMjMuNSwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjMuNSIgeT0iLTIwLjUzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJFUVXDiVJJUjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik03Mi43LC0yNC4yQzkyLjcyLC0yNC4yIDExOC4zNywtMjQuMiAxNDIuODIsLTI0LjIiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzIuNywtMjYuMkM5Mi43MiwtMjYuMiAxMTguMzcsLTI2LjIgMTQyLjgyLC0yNi4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEyNC42OSIgeT0iLTI4Ljk4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI0MzcuMjYsLTQzLjIgMzc0Ljc2LC00My4yIDM3NC43NiwtNy4yIDQzNy4yNiwtNy4yIDQzNy4yNiwtNDMuMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0MDYuMDEiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5QScOIQ0U8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMzc0LjYzLC0yNS4yQzM1NS4xNywtMjUuMiAzMjkuMTksLTI1LjIgMzA0LjI3LC0yNS4yIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMyMi40IiB5PSItMTIuMDciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TTwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjU5NC4wMiwtNTAuNCA1MDkuMjYsLTI1LjIgNTk0LjAyLDAgNjc4Ljc5LC0yNS4yIDU5NC4wMiwtNTAuNCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI1OTQuMDIiIHk9Ii0yMC41MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DT01QT1NFUjwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyYjNDU7NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmIzQ1OzQ8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik00MzcuNDgsLTMwLjM5QzQ2Mi40NiwtMzEuODkgNDk4LjIzLC0zMi4zMSA1MjkuMjcsLTMxLjY1Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjUxMS4zIiB5PSItMzUuNzQiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TTwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MyAtLT4KPGcgaWQ9ImVkZ2U0IiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzM8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01MjkuMzIsLTE4Ljc1QzQ5OC4zLC0xOC4wOSA0NjIuNTUsLTE4LjUxIDQzNy41NiwtMjAiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDU1LjIxIiB5PSItNS45MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Entités faibles et entités associatives\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Maintenant examinons le cas des entités faibles :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 168,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"314\\\" height=\\\"78\\\" viewBox=\\\"0 0 314 78\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"314\\\" height=\\\"78\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"48\\\" y1=\\\"39\\\" x2=\\\"136\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"245\\\" y1=\\\"39\\\" x2=\\\"136\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"136\\\" cy=\\\"39\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"123\\\" y=\\\"43.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"92\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"162\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"162\\\" y1=\\\"57\\\" x2=\\\"180\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity OEUVRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"87\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Œuvre</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">œuvre</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"58\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EXEMPLAIRE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"185\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"185\\\" y=\\\"39\\\" width=\\\"120\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"185\\\" y=\\\"9\\\" width=\\\"120\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"185\\\" y1=\\\"39\\\" x2=\\\"305\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"194\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Exemplaire</text>\\n\",\n       \"\\t<text x=\\\"193\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">exemplaire</text>\\n\",\n       \"\\t<line x1=\\\"193\\\" y1=\\\"59\\\" x2=\\\"262\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"4\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Œuvre: œuvre\\n\",\n    \"DF, 0N Œuvre, _11 Exemplaire\\n\",\n    \"Exemplaire: exemplaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 169,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjM5NXB0IiBoZWlnaHQ9IjY5cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMzk0LjcwIDY4LjgyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDY0LjgyKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtNjQuODIgMzkwLjcsLTY0LjgyIDM5MC43LDQgLTQsNCIvPgo8IS0tIDEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjY0LC00OC40MSAwLC00OC40MSAwLC0xMi40MSA2NCwtMTIuNDEgNjQsLTQ4LjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjMyIiB5PSItMjUuNzMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+xZJ1dnJlPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTcyLjQ4LC01NS42MSAxNDIuMjUsLTMwLjQxIDE3Mi40OCwtNS4yMSAyMDIuNzEsLTMwLjQxIDE3Mi40OCwtNTUuNjEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTcyLjQ4LC02MC44MiAxMzYsLTMwLjQxIDE3Mi40OCwwIDIwOC45NSwtMzAuNDEgMTcyLjQ4LC02MC44MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzIuNDgiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5ERjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik02NC4yMywtMzAuNDFDODUuNDUsLTMwLjQxIDExMy4zLC0zMC40MSAxMzUuNDQsLTMwLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjExNy4zMSIgeT0iLTM0LjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIzODIuNywtNDguNDEgMjg0Ljk1LC00OC40MSAyODQuOTUsLTEyLjQxIDM4Mi43LC0xMi40MSAzODIuNywtNDguNDEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMzg2LjcsLTUyLjQxIDI4MC45NSwtNTIuNDEgMjgwLjk1LC04LjQxIDM4Ni43LC04LjQxIDM4Ni43LC01Mi40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzMzMuODMiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5FeGVtcGxhaXJlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTIiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTI4MC41NSwtMzEuNDFDMjU3LjIzLC0zMS40MSAyMzAuNDUsLTMxLjQxIDIwOS4zOSwtMzEuNDEiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMjgwLjU1LC0yOS40MUMyNTcuMjMsLTI5LjQxIDIzMC40NSwtMjkuNDEgMjA5LjM5LC0yOS40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMjcuNTEiIHk9Ii0xNy4yOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'entité faible, à l'instar de la DF « renforçante », sont entourées d'un double trait.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le vocabulaire de Chen comporte encore un élément graphique, que Merise ne distingue pas spécialement. Nous avons vu que toute association non DF pouvait être décomposée de façon équivalente par l'insertion d'entités faibles :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"Produit: produit\\n\",\n    \"DF, _11 Ligne de commande, 0N Produit\\n\",\n    \"Ligne de commande: _quantité\\n\",\n    \"DF, _11 Ligne de commande, 1N Commande\\n\",\n    \"Commande: commande\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"LIGNE DE COMMANDE est quelquefois qualifiée d'« entité associative », et Chen la figure logiquement par un losange (association) inscrit dans un rectangle (entité). Graphviz ne prend actuellement [pas](https://stackoverflow.com/questions/48046186/is-it-possible-to-have-nested-node-shapes-on-graphviz) en charge cette représentation. Nous l'approximons donc ainsi :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 170,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjM2MHB0IiBoZWlnaHQ9IjY5cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMzYwLjM3IDY4LjgyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGcgaWQ9ImdyYXBoMCIgY2xhc3M9ImdyYXBoIiB0cmFuc2Zvcm09InNjYWxlKDEgMSkgcm90YXRlKDApIHRyYW5zbGF0ZSg0IDY0LjgyKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtNjQuODIgMzU2LjM3LC02NC44MiAzNTYuMzcsNCAtNCw0Ii8+CjwhLS0gMSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4xPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iNjQsLTQ4LjQxIDAsLTQ4LjQxIDAsLTEyLjQxIDY0LC0xMi40MSA2NCwtNDguNDEiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzIiIHk9Ii0yNS43MyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj7FknV2cmU8L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxNTkuNDksLTU1LjYxIDEyOS4yNiwtMzAuNDEgMTU5LjQ5LC01LjIxIDE4OS43MiwtMzAuNDEgMTU5LjQ5LC01NS42MSIvPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxNTkuNDksLTYwLjgyIDEyMy4wMSwtMzAuNDEgMTU5LjQ5LDAgMTk1Ljk2LC0zMC40MSAxNTkuNDksLTYwLjgyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE1OS40OSIgeT0iLTI1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkRGPC90ZXh0Pgo8L2c+CjwhLS0gMSYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjEmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTY0LjE3LC0zMC40MUM4MS44NywtMzAuNDEgMTAzLjkyLC0zMC40MSAxMjIuMzYsLTMwLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjEwNC4yMyIgeT0iLTM0LjE4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPjE8L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIzNDguMzcsLTQ4LjQxIDI1MC42MiwtNDguNDEgMjUwLjYyLC0xMi40MSAzNDguMzcsLTEyLjQxIDM0OC4zNywtNDguNDEiLz4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMzUyLjM3LC01Mi40MSAyNDYuNjIsLTUyLjQxIDI0Ni42MiwtOC40MSAzNTIuMzcsLTguNDEgMzUyLjM3LC01Mi40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOTkuNSIgeT0iLTI1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkV4ZW1wbGFpcmU8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMjQ2LjE3LC0zMS40MUMyMjkuNjMsLTMxLjQxIDIxMS43NywtMzEuNDEgMTk2LjU5LC0zMS40MSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0yNDYuMTcsLTI5LjQxQzIyOS42MywtMjkuNDEgMjExLjc3LC0yOS40MSAxOTYuNTksLTI5LjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjIxNC43MiIgeT0iLTE3LjI4IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPC9nPgo8L3N2Zz4K\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo,mindist=2,scale=0.6 --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Associations n-aires en _Look Across_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Triplet NNN\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Passons maintenant aux choses sérieuses. Jusqu'ici, la différence entre les deux notations était purement cosmétique. Qu'en est-il des associations n-aires, et que signifie _Look Across_ quand _across_ peut désigner plusieurs endroits ?\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 171,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"356\\\" height=\\\"162\\\" viewBox=\\\"0 0 356 162\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"356\\\" height=\\\"162\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association APPLIQUER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"56\\\" y1=\\\"39\\\" x2=\\\"186\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"308\\\" y1=\\\"39\\\" x2=\\\"186\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"186\\\" y1=\\\"123\\\" x2=\\\"186\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M226 10 a14 14 90 0 1 14 14 V38 h-108 V24 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M240 38 v16 a14 14 90 0 1 -14 14 H146 a14 14 90 0 1 -14 -14 V38 H108\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"132\\\" y=\\\"10\\\" width=\\\"108\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"132\\\" y1=\\\"38\\\" x2=\\\"240\\\" y2=\\\"38\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"140\\\" y=\\\"31.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Appliquer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"108\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"\\t<text x=\\\"245\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"191\\\" y=\\\"85\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"39\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"94\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"39\\\" x2=\\\"103\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"18\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Employé</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">employé</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"59\\\" x2=\\\"71\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"269\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"269\\\" y1=\\\"39\\\" x2=\\\"347\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"277\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"277\\\" y1=\\\"59\\\" x2=\\\"316\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity COMPETENCE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"123\\\" y=\\\"93\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"123\\\" y=\\\"123\\\" width=\\\"126\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"123\\\" y=\\\"93\\\" width=\\\"126\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"123\\\" y1=\\\"123\\\" x2=\\\"249\\\" y2=\\\"123\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"132\\\" y=\\\"114.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Compétence</text>\\n\",\n       \"\\t<text x=\\\"131\\\" y=\\\"140.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">compétence</text>\\n\",\n       \"\\t<line x1=\\\"131\\\" y1=\\\"143\\\" x2=\\\"208\\\" y2=\\\"143\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Appliquer** (<u>employé</u>, <u>projet</u>, <u>compétence</u>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t\\n\",\n    \"Employé: employé\\n\",\n    \"Appliquer, 0N Employé, 1N Projet, 1N Compétence\\n\",\n    \"Projet: projet\\n\",\n    \"\\n\",\n    \"Compétence: compétence\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans ce cas (le plus usuel), la question ne se pose pas vraiment, ou du moins n'est pas tranchée de façon évidente :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 172,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI2MHB0IiBoZWlnaHQ9IjE5OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI2MC4yNiAxOTkuNDUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTk1LjQ1KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTk1LjQ1IDI1Ni4yNiwtMTk1LjQ1IDI1Ni4yNiw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI3OC4yNSwtMTEzLjcyIDAsLTExMy43MiAwLC03Ny43MiA3OC4yNSwtNzcuNzIgNzguMjUsLTExMy43MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzOS4xMiIgeT0iLTkxLjA1IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkVtcGxvecOpPC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTgyLjIsLTEyMC45MiAxMTIuMTQsLTk1LjcyIDE4Mi4yLC03MC41MiAyNTIuMjYsLTk1LjcyIDE4Mi4yLC0xMjAuOTIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii05MS4wNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BcHBsaXF1ZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMyIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNNzguNiwtOTUuNzJDODguNjEsLTk1LjcyIDk5LjY3LC05NS43MiAxMTAuNzMsLTk1LjcyIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjkyLjYxIiB5PSItOTkuNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwhLS0gMyAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4zPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjExLjk1LC0zNiAxNTIuNDUsLTM2IDE1Mi40NSwwIDIxMS45NSwwIDIxMS45NSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5Qcm9qZXQ8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTgzLjIsLTM2LjQyQzE4My4yLC00Ni40OCAxODMuMiwtNTkuMDggMTgzLjIsLTcwLjA5Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE4MS4yLC0zNi40MkMxODEuMiwtNDYuNDggMTgxLjIsLTU5LjA4IDE4MS4yLC03MC4wOSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzMuNzUiIHk9Ii00Ny4yOCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwhLS0gNCAtLT4KPGcgaWQ9Im5vZGUzIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT40PC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjM0LjQ1LC0xOTEuNDUgMTI5Ljk1LC0xOTEuNDUgMTI5Ljk1LC0xNTUuNDUgMjM0LjQ1LC0xNTUuNDUgMjM0LjQ1LC0xOTEuNDUiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTgyLjIiIHk9Ii0xNjguNzciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+Q29tcMOpdGVuY2U8L3RleHQ+CjwvZz4KPCEtLSA0JiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+NCYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTgxLjIsLTE1NS4wM0MxODEuMiwtMTQ0Ljk3IDE4MS4yLC0xMzIuMzcgMTgxLjIsLTEyMS4zNiIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODMuMiwtMTU1LjAzQzE4My4yLC0xNDQuOTcgMTgzLjIsLTEzMi4zNyAxODMuMiwtMTIxLjM2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5MC42NSIgeT0iLTEzNC44MSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5OPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t chen:layout=circo,mindist=1,scale=0.4 --defer\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Quels sont les autres cas ? Il ne s'agit pas de ceux où l'association n-aire est entourée d'une ou plusieurs cardinalités maximale 1, puisqu'on pourrait alors la décomposer en DF binaires (cf. argument `split`). En réalité, on touche ici aux limites de la notation _Look Here_, plus intuitive, mais moins puissante que _Look Across_, et que Merise n'a pu rattraper que dans sa version 2.\\n\",\n    \"\\n\",\n    \"Pour répondre progressivement à la question, procédons désormais dans l'ordre inverse, en présentant d'abord l'ERD, et ensuite seulement le MCD équivalent.\\n\",\n    \"\\n\",\n    \"Les exemples qui suivent (ainsi d'ailleurs que le précédent), sont adaptés des pages 28 sqq. et 96 sqq. de l'ouvrage de Toby J. Teorey, Sam S. Lightstone, Tom Nadeau, H.V. Jagadish, _Database Modeling and Design - Logical Design_, 5th Edition - February 10, 2011 (Elsevier).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Triplet 1NN\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le premier ERD apportant véritablement quelque chose de nouveau a cette structure :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 173,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI1NnB0IiBoZWlnaHQ9IjE5OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI1Ni4xNyAxOTguNjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTk0LjYpIj4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC0xOTQuNiAyNTIuMTcsLTE5NC42IDI1Mi4xNyw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI4NSwtMTEzLjMgMCwtMTEzLjMgMCwtNzcuMyA4NSwtNzcuMyA4NSwtMTEzLjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNDIuNSIgeT0iLTkwLjYyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkluZ8OpbmlldXI8L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxOTUuMTcsLTEyMC41IDE0OC40LC05NS4zIDE5NS4xNywtNzAuMSAyNDEuOTUsLTk1LjMgMTk1LjE3LC0xMjAuNSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxOTUuMTciIHk9Ii05MC42MiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5Hw6lyZXI8L3RleHQ+CjwvZz4KPCEtLSAxJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MSYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNODUuNDMsLTk0LjNDMTA0Ljc1LC05NC4zIDEyNy42MiwtOTQuMyAxNDcuNDcsLTk0LjMiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNODUuNDMsLTk2LjNDMTA0Ljc1LC05Ni4zIDEyNy42MiwtOTYuMyAxNDcuNDcsLTk2LjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTI5LjM0IiB5PSItOTkuMDgiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIyNC45MiwtMzYgMTY1LjQyLC0zNiAxNjUuNDIsMCAyMjQuOTIsMCAyMjQuOTIsLTM2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5NS4xNyIgeT0iLTEzLjMyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlByb2pldDwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xOTYuMTcsLTM2LjMyQzE5Ni4xNywtNDYuMzIgMTk2LjE3LC01OC44NiAxOTYuMTcsLTY5LjgiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTk0LjE3LC0zNi4zMkMxOTQuMTcsLTQ2LjMyIDE5NC4xNywtNTguODYgMTk0LjE3LC02OS44Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4Ni43MiIgeT0iLTQ3IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPk48L3RleHQ+CjwvZz4KPCEtLSAzIC0tPgo8ZyBpZD0ibm9kZTMiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjM8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIyNDguMTcsLTE5MC42IDE0Mi4xNywtMTkwLjYgMTQyLjE3LC0xNTQuNiAyNDguMTcsLTE1NC42IDI0OC4xNywtMTkwLjYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTk1LjE3IiB5PSItMTY3LjkyIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlJlc3BvbnNhYmxlPC90ZXh0Pgo8L2c+CjwhLS0gMyYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTEiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjMmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE5NC4xNywtMTU0LjI4QzE5NC4xNywtMTQ0LjI4IDE5NC4xNywtMTMxLjc0IDE5NC4xNywtMTIwLjgiLz4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTk2LjE3LC0xNTQuMjhDMTk2LjE3LC0xNDQuMjggMTk2LjE3LC0xMzEuNzQgMTk2LjE3LC0xMjAuOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyMDMuNjMiIHk9Ii0xMzQuMjUiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer\\n\",\n    \"Ingénieur: ingénieur\\n\",\n    \"Gérer, /1N Responsable, 1N Ingénieur, 1N Projet\\n\",\n    \"Projet: projet\\n\",\n    \"\\n\",\n    \"Responsable: responsable\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les auteurs explicitent ainsi ses règles de gestion :\\n\",\n    \"\\n\",\n    \"> _Chaque ingénieur travaillant sur un projet particulier a exactement un responsable, mais chaque responsable d'un projet peut gérer plusieurs ingénieurs, et chaque responsable d'un ingénieur peut gérer cet ingénieur sur plusieurs projets._\\n\",\n    \"\\n\",\n    \"Reprenons ces trois assertions, et faisons-les correspondre au trois cardinalités dans le sens anti-horaire à partir du 1 :\\n\",\n    \"\\n\",\n    \"- 1 : pour un couple (ingénieur, projet) donné, un seul responsable possible ;\\n\",\n    \"- N : pour un couple (responsable, projet) donné, plusieurs ingénieurs possibles ;\\n\",\n    \"- N : pour un couple (responsable, ingénieur) donné, plusieurs projets possibles.\\n\",\n    \"\\n\",\n    \"Avec Merise, les assertions seraient plutôt du type : « pour un x donné, _tant_ de couples (y, z) possibles ». Il y a donc bien permutation, mais permutation des références au singleton et au $n-1$-uplet.\\n\",\n    \"\\n\",\n    \"C'est la réponse à notre question initiale, et nous verrons avec plaisir qu'elle reste valable quel que soit le triplet de cardinalités de l'association ternaire.\\n\",\n    \"\\n\",\n    \"Pour l'instant, résumons les règles de gestion par cette **unique** dépendance fonctionnelle :\\n\",\n    \"\\n\",\n    \"- (Ingénieur, Projet) $\\\\implies$ Responsable.\\n\",\n    \"\\n\",\n    \"Pour exprimer cela en (ou en dépit de) _Look Here_, on doit recourir à un agrégat :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 174,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"370\\\" height=\\\"190\\\" viewBox=\\\"0 0 370 190\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"370\\\" height=\\\"190\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association GERER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"200\\\" cy=\\\"106\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"200\\\" y1=\\\"142\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"72\\\" y1=\\\"48\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"313\\\" y1=\\\"48\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L350 13 a7 7 0 0 1 7 7 L357 76 a7 7 0 0 1 -7 7 L20 83 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.3\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M20 13 L350 13 a7 7 0 0 1 7 7 L357 76 a7 7 0 0 1 -7 7 L20 83 a7 7 0 0 1 -7 -7 L13 20 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M221 19 a14 14 90 0 1 14 14 V47 h-70 V33 a14 14 90 0 1 14 -14\\\" fill=\\\"#9ebd6d\\\" stroke=\\\"#9ebd6d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M235 47 v16 a14 14 90 0 1 -14 14 H179 a14 14 90 0 1 -14 -14 V47 H70\\\" fill=\\\"#c3dbbb\\\" stroke=\\\"#c3dbbb\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"165\\\" y=\\\"19\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"165\\\" y1=\\\"47\\\" x2=\\\"235\\\" y2=\\\"47\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"40.3\\\" fill=\\\"#3d484a\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Gérer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"210\\\" y=\\\"99\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"136\\\" y=\\\"69\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"245\\\" y=\\\"69\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity INGENIEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"48\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"108\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"48\\\" x2=\\\"126\\\" y2=\\\"48\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"39.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ingénieur</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"65.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ingénieur</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"68\\\" x2=\\\"84\\\" y2=\\\"68\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"274\\\" y1=\\\"48\\\" x2=\\\"352\\\" y2=\\\"48\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"39.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"65.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"282\\\" y1=\\\"68\\\" x2=\\\"321\\\" y2=\\\"68\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESPONSABLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"112\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"142\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"112\\\" width=\\\"134\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"133\\\" y1=\\\"142\\\" x2=\\\"267\\\" y2=\\\"142\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"133.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Responsable</text>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"159.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">responsable</text>\\n\",\n       \"\\t<line x1=\\\"141\\\" y1=\\\"162\\\" x2=\\\"216\\\" y2=\\\"162\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Gérer** (<u>ingénieur</u>, <u>projet</u>, responsable)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --mld --colors pond\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"… ou à une CIF à unicité complète (ici en notation allégée) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 175,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"370\\\" height=\\\"190\\\" viewBox=\\\"0 0 370 190\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"370\\\" height=\\\"190\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"200\\\" y1=\\\"48\\\" x2=\\\"72\\\" y2=\\\"142\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"133 142 121 148 125 142 121 136\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"200\\\" y1=\\\"142\\\" x2=\\\"72\\\" y2=\\\"142\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"72\\\" cy=\\\"142\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"63.5\\\" y=\\\"146.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association GERER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"200\\\" y1=\\\"142\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"72\\\" y1=\\\"48\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"313\\\" y1=\\\"48\\\" x2=\\\"200\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M221 19 a14 14 90 0 1 14 14 V47 h-70 V33 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M235 47 v16 a14 14 90 0 1 -14 14 H179 a14 14 90 0 1 -14 -14 V47 H70\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"165\\\" y=\\\"19\\\" width=\\\"70\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"165\\\" y1=\\\"47\\\" x2=\\\"235\\\" y2=\\\"47\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"172\\\" y=\\\"40.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Gérer</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"210\\\" y=\\\"99\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"136\\\" y=\\\"69\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"245\\\" y=\\\"69\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity INGENIEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"48\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"18\\\" y=\\\"18\\\" width=\\\"108\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"18\\\" y1=\\\"48\\\" x2=\\\"126\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"27\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ingénieur</text>\\n\",\n       \"\\t<text x=\\\"26\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ingénieur</text>\\n\",\n       \"\\t<line x1=\\\"26\\\" y1=\\\"68\\\" x2=\\\"84\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"48\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"274\\\" y=\\\"18\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"274\\\" y1=\\\"48\\\" x2=\\\"352\\\" y2=\\\"48\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"39.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"282\\\" y=\\\"65.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"282\\\" y1=\\\"68\\\" x2=\\\"321\\\" y2=\\\"68\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESPONSABLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"112\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"142\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"133\\\" y=\\\"112\\\" width=\\\"134\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"133\\\" y1=\\\"142\\\" x2=\\\"267\\\" y2=\\\"142\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"133.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Responsable</text>\\n\",\n       \"\\t<text x=\\\"141\\\" y=\\\"159.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">responsable</text>\\n\",\n       \"\\t<line x1=\\\"141\\\" y1=\\\"162\\\" x2=\\\"216\\\" y2=\\\"162\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Gérer** (<u>ingénieur</u>, <u>projet</u>, responsable)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --mld -t create:cifs=light arrange:balanced --seed=3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"... Ou encore à une entité faible :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 176,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"328\\\" height=\\\"228\\\" viewBox=\\\"0 0 328 228\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"328\\\" height=\\\"228\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association DF0 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"192\\\" y1=\\\"114\\\" x2=\\\"192\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"280\\\" y1=\\\"39\\\" x2=\\\"192\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"192\\\" cy=\\\"39\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"179\\\" y=\\\"43.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"197\\\" y=\\\"85\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"197\\\" y1=\\\"87\\\" x2=\\\"215\\\" y2=\\\"87\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"217\\\" y=\\\"55\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"192\\\" y1=\\\"114\\\" x2=\\\"76\\\" y2=\\\"114\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"76\\\" y1=\\\"39\\\" x2=\\\"76\\\" y2=\\\"114\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"76\\\" cy=\\\"114\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"63\\\" y=\\\"118.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"133\\\" y=\\\"130\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<line x1=\\\"133\\\" y1=\\\"132\\\" x2=\\\"151\\\" y2=\\\"132\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<text x=\\\"81\\\" y=\\\"85\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association DF2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"192\\\" y1=\\\"114\\\" x2=\\\"192\\\" y2=\\\"189\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"76\\\" y1=\\\"189\\\" x2=\\\"192\\\" y2=\\\"189\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"192\\\" cy=\\\"189\\\" r=\\\"20\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"179\\\" y=\\\"193.8\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">DF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"197\\\" y=\\\"151\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,1</text>\\n\",\n       \"\\t<text x=\\\"148\\\" y=\\\"205\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity INGENIEUR -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"22\\\" y=\\\"9\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"22\\\" y=\\\"39\\\" width=\\\"108\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"22\\\" y=\\\"9\\\" width=\\\"108\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"22\\\" y1=\\\"39\\\" x2=\\\"130\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"31\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Ingénieur</text>\\n\",\n       \"\\t<text x=\\\"30\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">ingénieur</text>\\n\",\n       \"\\t<line x1=\\\"30\\\" y1=\\\"59\\\" x2=\\\"88\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"39\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"241\\\" y=\\\"9\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"241\\\" y1=\\\"39\\\" x2=\\\"319\\\" y2=\\\"39\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"249\\\" y=\\\"30.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"249\\\" y=\\\"56.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"249\\\" y1=\\\"59\\\" x2=\\\"288\\\" y2=\\\"59\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity GERER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"93\\\" width=\\\"72\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"123\\\" width=\\\"72\\\" height=\\\"12\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"93\\\" width=\\\"72\\\" height=\\\"42\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"123\\\" x2=\\\"228\\\" y2=\\\"123\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"164\\\" y=\\\"114.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Gérer</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity RESPONSABLE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"159\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"189\\\" width=\\\"134\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"9\\\" y=\\\"159\\\" width=\\\"134\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"9\\\" y1=\\\"189\\\" x2=\\\"143\\\" y2=\\\"189\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"180.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Responsable</text>\\n\",\n       \"\\t<text x=\\\"17\\\" y=\\\"206.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">responsable</text>\\n\",\n       \"\\t<line x1=\\\"17\\\" y1=\\\"209\\\" x2=\\\"92\\\" y2=\\\"209\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Gérer** (<u>ingénieur</u>, <u>projet</u>, responsable)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --mld -t explode:weak,arity=2 arrange:balanced --seed=14\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les schémas relationnels produits permettent de se convaincre que ces différentes variantes respectent bien la dépendance fonctionnelle désirée : (Ingénieur, Projet) $\\\\implies$ Responsable.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Triplet 11N\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Passons à la deuxième combinaison intéressante :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 177,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjIzN3B0IiBoZWlnaHQ9IjE5N3B0Igogdmlld0JveD0iMC4wMCAwLjAwIDIzNi43NCAxOTcuMTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTkzLjE0KSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTkzLjE0IDIzMi43NCwtMTkzLjE0IDIzMi43NCw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI1OS41LC0xMTIuNTcgMCwtMTEyLjU3IDAsLTc2LjU3IDU5LjUsLTc2LjU3IDU5LjUsLTExMi41NyIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIyOS43NSIgeT0iLTg5LjkiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+UHJvamV0PC90ZXh0Pgo8L2c+CjwhLS0gMiAtLT4KPGcgaWQ9Im5vZGU0IiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTY5LjcxLC0xMTkuNzcgMTEwLjY4LC05NC41NyAxNjkuNzEsLTY5LjM3IDIyOC43NCwtOTQuNTcgMTY5LjcxLC0xMTkuNzciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTY5LjcxIiB5PSItODkuOSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BZmZlY3RlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik01OS43OCwtOTMuNTdDNzQuMzEsLTkzLjU3IDkyLjMxLC05My41NyAxMDkuNTEsLTkzLjU3Ii8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTU5Ljc4LC05NS41N0M3NC4zMSwtOTUuNTcgOTIuMzEsLTk1LjU3IDEwOS41MSwtOTUuNTciLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iOTEuMzgiIHk9Ii05OC4zNSIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwhLS0gMyAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT4zPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMTk2LjcxLC0zNiAxNDIuNzEsLTM2IDE0Mi43MSwwIDE5Ni43MSwwIDE5Ni43MSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTY5LjcxIiB5PSItMTMuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+U2l0ZTwvdGV4dD4KPC9nPgo8IS0tIDMmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4zJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNzAuNzEsLTM2LjE1QzE3MC43MSwtNDUuOTYgMTcwLjcxLC01OC4yNSAxNzAuNzEsLTY5LjAyIi8+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE2OC43MSwtMzYuMTVDMTY4LjcxLC00NS45NiAxNjguNzEsLTU4LjI1IDE2OC43MSwtNjkuMDIiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYxLjI2IiB5PSItNDYuMjIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+NDwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIwOC44NCwtMTg5LjE0IDEzMC41OSwtMTg5LjE0IDEzMC41OSwtMTUzLjE0IDIwOC44NCwtMTUzLjE0IDIwOC44NCwtMTg5LjE0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2OS43MSIgeT0iLTE2Ni40NyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5FbXBsb3nDqTwvdGV4dD4KPC9nPgo8IS0tIDQmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT40JiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xNjkuNzEsLTE1Mi45OUMxNjkuNzEsLTE0My4xOCAxNjkuNzEsLTEzMC44OSAxNjkuNzEsLTEyMC4xMiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNzguMTciIHk9Ii0xMzMuNTciIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+TjwvdGV4dD4KPC9nPgo8L2c+Cjwvc3ZnPgo=\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer\\n\",\n    \"Projet: projet\\n\",\n    \"Affecter, /1N Site, /1N Projet, 0N Employé\\n\",\n    \"Site: site\\n\",\n    \"\\n\",\n    \"Employé: employé\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Règles de gestion :\\n\",\n    \"\\n\",\n    \"> _Chaque employé affecté à un projet travaille sur un seul site pour ce projet, mais peut se trouver sur différents sites pour différents projets. Sur un site donné, un salarié ne travaille que sur un seul projet. Sur un site donné, il peut y avoir plusieurs employés affectés à un projet donné._\\n\",\n    \"\\n\",\n    \"Autrement dit (en partant du bas et dans le sens anti-horaire) :\\n\",\n    \"\\n\",\n    \"1 : pour un couple (projet, employé) donné, un seul site possible ;\\n\",\n    \"1 : pour un couple (employé, site) donné, un seul projet possible ;\\n\",\n    \"N : pour un couple (projet, site) donné, plusieurs employés possibles.\\n\",\n    \"\\n\",\n    \"En résumé, **deux** dépendances fonctionnelles :\\n\",\n    \"\\n\",\n    \"- (Projet, Employé) $\\\\implies$ Site.\\n\",\n    \"- (Employé, Site) $\\\\implies$ Projet.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Voici le MCD correspondant, successivement avec des agrégats et des CIFS (plus de variante possible avec entité faible) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 178,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"382\\\" height=\\\"217\\\" viewBox=\\\"0 0 382 217\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"382\\\" height=\\\"217\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association AFFECTER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"295\\\" cy=\\\"57\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"328\\\" y1=\\\"57\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"111\\\" cy=\\\"57\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"57\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"203\\\" y1=\\\"160\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M27 20 L253 20 a7 7 0 0 1 7 7 L260 191 a7 7 0 0 1 -7 7 L154 198 a7 7 0 0 1 -7 -7 L147 102 a7 7 0 0 0 -7 -7 L27 95 a7 7 0 0 1 -7 -7 L20 27 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.15\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M27 20 L253 20 a7 7 0 0 1 7 7 L260 191 a7 7 0 0 1 -7 7 L154 198 a7 7 0 0 1 -7 -7 L147 102 a7 7 0 0 0 -7 -7 L27 95 a7 7 0 0 1 -7 -7 L20 27 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M146 12 L363 12 a7 7 0 0 1 7 7 L370 95 a7 7 0 0 1 -7 7 L274 102 a7 7 0 0 0 -7 7 L267 198 a7 7 0 0 1 -7 7 L146 205 a7 7 0 0 1 -7 -7 L139 19 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.15\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M146 12 L363 12 a7 7 0 0 1 7 7 L370 95 a7 7 0 0 1 -7 7 L274 102 a7 7 0 0 0 -7 7 L267 198 a7 7 0 0 1 -7 7 L146 205 a7 7 0 0 1 -7 -7 L139 19 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M238 28 a14 14 90 0 1 14 14 V56 h-98 V42 a14 14 90 0 1 14 -14\\\" fill=\\\"#9ebd6d\\\" stroke=\\\"#9ebd6d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M252 56 v16 a14 14 90 0 1 -14 14 H168 a14 14 90 0 1 -14 -14 V56 H98\\\" fill=\\\"#c3dbbb\\\" stroke=\\\"#c3dbbb\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"154\\\" y=\\\"28\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"154\\\" y1=\\\"56\\\" x2=\\\"252\\\" y2=\\\"56\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"162\\\" y=\\\"49.3\\\" fill=\\\"#3d484a\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Affecter</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"267\\\" y=\\\"83\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"83\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"218\\\" y=\\\"112\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"27\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"57\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"27\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"27\\\" y1=\\\"57\\\" x2=\\\"105\\\" y2=\\\"57\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"48.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"74.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"35\\\" y1=\\\"77\\\" x2=\\\"74\\\" y2=\\\"77\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"27\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"57\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"27\\\" width=\\\"54\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"301\\\" y1=\\\"57\\\" x2=\\\"355\\\" y2=\\\"57\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"309\\\" y=\\\"48.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Site</text>\\n\",\n       \"\\t<text x=\\\"309\\\" y=\\\"74.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">site</text>\\n\",\n       \"\\t<line x1=\\\"309\\\" y1=\\\"77\\\" x2=\\\"332\\\" y2=\\\"77\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"130\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"160\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"130\\\" width=\\\"94\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"160\\\" x2=\\\"250\\\" y2=\\\"160\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"165\\\" y=\\\"151.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Employé</text>\\n\",\n       \"\\t<text x=\\\"164\\\" y=\\\"177.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">employé</text>\\n\",\n       \"\\t<line x1=\\\"164\\\" y1=\\\"180\\\" x2=\\\"218\\\" y2=\\\"180\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Affecter** (<u>projet</u>, <u>employé</u> <sup>u1</sup>, site! <sup>u1</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --select all -t mld:c --colors pond\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 179,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"382\\\" height=\\\"217\\\" viewBox=\\\"0 0 382 217\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"382\\\" height=\\\"217\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"203\\\" y1=\\\"57\\\" x2=\\\"66\\\" y2=\\\"160\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"66 87 72 99 66 95 60 99\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"57\\\" x2=\\\"66\\\" y2=\\\"160\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"66\\\" cy=\\\"160\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"57.5\\\" y=\\\"164.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"203\\\" y1=\\\"57\\\" x2=\\\"328\\\" y2=\\\"160\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"328 87 334 99 328 95 322 99\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"328\\\" y1=\\\"57\\\" x2=\\\"328\\\" y2=\\\"160\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"328\\\" cy=\\\"160\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"319.5\\\" y=\\\"164.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association AFFECTER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"328\\\" y1=\\\"57\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"66\\\" y1=\\\"57\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"203\\\" y1=\\\"160\\\" x2=\\\"203\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M238 28 a14 14 90 0 1 14 14 V56 h-98 V42 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M252 56 v16 a14 14 90 0 1 -14 14 H168 a14 14 90 0 1 -14 -14 V56 H98\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"154\\\" y=\\\"28\\\" width=\\\"98\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"154\\\" y1=\\\"56\\\" x2=\\\"252\\\" y2=\\\"56\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"162\\\" y=\\\"49.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Affecter</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"267\\\" y=\\\"83\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"120\\\" y=\\\"83\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"218\\\" y=\\\"112\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">0,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"27\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"57\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"27\\\" y=\\\"27\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"27\\\" y1=\\\"57\\\" x2=\\\"105\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"35\\\" y=\\\"74.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"35\\\" y1=\\\"77\\\" x2=\\\"74\\\" y2=\\\"77\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity SITE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"27\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"57\\\" width=\\\"54\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"301\\\" y=\\\"27\\\" width=\\\"54\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"301\\\" y1=\\\"57\\\" x2=\\\"355\\\" y2=\\\"57\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"309\\\" y=\\\"48.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Site</text>\\n\",\n       \"\\t<text x=\\\"309\\\" y=\\\"74.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">site</text>\\n\",\n       \"\\t<line x1=\\\"309\\\" y1=\\\"77\\\" x2=\\\"332\\\" y2=\\\"77\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity EMPLOYE -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"130\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"160\\\" width=\\\"94\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"156\\\" y=\\\"130\\\" width=\\\"94\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"156\\\" y1=\\\"160\\\" x2=\\\"250\\\" y2=\\\"160\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"165\\\" y=\\\"151.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Employé</text>\\n\",\n       \"\\t<text x=\\\"164\\\" y=\\\"177.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">employé</text>\\n\",\n       \"\\t<line x1=\\\"164\\\" y1=\\\"180\\\" x2=\\\"218\\\" y2=\\\"180\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Affecter** (<u>projet</u>, <u>employé</u> <sup>u1</sup>, site! <sup>u1</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced --seed=3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"On voit apparaître dans le schéma relationnel un « u1 » en exposant qui signifie : contrainte d'unicité n°1. Il y a en effet deux clés candidates : (projet, employé) et (employé, site). Seule l'une des deux est devenue clé primaire, mais cela ne veut pas dire qu'on a perdu la contrainte de dépendance fonctionnelle induite par l'autre. En SQL :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 180,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE Affecter (\\n\",\n       \"  PRIMARY KEY (projet, employe),\\n\",\n       \"  projet  VARCHAR(42) NOT NULL,\\n\",\n       \"  employe VARCHAR(42) NOT NULL,\\n\",\n       \"  site    VARCHAR(42) NOT NULL,\\n\",\n       \"  UNIQUE (employe, site)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t sql\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Triplet 111\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La dernière combinaison obéit à la même logique :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 181,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_erd_chen.svg\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"<img max-width=\\\"100%\\\" src=\\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDkuMC4wICgyMDIzMDkxMS4xODI3KQogLS0+CjwhLS0gUGFnZXM6IDEgLS0+Cjxzdmcgd2lkdGg9IjI1MXB0IiBoZWlnaHQ9IjE4OXB0Igogdmlld0JveD0iMC4wMCAwLjAwIDI1MS4zOSAxODkuNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTg1LjQxKSI+Cjxwb2x5Z29uIGZpbGw9IndoaXRlIiBzdHJva2U9Im5vbmUiIHBvaW50cz0iLTQsNCAtNCwtMTg1LjQxIDI0Ny4zOSwtMTg1LjQxIDI0Ny4zOSw0IC00LDQiLz4KPCEtLSAxIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSI5MS43NSwtMTA4LjcxIDAsLTEwOC43MSAwLC03Mi43MSA5MS43NSwtNzIuNzEgOTEuNzUsLTEwOC43MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI0NS44OCIgeT0iLTg2LjAzIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPlRlY2huaWNpZW48L3RleHQ+CjwvZz4KPCEtLSAyIC0tPgo8ZyBpZD0ibm9kZTQiIGNsYXNzPSJub2RlIj4KPHRpdGxlPjI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEuNSIgcG9pbnRzPSIxODYuMTksLTExNS45MSAxMjksLTkwLjcxIDE4Ni4xOSwtNjUuNTEgMjQzLjM5LC05MC43MSAxODYuMTksLTExNS45MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxODYuMTkiIHk9Ii04Ni4wMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5VdGlsaXNlcjwvdGV4dD4KPC9nPgo8IS0tIDEmIzQ1OyYjNDU7MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT4xJiM0NTsmIzQ1OzI8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik05Mi4yMSwtODkuNzFDMTAzLjcsLTg5LjcxIDExNi4xNywtODkuNzEgMTI4LjE1LC04OS43MSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik05Mi4yMSwtOTEuNzFDMTAzLjcsLTkxLjcxIDExNi4xNywtOTEuNzEgMTI4LjE1LC05MS43MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMTAuMDIiIHk9Ii05NC40OCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwhLS0gNCAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT40PC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxLjUiIHBvaW50cz0iMjE1Ljk0LC0zNiAxNTYuNDQsLTM2IDE1Ni40NCwwIDIxNS45NCwwIDIxNS45NCwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTg2LjE5IiB5PSItMTMuMzIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+UHJvamV0PC90ZXh0Pgo8L2c+CjwhLS0gNCYjNDU7JiM0NTsyIC0tPgo8ZyBpZD0iZWRnZTMiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPjQmIzQ1OyYjNDU7MjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTE4Ny4xOSwtMzYuMzVDMTg3LjE5LC00NS4xIDE4Ny4xOSwtNTUuNzEgMTg3LjE5LC02NS4yMyIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODUuMTksLTM2LjM1QzE4NS4xOSwtNDUuMSAxODUuMTksLTU1LjcxIDE4NS4xOSwtNjUuMjMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTc3Ljc0IiB5PSItNDIuNDIiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+MTwvdGV4dD4KPC9nPgo8IS0tIDMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+MzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMS41IiBwb2ludHM9IjIxOC41NywtMTgxLjQxIDE1My44MiwtMTgxLjQxIDE1My44MiwtMTQ1LjQxIDIxOC41NywtMTQ1LjQxIDIxOC41NywtMTgxLjQxIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE4Ni4xOSIgeT0iLTE1OC43NCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DYXJuZXQ8L3RleHQ+CjwvZz4KPCEtLSAzJiM0NTsmIzQ1OzIgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+MyYjNDU7JiM0NTsyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBkPSJNMTg1LjE5LC0xNDUuMDZDMTg1LjE5LC0xMzYuMzEgMTg1LjE5LC0xMjUuNyAxODUuMTksLTExNi4xOSIvPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIGQ9Ik0xODcuMTksLTE0NS4wNkMxODcuMTksLTEzNi4zMSAxODcuMTksLTEyNS43IDE4Ny4xOSwtMTE2LjE5Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE5NC42NSIgeT0iLTEyOS42NCIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj4xPC90ZXh0Pgo8L2c+CjwvZz4KPC9zdmc+Cg==\\\">\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer\\n\",\n    \"Technicien: technicien\\n\",\n    \"Utiliser, /1N Technicien, /1N Carnet, /1N Projet\\n\",\n    \"Projet: projet\\n\",\n    \"\\n\",\n    \"Carnet: carnet\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Règles de gestion :\\n\",\n    \"\\n\",\n    \"> _Un technicien utilise exactement un carnet pour chaque projet. Chaque carnet appartient à un technicien pour chaque projet. Notez qu'un technicien peut toujours travailler sur plusieurs projets et gérer différents carnets pour différents projets._\\n\",\n    \"\\n\",\n    \"Autrement dit (en partant du haut et dans le sens horaire) :\\n\",\n    \"\\n\",\n    \"- 1 : pour un couple (technicien, projet) donné, un seul carnet possible ;\\n\",\n    \"- 1 : pour un couple (carnet, projet) donné, un seul technicien possible ;\\n\",\n    \"- 1 : pour un couple (carnet, technicien) donné, un seul projet possible.\\n\",\n    \"\\n\",\n    \"En résumé, **trois** dépendances fonctionnelles :\\n\",\n    \"\\n\",\n    \"- (Technicien, Projet) $\\\\implies$ Carnet.\\n\",\n    \"- (Carnet, Technicien) $\\\\implies$ Projet.\\n\",\n    \"- (Carnet, Projet) $\\\\implies$ Technicien.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 182,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"474\\\" height=\\\"245\\\" viewBox=\\\"0 0 474 245\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"474\\\" height=\\\"245\\\" fill=\\\"none\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Association UTILISER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<circle cx=\\\"158\\\" cy=\\\"66\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"94\\\" y1=\\\"66\\\" x2=\\\"256\\\" y2=\\\"66\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"256\\\" cy=\\\"143\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"179\\\" x2=\\\"256\\\" y2=\\\"66\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<circle cx=\\\"354\\\" cy=\\\"66\\\" r=\\\"6\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1\\\" fill=\\\"#a6efb355\\\"/>\\n\",\n       \"\\t<line x1=\\\"399\\\" y1=\\\"66\\\" x2=\\\"256\\\" y2=\\\"66\\\" stroke=\\\"#476062\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M208 26 L441 26 a7 7 0 0 1 7 7 L448 99 a7 7 0 0 1 -7 7 L318 106 a7 7 0 0 0 -7 7 L311 212 a7 7 0 0 1 -7 7 L208 219 a7 7 0 0 1 -7 -7 L201 33 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.1\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M208 26 L441 26 a7 7 0 0 1 7 7 L448 99 a7 7 0 0 1 -7 7 L318 106 a7 7 0 0 0 -7 7 L311 212 a7 7 0 0 1 -7 7 L208 219 a7 7 0 0 1 -7 -7 L201 33 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M23 16 L451 16 a7 7 0 0 1 7 7 L458 109 a7 7 0 0 1 -7 7 L23 116 a7 7 0 0 1 -7 -7 L16 23 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.1\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M23 16 L451 16 a7 7 0 0 1 7 7 L458 109 a7 7 0 0 1 -7 7 L23 116 a7 7 0 0 1 -7 -7 L16 23 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M13 6 L324 6 a7 7 0 0 1 7 7 L331 232 a7 7 0 0 1 -7 7 L188 239 a7 7 0 0 1 -7 -7 L181 133 a7 7 0 0 0 -7 -7 L13 126 a7 7 0 0 1 -7 -7 L6 13 a7 7 0 0 1 7 -7\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"0.1\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M13 6 L324 6 a7 7 0 0 1 7 7 L331 232 a7 7 0 0 1 -7 7 L188 239 a7 7 0 0 1 -7 -7 L181 133 a7 7 0 0 0 -7 -7 L13 126 a7 7 0 0 1 -7 -7 L6 13 a7 7 0 0 1 7 -7\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" stroke-dasharray=\\\"0,4\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M287 37 a14 14 90 0 1 14 14 V65 h-90 V51 a14 14 90 0 1 14 -14\\\" fill=\\\"#9ebd6d\\\" stroke=\\\"#9ebd6d\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M301 65 v16 a14 14 90 0 1 -14 14 H225 a14 14 90 0 1 -14 -14 V65 H90\\\" fill=\\\"#c3dbbb\\\" stroke=\\\"#c3dbbb\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"37\\\" width=\\\"90\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"211\\\" y1=\\\"65\\\" x2=\\\"301\\\" y2=\\\"65\\\" stroke=\\\"#8ea243\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"218\\\" y=\\\"58.3\\\" fill=\\\"#3d484a\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Utiliser</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"97\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"276\\\" y=\\\"126\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"321\\\" y=\\\"97\\\" fill=\\\"#2f494e\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TECHNICIEN -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"36\\\" width=\\\"116\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"66\\\" width=\\\"116\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"36\\\" width=\\\"116\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"36\\\" y1=\\\"66\\\" x2=\\\"152\\\" y2=\\\"66\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"44\\\" y=\\\"57.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Technicien</text>\\n\",\n       \"\\t<text x=\\\"44\\\" y=\\\"83.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">technicien</text>\\n\",\n       \"\\t<line x1=\\\"44\\\" y1=\\\"86\\\" x2=\\\"108\\\" y2=\\\"86\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"36\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"66\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"36\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"360\\\" y1=\\\"66\\\" x2=\\\"438\\\" y2=\\\"66\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"368\\\" y=\\\"57.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"368\\\" y=\\\"83.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"368\\\" y1=\\\"86\\\" x2=\\\"407\\\" y2=\\\"86\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CARNET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"149\\\" width=\\\"82\\\" height=\\\"30\\\" fill=\\\"#7ecb9a\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"179\\\" width=\\\"82\\\" height=\\\"30\\\" fill=\\\"#a6efb3\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"149\\\" width=\\\"82\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"215\\\" y1=\\\"179\\\" x2=\\\"297\\\" y2=\\\"179\\\" stroke=\\\"#387252\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"223\\\" y=\\\"170.3\\\" fill=\\\"#1b5343\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Carnet</text>\\n\",\n       \"\\t<text x=\\\"223\\\" y=\\\"196.1\\\" fill=\\\"#1b5343\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">carnet</text>\\n\",\n       \"\\t<line x1=\\\"223\\\" y1=\\\"199\\\" x2=\\\"263\\\" y2=\\\"199\\\" stroke=\\\"#1b5343\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Utiliser** (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien! <sup>u1 u2</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --select all -t mld:c --colors pond\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 183,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"474\\\" height=\\\"299\\\" viewBox=\\\"0 0 474 299\\\">\\n\",\n       \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"474\\\" height=\\\"299\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#1 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"120\\\" x2=\\\"399\\\" y2=\\\"233\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"297 233 309 227 305 233 309 239\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"233\\\" x2=\\\"399\\\" y2=\\\"233\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"399\\\" cy=\\\"233\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"390.5\\\" y=\\\"237.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#2 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"120\\\" x2=\\\"399\\\" y2=\\\"36\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"399 90 393 78 399 82 405 78\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"399\\\" y1=\\\"120\\\" x2=\\\"399\\\" y2=\\\"36\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"399\\\" cy=\\\"36\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"390.5\\\" y=\\\"40.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Constraint CIF_CONSTRAINT_#3 -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"120\\\" x2=\\\"94\\\" y2=\\\"233\\\" stroke=\\\"#000000\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"0,5\\\" stroke-linecap=\\\"round\\\"/>\\n\",\n       \"\\t<polygon points=\\\"94 150 100 162 94 158 88 162\\\" fill=\\\"#000000\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t<line x1=\\\"94\\\" y1=\\\"120\\\" x2=\\\"94\\\" y2=\\\"233\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<circle cx=\\\"94\\\" cy=\\\"233\\\" r=\\\"13\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"85.5\\\" y=\\\"237.2\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\" style=\\\"pointer-events: none;\\\">CIF</text>\\n\",\n       \"\\t</g>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Association UTILISER -->\\n\",\n       \"<g>\\n\",\n       \"\\t<line x1=\\\"94\\\" y1=\\\"120\\\" x2=\\\"256\\\" y2=\\\"120\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"256\\\" y1=\\\"233\\\" x2=\\\"256\\\" y2=\\\"120\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<line x1=\\\"399\\\" y1=\\\"120\\\" x2=\\\"256\\\" y2=\\\"120\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<path d=\\\"M287 91 a14 14 90 0 1 14 14 V119 h-90 V105 a14 14 90 0 1 14 -14\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<path d=\\\"M301 119 v16 a14 14 90 0 1 -14 14 H225 a14 14 90 0 1 -14 -14 V119 H90\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"0\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"211\\\" y=\\\"91\\\" width=\\\"90\\\" height=\\\"58\\\" fill=\\\"none\\\" rx=\\\"14\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"211\\\" y1=\\\"119\\\" x2=\\\"301\\\" y2=\\\"119\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t\\t<text x=\\\"218\\\" y=\\\"112.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Utiliser</text>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"172\\\" y=\\\"151\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"276\\\" y=\\\"180\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"\\t<text x=\\\"321\\\" y=\\\"151\\\" fill=\\\"#000000\\\" font-family=\\\"Futura\\\" font-size=\\\"11\\\">1,N</text>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity TECHNICIEN -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"90\\\" width=\\\"116\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"120\\\" width=\\\"116\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"36\\\" y=\\\"90\\\" width=\\\"116\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"36\\\" y1=\\\"120\\\" x2=\\\"152\\\" y2=\\\"120\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"44\\\" y=\\\"111.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Technicien</text>\\n\",\n       \"\\t<text x=\\\"44\\\" y=\\\"137.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">technicien</text>\\n\",\n       \"\\t<line x1=\\\"44\\\" y1=\\\"140\\\" x2=\\\"108\\\" y2=\\\"140\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity PROJET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"90\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"120\\\" width=\\\"78\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"360\\\" y=\\\"90\\\" width=\\\"78\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"360\\\" y1=\\\"120\\\" x2=\\\"438\\\" y2=\\\"120\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"368\\\" y=\\\"111.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Projet</text>\\n\",\n       \"\\t<text x=\\\"368\\\" y=\\\"137.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">projet</text>\\n\",\n       \"\\t<line x1=\\\"368\\\" y1=\\\"140\\\" x2=\\\"407\\\" y2=\\\"140\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"\\n\",\n       \"<!-- Entity CARNET -->\\n\",\n       \"<g>\\n\",\n       \"\\t<g>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"203\\\" width=\\\"82\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"233\\\" width=\\\"82\\\" height=\\\"30\\\" fill=\\\"#FFFFFF\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<rect x=\\\"215\\\" y=\\\"203\\\" width=\\\"82\\\" height=\\\"60\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\" opacity=\\\"1\\\"/>\\n\",\n       \"\\t\\t<line x1=\\\"215\\\" y1=\\\"233\\\" x2=\\\"297\\\" y2=\\\"233\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1.5\\\"/>\\n\",\n       \"\\t</g>\\n\",\n       \"\\t<text x=\\\"223\\\" y=\\\"224.3\\\" fill=\\\"#000000\\\" font-family=\\\"Copperplate\\\" font-size=\\\"18\\\">Carnet</text>\\n\",\n       \"\\t<text x=\\\"223\\\" y=\\\"250.1\\\" fill=\\\"#000000\\\" font-family=\\\"Gill Sans\\\" font-size=\\\"15\\\">carnet</text>\\n\",\n       \"\\t<line x1=\\\"223\\\" y1=\\\"253\\\" x2=\\\"263\\\" y2=\\\"253\\\" stroke=\\\"#000000\\\" stroke-width=\\\"1\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_mld.md\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"- **Utiliser** (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien! <sup>u1 u2</sup>)\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced flip:d,v --seed=12\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il y a maintenant trois clés candidates, correspondant à deux contraintes d'unicité. En SQL :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 184,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE Utiliser (\\n\",\n       \"  PRIMARY KEY (carnet, projet),\\n\",\n       \"  carnet     VARCHAR(42) NOT NULL,\\n\",\n       \"  projet     VARCHAR(42) NOT NULL,\\n\",\n       \"  technicien VARCHAR(42) NOT NULL,\\n\",\n       \"  UNIQUE (carnet, technicien),\\n\",\n       \"  UNIQUE (projet, technicien)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t sql\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Conclusion sur les agrégats multiples\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notre syntaxe `/1N` pour les agrégats permet d'exprimer simplement toutes les combinaisons possibles de cardinalités d'une association n-aire dans la notation de Chen : il suffit de mettre un `/1N` partout où Chen met un `1`. Chaque `/1N` créera une nouvelle dépendance fonctionnelle, autrement dit, une nouvelle clé candidate.\\n\",\n    \"\\n\",\n    \"Plus rigoureusement : supposons une association $n$-aire $A$ exclusivement entourée de 1N (ou 0N). Soient $E_1$, $E_2$, ..., $E_n$ les entités mises en jeu, et $k_1, k_2$, ..., $k_n$ leurs identifiants respectifs. Alors, noter `/1N` (ou `/0N`) la cardinalité de la patte de $E_i$ dénote l'existence de la dépendance fonctionnelle suivante : $(k_1, ..., k_{i-1}, k_{i+1}, ..., k_n) \\\\implies k_i$, autrement dit : que $(k_1, ..., k_{i-1}, k_{i+1}, ..., k_n)$ est une clé candidate de la table $A$.\\n\",\n    \"\\n\",\n    \"Notez pour finir que Mocodo permet de spécifier à coût zéro quelle clé candidate sera élue clé primaire. Il suffit pour cela de placer en tête de la liste des entités mises en jeu par $A$ celle dont l'identifiant ne doit **pas** entrer dans la clé primaire. Si c'est $E_1$, la clé primaire sera automatiquement $(k_2, ..., k_n)$.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Annexe B : La commande `mocodo`\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Paramétrage\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### `mocodo --help`\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 185,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"usage: mocodo [--language CODE] [--params_path PATH] [--input PATH] [--help]\\n\",\n      \"              [--version] [--restore] [--lib [URL]] [--output_dir PATH]\\n\",\n      \"              [--encodings [STR ...]] [--svg_to {png,pdf} [{png,pdf} ...]]\\n\",\n      \"              [--print_params] [--reuse_geo] [--uid_suffix INT]\\n\",\n      \"              [--select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]]\\n\",\n      \"              [--defer [STR ...]] [--mld] [--transform [STR ...]]\\n\",\n      \"              [--seed [FLOAT]] [--title STR] [--df STR] [--card_format [STR]]\\n\",\n      \"              [--fk_format [STR]] [--strengthen_card [STR]] [--flex FLOAT]\\n\",\n      \"              [--colors STEM_OR_PATH] [--shapes STEM_OR_PATH] [--scale RATE]\\n\",\n      \"              [--adjust_width RATE] [--detect_overlaps] [--no_assoc_ids]\\n\",\n      \"              [--gutters STR [STR ...]]\\n\",\n      \"\\n\",\n      \"NOM :\\n\",\n      \"Mocodo - Un générateur de diagrammes entité-association.\\n\",\n      \"\\n\",\n      \"DESCRIPTION :\\n\",\n      \"Mocodo est un outil libre destiné à l'enseignement des bases de données relationnelles.\\n\",\n      \"Il prend en entrée une description textuelle des entités et associations d'un diagramme\\n\",\n      \"entité-association (MCD). Il produit en sortie un dessin vectoriel en SVG et un schéma\\n\",\n      \"relationnel dans divers formats (SQL, LaTeX, Markdown, etc.).\\n\",\n      \"\\n\",\n      \"NOTE :\\n\",\n      \"Chacune des valeurs suivantes est :\\n\",\n      \"- spécifiée explicitement par l'utilisateur comme option de ligne de commande ;\\n\",\n      \"- sinon, récupérée depuis un fichier de chemin --params_path ;\\n\",\n      \"- sinon, récupérée depuis un fichier nommé « params.json » dans le répertoire d'entrée ;\\n\",\n      \"- sinon, calculée à partir d'une valeur par défaut, éventuellement dépendante de votre système.\\n\",\n      \"    \\n\",\n      \"\\n\",\n      \"OPTIONS SUR MOCODO LUI-MÊME :\\n\",\n      \"  --language CODE       force la localisation des messages avec le code de\\n\",\n      \"                        langue donné (par exemple, « fr », « en », ...)\\n\",\n      \"                        (default: fr)\\n\",\n      \"  --help                affiche ce message d'aide, puis termine\\n\",\n      \"  --version             affiche le numéro de version, puis termine\\n\",\n      \"  --restore             recrée une version vierge des fichiers « sandbox.mcd »\\n\",\n      \"                        et « params.json » dans le répertoire d'entrée, puis\\n\",\n      \"                        termine (default: False)\\n\",\n      \"\\n\",\n      \"ENTRÉE/SORTIE :\\n\",\n      \"  --params_path PATH    le chemin du fichier de paramètres. S'il est omis,\\n\",\n      \"                        utilise « params.json » dans le répertoire d'entrée.\\n\",\n      \"                        S'il n'existe pas, utilise les paramètres par défaut.\\n\",\n      \"                        (default: params.json)\\n\",\n      \"  --input PATH, -i PATH\\n\",\n      \"                        le chemin du fichier d'entrée. Par défaut, les\\n\",\n      \"                        fichiers de sortie seront générés dans le même\\n\",\n      \"                        répertoire (default: /Users/aristide/Dropbox/Sites/moc\\n\",\n      \"                        odo/doc/mocodo_notebook/sandbox.mcd)\\n\",\n      \"  --lib [URL]           remote directory to use as fallback when the input\\n\",\n      \"                        file is not found locally (default:\\n\",\n      \"                        https://mocodo.net/web/lib)\\n\",\n      \"  --output_dir PATH     le répertoire des fichiers de sortie (default: .)\\n\",\n      \"  --encodings [STR ...]\\n\",\n      \"                        un ou plusieurs encodages à essayer successivement\\n\",\n      \"                        lors de la lecture du fichier d'entrée (default:\\n\",\n      \"                        ['utf8', 'macroman'])\\n\",\n      \"  --svg_to {png,pdf} [{png,pdf} ...]\\n\",\n      \"                        génère une version PNG ou PDF de la sortie SVG\\n\",\n      \"                        (requiert CairoSVG) (default: [])\\n\",\n      \"  --print_params        affiche le contenu du fichier de paramètres, puis\\n\",\n      \"                        termine (default: False)\\n\",\n      \"  --reuse_geo           réutilise le fichier de géométrie de l'exécution\\n\",\n      \"                        précédente (default: False)\\n\",\n      \"  --uid_suffix INT      ajoute un discriminateur à un SVG interactif (default:\\n\",\n      \"                        0)\\n\",\n      \"  --select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]\\n\",\n      \"                        sous Jupyter Notebook, spécifie explicitement les\\n\",\n      \"                        catégories de résultats à afficher\\n\",\n      \"  --defer [STR ...]     utilise un service web externe pour convertir les\\n\",\n      \"                        résultats de la conversion dans les formats graphiques\\n\",\n      \"                        donnés\\n\",\n      \"  --mld                 alias de compatibilité ascendante pour « -t » (sans\\n\",\n      \"                        arguments). Équivalent à « -t markdown » mais, sous\\n\",\n      \"                        Jupyter Notebook, n'empêche pas le rendu du diagramme\\n\",\n      \"                        conceptuel dans la sortie de la cellule (default:\\n\",\n      \"                        False)\\n\",\n      \"  --transform [STR ...], -t [STR ...]\\n\",\n      \"                        crée une nouvelle version du MCD en appliquant\\n\",\n      \"                        séquentiellement les opérations de réécriture données,\\n\",\n      \"                        et/ou le convertit dans les formats ou langages\\n\",\n      \"                        donnés. Sous Jupyter Notebook, « -T » remplace\\n\",\n      \"                        respectivement la cellule courante par le résultat\\n\",\n      \"                        textuel, ou le copie dans le presse-papier (pip3\\n\",\n      \"                        install pyperclip)\\n\",\n      \"  --seed [FLOAT]        valeur initiale pour le générateur de nombres\\n\",\n      \"                        aléatoires (default: None)\\n\",\n      \"  --title STR           nom du modèle, utilisé à divers endroits (système de\\n\",\n      \"                        fichiers, base de données, etc.) (default: MCD)\\n\",\n      \"\\n\",\n      \"ASPECT DE LA SORTIE GRAPHIQUE :\\n\",\n      \"  --df STR              l'acronyme à entourer dans une dépendance\\n\",\n      \"                        fonctionnelle (default: DF)\\n\",\n      \"  --card_format [STR]   chaîne de formatage pour les cardinalités minimales et\\n\",\n      \"                        maximales (default: {min_card},{max_card})\\n\",\n      \"  --fk_format [STR]     chaîne de formatage pour les clés étrangères dans le\\n\",\n      \"                        diagramme relationnel (default: #{label})\\n\",\n      \"  --strengthen_card [STR]\\n\",\n      \"                        chaîne pour les cardinalités relatives (default:\\n\",\n      \"                        _1,1_)\\n\",\n      \"  --flex FLOAT          incurve les pattes rectilignes dont les cardinalités\\n\",\n      \"                        peuvent se chevaucher (default: 0.75)\\n\",\n      \"  --colors STEM_OR_PATH\\n\",\n      \"                        la palette de couleurs à utiliser lors de la\\n\",\n      \"                        génération du dessin. Nom (sans extension) d'un\\n\",\n      \"                        fichier situé dans le répertoire « colors », ou chemin\\n\",\n      \"                        vers un fichier personnel (default: bw)\\n\",\n      \"  --shapes STEM_OR_PATH\\n\",\n      \"                        spécification des polices, dimensions, etc. Nom (sans\\n\",\n      \"                        extension) d'un fichier situé dans le répertoire\\n\",\n      \"                        « shapes », ou chemin vers un fichier personnel\\n\",\n      \"                        (default: copperplate)\\n\",\n      \"  --scale RATE          applique au diagramme le facteur de mise à l'échelle\\n\",\n      \"                        donné (default: 1)\\n\",\n      \"  --adjust_width RATE   applique à tous les textes calculés le facteur de mise\\n\",\n      \"                        à l'échelle donné (default: 1)\\n\",\n      \"  --detect_overlaps     lève une erreur quand des pattes horizontales ou\\n\",\n      \"                        verticales se chevauchent (default: False)\\n\",\n      \"  --no_assoc_ids        interdit l'utilisation d'identifiants dans les\\n\",\n      \"                        associations (conformément au standard Merise)\\n\",\n      \"                        (default: False)\\n\",\n      \"  --gutters STR [STR ...]\\n\",\n      \"                        définit la visibilité et le contenu des gouttières\\n\",\n      \"                        latérales\\n\",\n      \"\\n\",\n      \"VOIR AUSSI :\\n\",\n      \"  Version en ligne      https://mocodo.net\\n\",\n      \"  Code source           https://github.com/laowantong/mocodo\\n\",\n      \"  Documentation         https://laowantong.github.io/mocodo/doc/fr_refman.html\\n\",\n      \"  Aide-mémoire pour -t  https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md\\n\",\n      \"\\n\",\n      \"LICENCE :               MIT\\n\",\n      \"\\n\",\n      \"CONTACT :\\n\",\n      \"  Auteur                Aristide Grange\\n\",\n      \"  Adresse               Université de Lorraine\\n\",\n      \"                        Laboratoire LCOMS - UFR MIM\\n\",\n      \"                        3 rue Augustin Fresnel\\n\",\n      \"                        57070 METZ Technopôle\\n\",\n      \"                        France\\n\",\n      \"  Courriel              <prénom.nom>@univ-lorraine.fr\\n\",\n      \"    \\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%mocodo --help\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Paramétrage à long terme\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour éviter d'avoir à invoquer Mocodo répétitivement avec une longue kyrielle d'options, vous pouvez mettre celles-ci dans un fichier `params.json` situé dans le répertoire de lancement de Mocodo. La commande:\\n\",\n    \"\\n\",\n    \"    mocodo --restore\\n\",\n    \"\\n\",\n    \"... le fait pour vous avec un fichier de paramètres vide, _i.e._, un fichier-texte réduit aux deux caractères `{}`  (attention, elle rétablit aussi le fichier `sandbox.mcd` à son contenu par défaut).\\n\",\n    \"\\n\",\n    \"Pour que le style de vos MCD soit maintenu à moindre frais à travers tous vos documents, vous êtes encouragés à modifier ce fichier de paramètres selon vos goûts et vos besoins. Mocodo peut même vous aider à le faire en exécutant la cellule suivante:\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"%mocodo --print_params\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"Son évaluation remplace son propre contenu par des lignes de code similaires à :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 186,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# You may edit and run the following lines\\n\",\n    \"import json, pathlib\\n\",\n    \"params = \\\"\\\"\\\"\\\\\\n\",\n    \"{\\n\",\n    \"  \\\"adjust_width\\\": 1,\\n\",\n    \"  \\\"card_format\\\": \\\"{min_card},{max_card}\\\",\\n\",\n    \"  \\\"colors\\\": \\\"bw\\\",\\n\",\n    \"  \\\"detect_overlaps\\\": false,\\n\",\n    \"  \\\"df\\\": \\\"DF\\\",\\n\",\n    \"  \\\"encodings\\\": [ \\\"utf8\\\", \\\"macroman\\\" ],\\n\",\n    \"  \\\"fk_format\\\": \\\"#{label}\\\",\\n\",\n    \"  \\\"flex\\\": 0.75,\\n\",\n    \"  \\\"language\\\": \\\"fr\\\",\\n\",\n    \"  \\\"lib\\\": \\\"https://mocodo.net/web/lib\\\",\\n\",\n    \"  \\\"mld\\\": false,\\n\",\n    \"  \\\"no_assoc_ids\\\": false,\\n\",\n    \"  \\\"output_dir\\\": \\\".\\\",\\n\",\n    \"  \\\"restore\\\": false,\\n\",\n    \"  \\\"scale\\\": 1,\\n\",\n    \"  \\\"seed\\\": null,\\n\",\n    \"  \\\"shapes\\\": \\\"copperplate\\\",\\n\",\n    \"  \\\"strengthen_card\\\": \\\"_1,1_\\\",\\n\",\n    \"  \\\"svg_to\\\": [],\\n\",\n    \"  \\\"title\\\": \\\"MCD\\\",\\n\",\n    \"  \\\"uid_suffix\\\": 0\\n\",\n    \"}\\\"\\\"\\\"\\n\",\n    \"try:\\n\",\n    \"    json.loads(params)\\n\",\n    \"except:\\n\",\n    \"    raise RuntimeError(\\\"Invalid JSON. Check your syntax on https://jsonlint.com.\\\")\\n\",\n    \"pathlib.Path(\\\"./params.json\\\").write_text(params, encoding=\\\"utf8\\\");\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ensuite :\\n\",\n    \"\\n\",\n    \"1. Modifiez la variable `params` à votre gré en respectant la syntaxe [JSON](http://json.org).\\n\",\n    \"2. Exécutez la cellule pour créer un fichier de nom et emplacement adéquats.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"En cas de besoin, vous pourrez toujours ponctuellement passer outre ces réglages en en précisant d'autres en ligne de commande. Plus précisément, chaque paramètre est déterminé:\\n\",\n    \"\\n\",\n    \"1. par sa valuation en ligne de commande;\\n\",\n    \"2. à défaut, par sa valuation dans le fichier de paramètres indiqué par `--params_path`;\\n\",\n    \"3. à défaut d'une telle indication, par sa valuation dans le fichier `params.json` du répertoire courant;\\n\",\n    \"4. à défaut, par une valeur défaut éventuellement dépendante de votre système.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Dissection de la commande\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'API de Mocodo a été revue de façon radicale pour la version 4.0. Le nombre d'options de premier niveau a été réduit ; en contrepartie, certaines sont devenues de véritables mini-commandes, avec leur propre liste d'arguments, et une syntaxe et un comportement uniformes. Voici leur définition en ABNF :\\n\",\n    \"\\n\",\n    \"![](examples/option_syntax_2.png)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Introduisons, sur un exemple fictif, un vocabulaire que nous avons essayé d'employer le plus rigoureusement possible tout au long de cette documentation (et dans le code lui-même) :\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"mocodo    --select all    --transform  drain  arrange:wide  explode:weak,arity=2.5\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"- La **commande** `mocodo` est invoquée avec les **options** `--select` et `--transform`.\\n\",\n    \"- On passe à la seconde trois **arguments** de complexité croissante, `drain`, `arrange:wide` et `explode:weak,arity=2.5`. Notez que le séparateur des arguments est l'espace. Par conséquent, un argument ne peut contenir d'espaces qu'entre guillemets.\\n\",\n    \"- Chacun des arguments consiste en un nom de **sous-option** (`drain`, `arrange` ou `explode`), suivi éventuellement d'un deux-points (`:`), suivi d'une liste de **sous-arguments** séparés par des virgules (`,`).\\n\",\n    \"- Chacun des sous-arguments consiste en un nom de **sous-sous-option**, suivi éventuellement d'un signe égal (`=`), suivi d'un **sous-sous-argument** (éventuellement entre guillemets).\\n\",\n    \"\\n\",\n    \"On n'ira pas plus loin et, heureusement, la plupart des commandes réelles n'atteignent pas ce degré d'imbrication. La décomposition suivante fixera peut-être les idées, ou pourra du moins servir de référence en cas de doute :\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\underbrace{\\\\texttt{mocodo}}_{\\\\text{command}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\texttt{-}\\\\,\\\\texttt{-}\\n\",\n    \"\\\\underbrace{\\\\texttt{select}}_{\\\\text{option}}\\n\",\n    \"\\\\underbrace{\\n\",\n    \"    \\\\texttt{all}\\n\",\n    \"}_{\\\\text{argument}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\texttt{-}\\\\,\\\\texttt{-}\\n\",\n    \"\\\\underbrace{\\\\texttt{transform}}_{\\\\text{option}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\underbrace{\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\texttt{drain}\\n\",\n    \"    }_{\\\\text{sub-option}}\\n\",\n    \"}_{\\\\text{argument}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\underbrace{\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\texttt{arrange}\\n\",\n    \"    }_{\\\\text{sub-option}}\\n\",\n    \"    \\\\texttt{:}\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\underbrace{\\n\",\n    \"            \\\\texttt{wide}\\n\",\n    \"        }_{\\\\text{sub-sub-opt}}\\n\",\n    \"    }_{\\\\text{sub-arg}}\\n\",\n    \"}_{\\\\text{argument}}\\n\",\n    \"\\\\qquad\\n\",\n    \"\\\\underbrace{\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\texttt{explode}\\n\",\n    \"    }_{\\\\text{sub-option}}\\n\",\n    \"    \\\\texttt{:}\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\underbrace{\\n\",\n    \"            \\\\texttt{weak}\\n\",\n    \"        }_{\\\\text{sub-sub-opt}}\\n\",\n    \"    }_{\\\\text{sub-arg}}\\n\",\n    \"    \\\\texttt{,}\\n\",\n    \"    \\\\underbrace{\\n\",\n    \"        \\\\underbrace{\\n\",\n    \"            \\\\texttt{arity}\\n\",\n    \"        }_{\\\\text{sub-sub-opt}}\\n\",\n    \"        \\\\texttt{=}\\n\",\n    \"        \\\\underbrace{\\n\",\n    \"            \\\\texttt{2.5}\\n\",\n    \"        }_{\\\\text{sub-sub-arg}}\\n\",\n    \"    }_{\\\\text{sub-argument}}\\n\",\n    \"}_{\\\\text{argument}}\\n\",\n    \"$$ \\n\",\n    \"\\n\",\n    \"L'intérêt de cette structuration en arborescence est double. Elle permet :\\n\",\n    \"- de créer des pipelines d'opérations : le résultat de l'application du premier argument est fourni en entrée au second, etc ;\\n\",\n    \"- de regrouper les opérations interdépendantes. Par exemple, avant la version 4.0, l'argument `explode:weak,arity=2.5` aurait dû être mis à plat : `--explode --weak_explosion --explosion_arity=2.5`. Cela donne le même statut à toutes, masquant le fait que certaines n'ont de sens qu'en présence d'une autre.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## L'option `--transform` et ses arguments\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Triage et exécution des transformations\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'option à tout faire est `--transform`, que vous pouvez abréger `-t`. Avant de traiter ses arguments, Mocodo commence par les répartir en deux catégories :\\n\",\n    \"\\n\",\n    \"- les **réécritures**, qui transforment le MCD original en un nouveau MCD avec, par exemple, les libellés mis en majuscules, ou les associations n-aires décomposées en DF, ou les boîtes réarrangées ;\\n\",\n    \"- les **conversions**, qui produisent quelque chose qui n'est pas un MCD : ce peut être un dictionnaire des données, un diagramme de classes UML, un ERD dans la notation _crow's foot_, etc.\\n\",\n    \"\\n\",\n    \"L'exécution se déroule alors en deux étapes :\\n\",\n    \"\\n\",\n    \"1. les réécritures sont opérées en pipeline, c'est-à-dire que le MCD produit par la première réécriture est passé en entrée de la seconde, etc. Leur ordre a donc de l'importance ;\\n\",\n    \"2. les conversions sont alors appliquées au résultat de la dernière réécriture. Leur ordre n'a pas d'importance.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Aide-mémoire des transformations\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'option `-t` (ou `--transform`) permet d'accéder à un grand nombre d'opérations de conversion ou de réécriture.\\n\",\n    \"\\n\",\n    \"Toutes les opérations de conversion ont déjà été décrites dans ce document :\\n\",\n    \"\\n\",\n    \"- produits dérivés : `data_dict`, `share` ;\\n\",\n    \"- schémas relationnels textuels : `html`, `latex`, `markdown`, `text` ;\\n\",\n    \"- DDL : `sql` (et ses dialectes) ;\\n\",\n    \"- autres sorties relationnelles : `diagram`, `dbml`, `d2`, `dependencies` ;\\n\",\n    \"- conversions dans d'autres notations : `uml`, `crow`, `chen`.\\n\",\n    \"\\n\",\n    \"Certaines opérations de réécriture ont été présentées, d'autres passées sous silence :\\n\",\n    \"\\n\",\n    \"- réorganisation du MCD : `arrange`, `flip` ;\\n\",\n    \"- obfuscation et randomisation d'éléments donnés : `randomize`, `drown` ;\\n\",\n    \"- génération de MCD aléatoires : `grow` ;\\n\",\n    \"- décomposition d'associations : `split`, `drain`, `explode` ;\\n\",\n    \"- inférence d'informations manquantes : `create` ;\\n\",\n    \"- suppression d'éléments donnés : `delete` ;\\n\",\n    \"- traitement de chaînes de caractères : `truncate`, `slice`, `prefix`, `suffix`, `replace` ;\\n\",\n    \"- homogénéisation de la mise en forme : `ascii`, `camel`, `snake`, `pascal`, `lower`, `upper`, etc.\\n\",\n    \"\\n\",\n    \"L'aide-mémoire suivant devrait vous permettre de prendre en main les sous-options de `--transform` qui vous intéressent. Survolez une sous-option pour afficher ses alias éventuels.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 187,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"### Opérations de conversion\\n\",\n       \"\\n\",\n       \"| Sous-option | Description | Exemples | Explications |\\n\",\n       \"| :-- | :-- | :-- | :-- |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">ast</span> | crée l'arbre de syntaxe abstraite du texte source (pour le débogage) |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">chen</span> | convertit le modèle conceptuel dans la notation de Chen | `` chen `` | sans attributs |\\n\",\n       \"|  |  | `` chen:attrs `` | avec attributs |\\n\",\n       \"|  |  | `` chen:attrs --defer `` | calcule le rendu graphique via un service web |\\n\",\n       \"|  |  | `` chen:layout=circo,mindist=2,scale=0.6 `` | ajoute des options arbitraires pour Graphviz |\\n\",\n       \"| <span title=\\\"Alias : crowfoot, crowsfoot.\\\" style=\\\"font-family:monospace; font-weight:600\\\">crow</span> | convertit le modèle conceptuel dans la notation crow's foot | `` crow `` | format Graphviz |\\n\",\n       \"|  |  | `` crow --defer `` | calcule le rendu graphique via un service web |\\n\",\n       \"|  |  | `` crow:mmd `` | format Mermaid |\\n\",\n       \"|  |  | `` crow:mermaid `` | idem |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">d2</span> | convertit le modèle conceptuel en un schéma relationnel au format D2 |  |  |\\n\",\n       \"| <span title=\\\"Alias : data_dictionary.\\\" style=\\\"font-family:monospace; font-weight:600\\\">data_dict</span> | extrait tous les attributs du MCD dans une table | `` data_dict `` | tableau Markdown, trois colonnes |\\n\",\n       \"|  |  | `` data_dict:label `` | liste Markdown, une colonne |\\n\",\n       \"|  |  | `` data_dict:label,type='Description' `` | deux colonnes, un libellé personnalisé |\\n\",\n       \"|  |  | `` data_dict:label='Attribut',type='Description' `` | deux colonnes, deux libellés personnalisés |\\n\",\n       \"|  |  | `` data_dict:**box**='Entité ou<br>association',label,`type`=`'Type de données'` `` | mise en forme de certains libellés |\\n\",\n       \"|  |  | `` data_dict:tsv `` | tableau TSV, trois colonnes |\\n\",\n       \"|  |  | `` data_dict:tsv,label `` | liste des attributs séparés par des retours à la ligne |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">dbml</span> | convertit le modèle conceptuel en un schéma relationnel au format DBML | `` dbml `` | version de base |\\n\",\n       \"|  |  | `` dbml:b `` | avec _boilerplate_ |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">debug</span> | liste des informations internes relatives à la conversion en schéma relationnel |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">dependencies</span> | convertit le modèle conceptuel en un graphe de dépendances |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">diagram</span> | convertit le modèle conceptuel en un diagramme relationnel au format Mocodo | `` diagram `` | version de base |\\n\",\n       \"|  |  | `` diagram:c `` | avec contraintes d'unicité et d'optionalité |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">html</span> | convertit le modèle conceptuel en un schéma relationnel au format HTML | `` html `` | version de base |\\n\",\n       \"|  |  | `` html:b `` | avec _boilerplate_ |\\n\",\n       \"|  |  | `` html:c `` | avec contraintes d'unicité et d'optionalité |\\n\",\n       \"|  |  | `` html:e `` | avec explications |\\n\",\n       \"|  |  | `` html:bce `` | avec _boilerplate_, contraintes et explications |\\n\",\n       \"| <span title=\\\"Alias : tex.\\\" style=\\\"font-family:monospace; font-weight:600\\\">latex</span> | convertit le modèle conceptuel en un schéma relationnel au format LaTeX | `` latex `` | version de base |\\n\",\n       \"|  |  | `` latex:b `` | avec _boilerplate_ |\\n\",\n       \"|  |  | `` latex:c `` | avec contraintes d'unicité et d'optionalité |\\n\",\n       \"|  |  | `` latex:e `` | avec explications |\\n\",\n       \"|  |  | `` latex:bce `` | avec _boilerplate_, contraintes et explications |\\n\",\n       \"| <span title=\\\"Alias : md, mld.\\\" style=\\\"font-family:monospace; font-weight:600\\\">markdown</span> | convertit le modèle conceptuel en un schéma relationnel au format Markdown | `` markdown `` | version de base |\\n\",\n       \"|  |  | `` markdown:c `` | avec contraintes d'unicité et d'optionalité |\\n\",\n       \"|  |  | `` markdown:e `` | avec explications |\\n\",\n       \"|  |  | `` markdown:ce `` | avec contraintes et explications |\\n\",\n       \"| <span title=\\\"Alias : ms_sql, sql_server, sqlserver.\\\" style=\\\"font-family:monospace; font-weight:600\\\">mssql</span> | convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server | `` mssql `` | version de base |\\n\",\n       \"|  |  | `` mssql:b `` | avec _boilerplate_ |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">mysql</span> | convertit le modèle conceptuel en un modèle physique pour MySQL | `` mysql `` | version de base |\\n\",\n       \"|  |  | `` mysql:b `` | avec _boilerplate_ |\\n\",\n       \"| <span title=\\\"Alias : oracle_db.\\\" style=\\\"font-family:monospace; font-weight:600\\\">oracle</span> | convertit le modèle conceptuel en un modèle physique pour Oracle DB | `` oracle `` | version de base |\\n\",\n       \"|  |  | `` oracle:b `` | avec _boilerplate_ |\\n\",\n       \"| <span title=\\\"Alias : postgres.\\\" style=\\\"font-family:monospace; font-weight:600\\\">postgresql</span> | convertit le modèle conceptuel en un modèle physique pour PostgreSQL | `` postgresql `` | version de base |\\n\",\n       \"|  |  | `` postgresql:b `` | avec _boilerplate_ |\\n\",\n       \"| <span title=\\\"Alias : chat, chatbot, ia, ai.\\\" style=\\\"font-family:monospace; font-weight:600\\\">prompt</span> | génère un prompt pour demander à une IA de compléter le MCD | `` prompt:cards `` | avec les explications des cardinalités |\\n\",\n       \"|  |  | `` prompt:types `` | avec les types des attributs |\\n\",\n       \"| <span title=\\\"Alias : template, relation_template.\\\" style=\\\"font-family:monospace; font-weight:600\\\">relation</span> | convertit le modèle conceptuel en schéma relationnel avec le gabarit donné | `` relation:path/to/my_template.yaml `` | chemin relatif, extension obligatoire |\\n\",\n       \"| <span title=\\\"Alias : url, link, qr, qr_code.\\\" style=\\\"font-family:monospace; font-weight:600\\\">share</span> | encode le MCD dans une URL pour Mocodo online | `` qr --defer `` | génère un QR code via un service web |\\n\",\n       \"| <span title=\\\"Alias : ddl.\\\" style=\\\"font-family:monospace; font-weight:600\\\">sql</span> | convertit le modèle conceptuel en un modèle physique pour SQL |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">sqlite</span> | convertit le modèle conceptuel en un modèle physique pour SQLite | `` sqlite `` | version de base |\\n\",\n       \"|  |  | `` sqlite:b `` | avec _boilerplate_ |\\n\",\n       \"| <span title=\\\"Alias : txt.\\\" style=\\\"font-family:monospace; font-weight:600\\\">text</span> | convertit le modèle conceptuel en un schéma relationnel au format texte | `` text `` | version de base |\\n\",\n       \"|  |  | `` text:c `` | avec contraintes d'unicité et d'optionalité |\\n\",\n       \"|  |  | `` html:e `` | avec explications |\\n\",\n       \"|  |  | `` html:ce `` | avec contraintes et explications |\\n\",\n       \"| <span title=\\\"Alias : uml, class_diagram.\\\" style=\\\"font-family:monospace; font-weight:600\\\">uml</span> | convertit le modèle conceptuel en diagramme de classes UML | `` uml `` | format PlantUML |\\n\",\n       \"|  |  | `` uml:plantuml `` | idem |\\n\",\n       \"|  |  | `` uml --defer `` | calcule le rendu graphique via un service web |\\n\",\n       \"|  |  | `` uml:plantuml=- `` | supprime les styles par défaut |\\n\",\n       \"|  |  | `` uml:plantuml='skinparam backgroundColor yellow\\\\nskinparam classAttributeFontName Arial\\\\n' `` | ajoute des styles personnalisés |\\n\",\n       \"\\n\",\n       \"### Opérations de réécriture\\n\",\n       \"\\n\",\n       \"| Sous-option | Description | Exemples | Explications |\\n\",\n       \"| :-- | :-- | :-- | :-- |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">arrange</span> | réarrange la disposition, soit par Branch & Bound, soit avec un algorithme génétique | `` arrange `` | B&B sans contraintes |\\n\",\n       \"|  |  | `` arrange:timeout=60 `` | B&B limité à une minute |\\n\",\n       \"|  |  | `` arrange:wide `` | B&B privilégiant la largeur |\\n\",\n       \"|  |  | `` arrange:current `` | B&B sur la grille courante |\\n\",\n       \"|  |  | `` arrange:balanced=0 `` | B&B sur la plus petite grille équilibrée |\\n\",\n       \"|  |  | `` arrange:balanced=1 `` | B&B sur la seconde plus petite grille équilibrée |\\n\",\n       \"|  |  | `` arrange:algo=ga `` | algorithme génétique |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">ascii</span> | réécrit les éléments donnés en ASCII | `` ascii:roles,labels `` | rôles, libellés des boîtes et des attributs en ASCII |\\n\",\n       \"| <span title=\\\"Alias : camelcase, camel_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">camel</span> | réécrit les éléments donnés en camelCase |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">capitalize</span> | réécrit les éléments donnés en capitalisant la première lettre de chaque mot |  |  |\\n\",\n       \"| <span title=\\\"Alias : case_fold.\\\" style=\\\"font-family:monospace; font-weight:600\\\">casefold</span> | réécrit les éléments donnés en minuscules, mais plus agressivement que « lower » |  |  |\\n\",\n       \"| <span title=\\\"Alias : add, insert, make, guess, infer, complete, new.\\\" style=\\\"font-family:monospace; font-weight:600\\\">create</span> | essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants | `` guess:types `` | deviner les types manquants |\\n\",\n       \"|  |  | `` create:types= `` | remplacer les types manquants par `[]` |\\n\",\n       \"|  |  | `` create:types=TODO `` | remplacer les types manquants par `[TODO]` |\\n\",\n       \"|  |  | `` make:entities `` | réparer l'oubli d'entités référencées dans des associations |\\n\",\n       \"|  |  | `` create:dfs `` | mettre des DF partout où c'est possible |\\n\",\n       \"|  |  | `` add:df_arrows `` | ajouter des flèches aux DF 11 |\\n\",\n       \"|  |  | `` add:cifs `` | ajouter les CIF correspondant aux agrégats |\\n\",\n       \"|  |  | `` add:cifs=light `` | même chose en visualisation allégée |\\n\",\n       \"|  |  | `` add:roles `` | mettre comme rôles le nom des associations partout où c'est utile |\\n\",\n       \"| <span title=\\\"Alias : del, suppress, erase, remove, hide, empty.\\\" style=\\\"font-family:monospace; font-weight:600\\\">delete</span> | supprime les éléments donnés quand c'est possible | `` empty `` | ne garde que la structure et le nom des boîtes |\\n\",\n       \"|  |  | `` delete:types,notes,attrs,cards `` | idem |\\n\",\n       \"|  |  | `` delete:cards `` | remplace les cardinalités par `XX` |\\n\",\n       \"|  |  | `` delete:card_prefixes `` | supprime les marqueurs d'entités faibles et d'agrégats |\\n\",\n       \"|  |  | `` delete:dfs `` | supprime les entités indépendantes dont tous les attributs sont identifiants (et les DF qui les relient) |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">drain</span> | déplace tout attribut d'association (1,1) vers l'entité appropriée |  |  |\\n\",\n       \"| <span title=\\\"Alias : drown_by_numbers, anonymize, anonymise.\\\" style=\\\"font-family:monospace; font-weight:600\\\">drown</span> | remplace tous les noms d'éléments par un libellé générique numéroté |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">echo</span> | réécrit le texte source tel quel |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">explode</span> | décompose toute association n-aire (*,N) en n associations binaires | `` explode arrange `` | décomposer les non-DF ternaires et plus, puis réarranger |\\n\",\n       \"|  |  | `` explode:arity=3 arrange `` | idem |\\n\",\n       \"|  |  | `` explode:weak arrange `` | idem, avec création d'entités faibles |\\n\",\n       \"|  |  | `` explode:arity=2.5 arrange `` | étendre aux non-DF binaires porteuses d'attributs |\\n\",\n       \"|  |  | `` explode:arity=2 arrange `` | étendre à toutes les non-DF binaires |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">fix</span> | essaie de corriger les erreurs courantes dans les éléments donnés | `` fix:cards `` | normaliser les cardinalités en 01, 11, 0N et 1N |\\n\",\n       \"| <span title=\\\"Alias : mirror, reflect.\\\" style=\\\"font-family:monospace; font-weight:600\\\">flip</span> | applique au diagramme une symétrie verticale, horizontale ou diagonale | `` flip:v `` | symétrie verticale |\\n\",\n       \"|  |  | `` flip:h `` | symétrie horizontale |\\n\",\n       \"|  |  | `` flip:d `` | symétrie selon la seconde diagonale |\\n\",\n       \"|  |  | `` flip:vhd `` | symétrie selon la première diagonale |\\n\",\n       \"|  |  | `` flip:dhv `` | idem (ordre indifférent) |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">grow</span> | ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations) | `` grow arrange `` | ajouter des éléments avec les paramètres par défaut, puis réarranger |\\n\",\n       \"|  |  | `` grow:n=10 `` | nombre total d'associations à ajouter (défaut) |\\n\",\n       \"|  |  | `` grow:arity_1=2 `` | nombre d'associations réflexives (défaut) |\\n\",\n       \"|  |  | `` grow:arity_3=2 `` | nombre d'associations ternaires (défaut) |\\n\",\n       \"|  |  | `` grow:arity_4=0 `` | nombre d'associations quaternaires (défaut) |\\n\",\n       \"|  |  | `` grow:doubles=1 `` | nombre d'associations liant deux mêmes entités (défaut) |\\n\",\n       \"|  |  | `` grow:composite_ids=1 `` | nombre d'identifiants composites (défaut) |\\n\",\n       \"|  |  | `` grow:ent_attrs=4 `` | nombre maximal d'attributs par entité (défaut) |\\n\",\n       \"|  |  | `` grow:assoc_attrs=2 `` | nombre maximal d'attributs par association (défaut) |\\n\",\n       \"|  |  | `` grow:'*1-*N'=3 `` | nombre d'associations `*1-*N` (défaut) |\\n\",\n       \"|  |  | `` grow:'01-11'=1 `` | nombre d'associations `01-11` (défaut) |\\n\",\n       \"|  |  | `` grow:'_11-*N'=1 `` | une entité faible (zéro par défaut) |\\n\",\n       \"|  |  | `` grow:'/1N-*N'=1 `` | un agrégat (zéro par défaut) |\\n\",\n       \"|  |  | `` grow:from_scratch arrange `` | à partir d'un MCD vide |\\n\",\n       \"|  |  | `` grow:grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange `` | créer un MCD d'entraînement à la conversion en relationnel |\\n\",\n       \"| <span title=\\\"Alias : lowercase, lower_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">lower</span> | réécrit les éléments donnés en minuscules | `` lower:attrs,roles `` | attributs et rôles en minuscules |\\n\",\n       \"| <span title=\\\"Alias : pascalcase, pascal_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">pascal</span> | réécrit les élements donnés en PascalCase |  |  |\\n\",\n       \"| <span title=\\\"Alias : prepend.\\\" style=\\\"font-family:monospace; font-weight:600\\\">prefix</span> | préfixe les éléments donnés avec la chaîne donnée | `` prefix:roles='-' `` | force les rôles à remplacer le nom des clés étrangères lors du passage au relationnel |\\n\",\n       \"| <span title=\\\"Alias : rand, random, randomise, obfuscate, obscure.\\\" style=\\\"font-family:monospace; font-weight:600\\\">randomize</span> | garde la structure, mais randomise les éléments donnés quand c'est possible | `` obfuscate `` | libellés remplacés par du Lorem Ipsum |\\n\",\n       \"|  |  | `` obfuscate:labels=lorem `` | idem |\\n\",\n       \"|  |  | `` obfuscate:labels=disparition `` | idem, lexique du roman de Perec |\\n\",\n       \"|  |  | `` obfuscate:labels=en4 `` | idem, mots anglais de 4 lettres (SFW) |\\n\",\n       \"|  |  | `` obfuscate:attrs=fr,boxes=fr5 `` | idem, mots français de longueur quelconque pour les attributs, de 5 lettres pour les boîtes |\\n\",\n       \"|  |  | `` randomize:types `` | types randomisés avec les fréquences de `default_datatypes_fr.tsv`. |\\n\",\n       \"| <span title=\\\"Alias : substitute, sub, repl.\\\" style=\\\"font-family:monospace; font-weight:600\\\">replace</span> | réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné | `` replace:boxes='DIRIGER/RÉPONDRE DE' `` | renomme une boîte |\\n\",\n       \"|  |  | `` replace:texts='personel/personnel' `` | corrige une faute d'orthographe |\\n\",\n       \"|  |  | `` replace:replace:texts='_/ ' `` | remplace les tirets bas par des espaces |\\n\",\n       \"|  |  | `` replace:types='VARCHAR/VARCHAR2' `` | modifie un nom de type |\\n\",\n       \"|  |  | `` replace:cards=0N/1N `` | remplace toutes les cardinalités 0N par 1N |\\n\",\n       \"|  |  | `` replace:cards=1N//1N `` | crée des agrégats un peu partout |\\n\",\n       \"|  |  | `` replace:cards='0/X' replace:cards='11/X1' replace:cards='1N/XN' `` | masque les cardinalités minimales |\\n\",\n       \"|  |  | `` delete:card_prefixes replace:cards=11/_11 `` | ajoute des marqueurs d'entités faibles |\\n\",\n       \"| <span title=\\\"Alias : cut, interval.\\\" style=\\\"font-family:monospace; font-weight:600\\\">slice</span> | réécrit les éléments donnés en n'en gardant qu'une tranche donnée | `` slice:boxes=5:10 `` | de l'indice 5 (inclus) à l'indice 10 (exclu) |\\n\",\n       \"|  |  | `` slice:boxes=5: `` | supprime les 5 premiers caractères |\\n\",\n       \"|  |  | `` slice:boxes=:5 `` | ne garde que les 5 premiers caractères |\\n\",\n       \"|  |  | `` slice:boxes=:-5 `` | supprime les 5 derniers caractères |\\n\",\n       \"|  |  | `` slice:boxes=: `` | équivalent de `echo` |\\n\",\n       \"|  |  | `` slice:boxes= `` | idem |\\n\",\n       \"|  |  | `` slice:boxes `` | idem |\\n\",\n       \"| <span title=\\\"Alias : snakecase, snake_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">snake</span> | réécrit les éléments donnés en snake_case |  |  |\\n\",\n       \"| <span style=\\\"font-family:monospace; font-weight:600\\\">split</span> | décompose toute association n-aire (*,1) en n-1 associations binaires | `` split arrange `` | décomposer, puis réarranger |\\n\",\n       \"| <span title=\\\"Alias : append.\\\" style=\\\"font-family:monospace; font-weight:600\\\">suffix</span> | suffixe les éléments donnés avec la chaîne donnée | `` suffix:boxes=1 `` | Ajoute un suffixe numérique au nom des boîtes en vue de mettre un MCD et sa copie sur le même diagramme. |\\n\",\n       \"| <span title=\\\"Alias : swap_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">swapcase</span> | réécrit les éléments donnés en inversant la casse de chaque lettre |  |  |\\n\",\n       \"| <span title=\\\"Alias : titlecase, title_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">title</span> | réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule |  |  |\\n\",\n       \"| <span title=\\\"Alias : trunc, shorten.\\\" style=\\\"font-family:monospace; font-weight:600\\\">truncate</span> | tronque les éléments donnés à la longueur donnée (par défaut : 64) | `` truncate:boxes=10 `` | tronque les noms des boîtes à 10 caractères |\\n\",\n       \"| <span title=\\\"Alias : uppercase, upper_case.\\\" style=\\\"font-family:monospace; font-weight:600\\\">upper</span> | réécrit les éléments donnés en majuscules | `` upper:boxes `` | noms des boîtes en majuscules |\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"execution_count\": 187,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Markdown(\\\"../fr_cheat_sheet.md\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Réécriture d'éléments donnés\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Dans l'aide-mémoire, de nombreuses opérations de réécriture sont décrites comme s'appliquant à des « éléments donnés ». Il s'agit de certains ensembles de _tokens_ produits par l'analyse syntaxique. Plus précisément :\\n\",\n    \"\\n\",\n    \"- `arrows` : flèches de pattes (suffixes `<` ou `>` des cardinalités).\\n\",\n    \"- `attrs` : libellés des attributs d'entités ou d'associations.\\n\",\n    \"- `boxes` : libellés des entités et associations.\\n\",\n    \"- `cards` : cardinalités (`11`, `1N`, etc., sans préfixe ni suffixe).\\n\",\n    \"- `card_prefixes` : préfixes de cardinalités (`_` pour les entités faibles, `/` pour les agrégats).\\n\",\n    \"- `constraint_notes` : messages affichés au survol d'une contrainte.\\n\",\n    \"- `labels` : libellés des entités, des associations et des attributs.\\n\",\n    \"- `leg_notes` : notes de pattes (rôles ou messages affichés au survol).\\n\",\n    \"- `notes` : équivalent de `roles` + `constraint_notes`.\\n\",\n    \"- `roles` : alias de `leg_notes`.\\n\",\n    \"- `texts` : équivalent de `labels` + `notes`.\\n\",\n    \"- `types` : types de données.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Fonctionnement de la commande magique\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il peut être utile de comprendre ce qui se passe en coulisses lorsque l'on invoque la commande magique sur une cellule d'un notebook Jupyter :\\n\",\n    \"\\n\",\n    \"- dans le répertoire courant est créé au besoin un sous-répertoire `mocodo_notebook` ;\\n\",\n    \"- le texte d'entrée y est sauvegardé sous le nom de `sandbox.mcd` ;\\n\",\n    \"- la commande est lancée sur ce fichier avec tous les paramètres donnés par l'utilisateur. Cela signifie que tous les fichiers générés le seront au même endroit sous les noms de `sandbox.svg`, `sandbox.html`, etc. (relisez-les avec la commande magique `%load`) ;\\n\",\n    \"- certains des fichiers générés sont affichés dans la sortie de la cellule, d'autres pas, selon les règles suivantes (`rw` et `cv` dénotent respectivement une opération de réécriture et de conversion) :\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"| commande | tracé<br>du MCD | résultat des<br>réécritures | résultats des<br>conversions |\\n\",\n    \"|:---|:---:|:---:|:---:|\\n\",\n    \"| `mocodo` | initial | - | - |\\n\",\n    \"| `mocodo -t` ou `mocodo --mld` | initial | - | MLD en<br>Markdown |\\n\",\n    \"| `mocodo -t rw1 rw2 ...` | final | final | - |\\n\",\n    \"| `mocodo -t             cv1 cv2 ...` | - | - | tous |\\n\",\n    \"| `mocodo -t rw1 rw2 ... cv1 cv2 ...` | final | - | tous |\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Ces règles d'affichage par défaut devraient répondre aux besoins les plus courants, mais l'option `--select` peut prendre le pas :\\n\",\n    \"\\n\",\n    \"- sans arguments, rien n'est affiché ;\\n\",\n    \"- l'argument `mcd` affiche le diagramme conceptuel ;\\n\",\n    \"- l'argument `rw` (ou un alias de commodité parmi `source`, `text`, `code`, `mocodo`) affiche le résultat de la _dernière_ réécriture ;\\n\",\n    \"- l'argument `cv` (ou un alias de commodité parmi `mld`, `ddl`, `sql`) affiche les résultats des conversions ;\\n\",\n    \"- ces arguments peuvent être librement combinés et ordonnés ;\\n\",\n    \"- l'argument `all` affiche tout ce qui est disponible, dans l'ordre `mcd`, `rw` et `cv` ;\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les conversions génèrent par défaut un fichier-texte. Un dessin s'affichera à la place :\\n\",\n    \"- pour l'argument `diagram` ;\\n\",\n    \"- avec l'option `--defer`, pour autant qu'un web-service de rendu soit défini pour le fichier en question.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Il est possible de mettre `-t` en majuscule. Dans ce cas :\\n\",\n    \"\\n\",\n    \"- s'il y a une ou plusieurs opérations de réécriture, le résultat de la dernière réécriture remplace le contenu de la cellule et la sortie est effacée ;\\n\",\n    \"- sinon, s'il y a une ou plusieurs opérations de conversion et que [Pyperclip](https://github.com/asweigart/pyperclip) est installé, le résultat de la dernière conversion est copié dans le presse-papier.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Gabarits de passage au relationnel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"L'algorithme convertissant la représentation interne d'un schéma relationnel en une représentation externe dans tel ou tel format est totalement découplé dudit format. Cela signifie que vous pouvez modifier ou créer un format sans écrire une seule ligne de code, mais en remplissant une espèce de formulaire, ou gabarit (_template_ en anglais).\\n\",\n    \"\\n\",\n    \"Si vous n'avez aucune velléité de le faire ou que vous n'êtes pas ami avec les expressions régulières, vous pouvez sauter cette section. Sinon, accrochez-vous, ça va devenir un peu technique.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Format des gabarits\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les gabarits de Mocodo étaient à l'origine écrits en JSON. Par conséquent, un grand nombre des caractères utilisés dans les expressions régulières devaient être échappés, ce qui rendait celles-ci (encore) plus difficiles à écrire, à relire et à tester. La version 4 passe à YAML, qui n'a pas cet inconvénient. Voici par exemple un extrait de gabarit dans l'ancienne syntaxe :\\n\",\n    \"\\n\",\n    \"```json\\n\",\n    \"    {\\n\",\n    \"      \\\"order\\\": 400,\\n\",\n    \"      \\\"comment\\\": \\\"Move all foreign keys constraints at the end of the document\\\",\\n\",\n    \"      \\\"search\\\": \\\"(?sm)(CREATE TABLE ([^\\\\n]+) \\\\\\\\(\\\\n(?:[^\\\\n]+\\\\n)*)  (FOREIGN KEY[^\\\\n]+),\\\\n(.*)\\\",\\n\",\n    \"      \\\"replace\\\": \\\"\\\\\\\\1\\\\\\\\4\\\\nALTER TABLE \\\\\\\\2 ADD \\\\\\\\3;\\\",\\n\",\n    \"      \\\"iterated\\\": true\\n\",\n    \"    },\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"... et le même dans la nouvelle :\\n\",\n    \"\\n\",\n    \"```yaml\\n\",\n    \"  - order: 400\\n\",\n    \"    comment: 'Move all foreign keys constraints at the end of the document'\\n\",\n    \"    search: '(?sm)(CREATE TABLE ([^\\\\n]+) \\\\(\\\\n(?:[^\\\\n]+\\\\n)*)  (FOREIGN KEY[^\\\\n]+),\\\\n(.*)'\\n\",\n    \"    replace: '\\\\1\\\\4\\\\nALTER TABLE \\\\2 ADD \\\\3;'\\n\",\n    \"    iterated: true\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"Si vous avez écrit vos propres gabarits JSON, vous pouvez les convertir automatiquement en YAML à l'aide du script `json_to_yaml_templates.py` fourni dans le répertoire `dev`.\\n\",\n    \"\\n\",\n    \"**Remarque.** Si les gabarits de Mocodo constituent des fichiers YAML valides, l'inverse n'est pas forcément vrai. Mocodo utilise un sous-ensemble sain de YAML adapté à ses besoins. Il a son propre _parser_ avec les particularités suivantes :\\n\",\n    \"\\n\",\n    \"- Un gabarit est un dictionnaire dont les valeurs sont :\\n\",\n    \"  - soit des types scalaires (chaînes, nombres, booléens, `null`) ;\\n\",\n    \"  - soit des listes de dictionnaires à valeurs scalaires.\\n\",\n    \"- Toute _valeur_ chaîne doit être délimitée par des simples quotes (`'`). Les quotes internes sont échappées en les doublant (`''`).\\n\",\n    \"- Les expressions régulières de recherche et de remplacement suivent les mêmes règles d'échappement que les r-strings de Python.\\n\",\n    \"- Les autres chaînes (notamment les chaînes de composition) ne demandent pas à échapper les anti-slashes, mais à doubler les accolades (règles des fr-strings). Exception : pour les distinguer du retour-chariot et de la tabulation, il faudra échapper les `\\\\n` et les `\\\\t` si on veut les laisser littéralement. Vous en avez un exemple pour `\\\\newcommand` et `\\\\title` dans le [_boilerplate_ du gabarit pour $\\\\LaTeX$](https://github.com/laowantong/mocodo/blob/53ba0fce41aaf7b8156821a50dd3d3f1051f8af0/mocodo/resources/relation_templates/latex-bce.yaml#L2).\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Dérivation de gabarits\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Depuis la version 3.1, il est possible de définir un gabarit dérivé d'un autre (qui lui-même peut dériver d'un autre, etc.). Dans le but de réduire les redondances et de faciliter les tests et la maintenance, la version 4.0 fait un usage intensif de cette fonctionnalité :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 188,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/svg+xml\": [\n       \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"738pt\\\" height=\\\"1853pt\\\" viewBox=\\\"0.00 0.00 737.75 1853.00\\\">\\n\",\n       \"<g id=\\\"graph0\\\" class=\\\"graph\\\" transform=\\\"scale(1 1) rotate(0) translate(4 1849)\\\">\\n\",\n       \"<title>G</title>\\n\",\n       \"<polygon fill=\\\"white\\\" stroke=\\\"none\\\" points=\\\"-4,4 -4,-1849 733.75,-1849 733.75,4 -4,4\\\"/>\\n\",\n       \"<!-- d2 -->\\n\",\n       \"<g id=\\\"node1\\\" class=\\\"node\\\">\\n\",\n       \"<title>d2</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M65,-36C65,-36 35,-36 35,-36 29,-36 23,-30 23,-24 23,-24 23,-12 23,-12 23,-6 29,0 35,0 35,0 65,0 65,0 71,0 77,-6 77,-12 77,-12 77,-24 77,-24 77,-30 71,-36 65,-36\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-12.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">d2</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- dbml -->\\n\",\n       \"<g id=\\\"node2\\\" class=\\\"node\\\">\\n\",\n       \"<title>dbml</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M65,-90C65,-90 35,-90 35,-90 29,-90 23,-84 23,-78 23,-78 23,-66 23,-66 23,-60 29,-54 35,-54 35,-54 65,-54 65,-54 71,-54 77,-60 77,-66 77,-66 77,-78 77,-78 77,-84 71,-90 65,-90\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-66.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">dbml</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- dbml&#45;b -->\\n\",\n       \"<g id=\\\"node3\\\" class=\\\"node\\\">\\n\",\n       \"<title>dbml-b</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M198.12,-90C198.12,-90 164.12,-90 164.12,-90 158.12,-90 152.12,-84 152.12,-78 152.12,-78 152.12,-66 152.12,-66 152.12,-60 158.12,-54 164.12,-54 164.12,-54 198.12,-54 198.12,-54 204.12,-54 210.12,-60 210.12,-66 210.12,-66 210.12,-78 210.12,-78 210.12,-84 204.12,-90 198.12,-90\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-66.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">dbml-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- dbml&#45;&gt;dbml&#45;b -->\\n\",\n       \"<g id=\\\"edge1\\\" class=\\\"edge\\\">\\n\",\n       \"<title>dbml-&gt;dbml-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M88.3,-72C108.81,-72 133.83,-72 152.56,-72\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"88.33,-68.5 78.33,-72 88.33,-75.5 88.33,-68.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql -->\\n\",\n       \"<g id=\\\"node4\\\" class=\\\"node\\\">\\n\",\n       \"<title>sql</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M65,-360C65,-360 35,-360 35,-360 29,-360 23,-354 23,-348 23,-348 23,-336 23,-336 23,-330 29,-324 35,-324 35,-324 65,-324 65,-324 71,-324 77,-330 77,-336 77,-336 77,-348 77,-348 77,-354 71,-360 65,-360\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-336.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">sql</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- ddl -->\\n\",\n       \"<g id=\\\"node5\\\" class=\\\"node\\\">\\n\",\n       \"<title>ddl</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-522C196.12,-522 166.12,-522 166.12,-522 160.12,-522 154.12,-516 154.12,-510 154.12,-510 154.12,-498 154.12,-498 154.12,-492 160.12,-486 166.12,-486 166.12,-486 196.12,-486 196.12,-486 202.12,-486 208.12,-492 208.12,-498 208.12,-498 208.12,-510 208.12,-510 208.12,-516 202.12,-522 196.12,-522\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-498.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">ddl</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;ddl -->\\n\",\n       \"<g id=\\\"edge2\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;ddl</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M68.97,-368.96C78.35,-383.17 89.94,-400.94 100,-417 116.51,-443.36 114.11,-454.91 136,-477 141.31,-482.36 147.89,-487.11 154.33,-491.07\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"72.15,-367.42 63.71,-361.02 66.32,-371.29 72.15,-367.42\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql -->\\n\",\n       \"<g id=\\\"node52\\\" class=\\\"node\\\">\\n\",\n       \"<title>mssql</title>\\n\",\n       \"<path fill=\\\"#ef3b2c\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-468C196.12,-468 166.12,-468 166.12,-468 160.12,-468 154.12,-462 154.12,-456 154.12,-456 154.12,-444 154.12,-444 154.12,-438 160.12,-432 166.12,-432 166.12,-432 196.12,-432 196.12,-432 202.12,-432 208.12,-438 208.12,-444 208.12,-444 208.12,-456 208.12,-456 208.12,-462 202.12,-468 196.12,-468\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-444.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">mssql</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;mssql -->\\n\",\n       \"<g id=\\\"edge46\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;mssql</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M80.97,-367.07C104.8,-387 137.54,-414.39 158.77,-432.14\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"83.4,-364.54 73.48,-360.81 78.91,-369.91 83.4,-364.54\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mysql -->\\n\",\n       \"<g id=\\\"node54\\\" class=\\\"node\\\">\\n\",\n       \"<title>mysql</title>\\n\",\n       \"<path fill=\\\"#ef3b2c\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-387C196.12,-387 166.12,-387 166.12,-387 160.12,-387 154.12,-381 154.12,-375 154.12,-375 154.12,-363 154.12,-363 154.12,-357 160.12,-351 166.12,-351 166.12,-351 196.12,-351 196.12,-351 202.12,-351 208.12,-357 208.12,-363 208.12,-363 208.12,-375 208.12,-375 208.12,-381 202.12,-387 196.12,-387\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-363.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">mysql</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;mysql -->\\n\",\n       \"<g id=\\\"edge48\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;mysql</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M88.03,-349.74C109.25,-354.18 135.36,-359.64 154.35,-363.61\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"88.81,-346.33 78.3,-347.71 87.37,-353.18 88.81,-346.33\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle -->\\n\",\n       \"<g id=\\\"node56\\\" class=\\\"node\\\">\\n\",\n       \"<title>oracle</title>\\n\",\n       \"<path fill=\\\"#ef3b2c\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-333C196.12,-333 166.12,-333 166.12,-333 160.12,-333 154.12,-327 154.12,-321 154.12,-321 154.12,-309 154.12,-309 154.12,-303 160.12,-297 166.12,-297 166.12,-297 196.12,-297 196.12,-297 202.12,-297 208.12,-303 208.12,-309 208.12,-309 208.12,-321 208.12,-321 208.12,-327 202.12,-333 196.12,-333\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-309.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">oracle</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;oracle -->\\n\",\n       \"<g id=\\\"edge50\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;oracle</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M88.03,-334.26C109.25,-329.82 135.36,-324.36 154.35,-320.39\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"87.37,-330.82 78.3,-336.29 88.81,-337.67 87.37,-330.82\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgresql -->\\n\",\n       \"<g id=\\\"node62\\\" class=\\\"node\\\">\\n\",\n       \"<title>postgresql</title>\\n\",\n       \"<path fill=\\\"#ef3b2c\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M208.25,-225C208.25,-225 154,-225 154,-225 148,-225 142,-219 142,-213 142,-213 142,-201 142,-201 142,-195 148,-189 154,-189 154,-189 208.25,-189 208.25,-189 214.25,-189 220.25,-195 220.25,-201 220.25,-201 220.25,-213 220.25,-213 220.25,-219 214.25,-225 208.25,-225\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-201.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">postgresql</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;postgresql -->\\n\",\n       \"<g id=\\\"edge56\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;postgresql</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M75.98,-315.88C101.7,-288.99 141.08,-247.82 163.32,-224.57\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"73.58,-313.33 69.19,-322.98 78.63,-318.17 73.58,-313.33\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sqlite -->\\n\",\n       \"<g id=\\\"node66\\\" class=\\\"node\\\">\\n\",\n       \"<title>sqlite</title>\\n\",\n       \"<path fill=\\\"#cb181d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-144C196.12,-144 166.12,-144 166.12,-144 160.12,-144 154.12,-138 154.12,-132 154.12,-132 154.12,-120 154.12,-120 154.12,-114 160.12,-108 166.12,-108 166.12,-108 196.12,-108 196.12,-108 202.12,-108 208.12,-114 208.12,-120 208.12,-120 208.12,-132 208.12,-132 208.12,-138 202.12,-144 196.12,-144\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-120.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">sqlite</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql&#45;&gt;sqlite -->\\n\",\n       \"<g id=\\\"edge60\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sql-&gt;sqlite</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M63.55,-314.05C78.87,-280.97 106.41,-224.75 136,-180 144.41,-167.27 155.23,-153.99 164.05,-143.79\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"60.45,-312.4 59.47,-322.95 66.81,-315.32 60.45,-312.4\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- debug -->\\n\",\n       \"<g id=\\\"node6\\\" class=\\\"node\\\">\\n\",\n       \"<title>debug</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M65,-462C65,-462 35,-462 35,-462 29,-462 23,-456 23,-450 23,-450 23,-438 23,-438 23,-432 29,-426 35,-426 35,-426 65,-426 65,-426 71,-426 77,-432 77,-438 77,-438 77,-450 77,-450 77,-456 71,-462 65,-462\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-438.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">debug</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- dependencies -->\\n\",\n       \"<g id=\\\"node7\\\" class=\\\"node\\\">\\n\",\n       \"<title>dependencies</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M88,-556C88,-556 12,-556 12,-556 6,-556 0,-550 0,-544 0,-544 0,-532 0,-532 0,-526 6,-520 12,-520 12,-520 88,-520 88,-520 94,-520 100,-526 100,-532 100,-532 100,-544 100,-544 100,-550 94,-556 88,-556\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-532.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">dependencies</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- diagram&#45;c -->\\n\",\n       \"<g id=\\\"node8\\\" class=\\\"node\\\">\\n\",\n       \"<title>diagram-c</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M76.38,-630C76.38,-630 23.62,-630 23.62,-630 17.63,-630 11.62,-624 11.62,-618 11.62,-618 11.62,-606 11.62,-606 11.62,-600 17.62,-594 23.62,-594 23.62,-594 76.38,-594 76.38,-594 82.38,-594 88.38,-600 88.38,-606 88.38,-606 88.38,-618 88.38,-618 88.38,-624 82.38,-630 76.38,-630\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-606.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">diagram-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- diagram -->\\n\",\n       \"<g id=\\\"node9\\\" class=\\\"node\\\">\\n\",\n       \"<title>diagram</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M201.88,-630C201.88,-630 160.38,-630 160.38,-630 154.38,-630 148.38,-624 148.38,-618 148.38,-618 148.38,-606 148.38,-606 148.38,-600 154.38,-594 160.38,-594 160.38,-594 201.88,-594 201.88,-594 207.88,-594 213.88,-600 213.88,-606 213.88,-606 213.88,-618 213.88,-618 213.88,-624 207.88,-630 201.88,-630\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-606.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">diagram</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- diagram&#45;c&#45;&gt;diagram -->\\n\",\n       \"<g id=\\\"edge3\\\" class=\\\"edge\\\">\\n\",\n       \"<title>diagram-c-&gt;diagram</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M99.43,-612C115.85,-612 133.77,-612 148.54,-612\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"99.86,-608.5 89.86,-612 99.86,-615.5 99.86,-608.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;bc -->\\n\",\n       \"<g id=\\\"node10\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-bc</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M199.62,-1764C199.62,-1764 162.62,-1764 162.62,-1764 156.62,-1764 150.62,-1758 150.62,-1752 150.62,-1752 150.62,-1740 150.62,-1740 150.62,-1734 156.62,-1728 162.62,-1728 162.62,-1728 199.62,-1728 199.62,-1728 205.62,-1728 211.62,-1734 211.62,-1740 211.62,-1740 211.62,-1752 211.62,-1752 211.62,-1758 205.62,-1764 199.62,-1764\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-1740.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;b -->\\n\",\n       \"<g id=\\\"node11\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.25,-1818C326.25,-1818 296,-1818 296,-1818 290,-1818 284,-1812 284,-1806 284,-1806 284,-1794 284,-1794 284,-1788 290,-1782 296,-1782 296,-1782 326.25,-1782 326.25,-1782 332.25,-1782 338.25,-1788 338.25,-1794 338.25,-1794 338.25,-1806 338.25,-1806 338.25,-1812 332.25,-1818 326.25,-1818\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1794.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;bc&#45;&gt;html&#45;b -->\\n\",\n       \"<g id=\\\"edge4\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-bc-&gt;html-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M222.03,-1762.83C242.36,-1771.41 266.5,-1781.6 284.36,-1789.13\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"223.46,-1759.64 212.89,-1758.98 220.74,-1766.09 223.46,-1759.64\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c -->\\n\",\n       \"<g id=\\\"node12\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-c</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M65,-1170C65,-1170 35,-1170 35,-1170 29,-1170 23,-1164 23,-1158 23,-1158 23,-1146 23,-1146 23,-1140 29,-1134 35,-1134 35,-1134 65,-1134 65,-1134 71,-1134 77,-1140 77,-1146 77,-1146 77,-1158 77,-1158 77,-1164 71,-1170 65,-1170\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"50\\\" y=\\\"-1146.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">html-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;html&#45;bc -->\\n\",\n       \"<g id=\\\"edge5\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;html-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M53.87,-1180.99C61.88,-1257.11 87.16,-1468.46 136,-1638 145.42,-1670.7 161.48,-1706.99 171.41,-1728.08\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"57.4,-1181.06 52.89,-1171.47 50.44,-1181.78 57.4,-1181.06\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce -->\\n\",\n       \"<g id=\\\"node13\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-ce</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M199.62,-1629C199.62,-1629 162.62,-1629 162.62,-1629 156.62,-1629 150.62,-1623 150.62,-1617 150.62,-1617 150.62,-1605 150.62,-1605 150.62,-1599 156.62,-1593 162.62,-1593 162.62,-1593 199.62,-1593 199.62,-1593 205.62,-1593 211.62,-1599 211.62,-1605 211.62,-1605 211.62,-1617 211.62,-1617 211.62,-1623 205.62,-1629 199.62,-1629\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-1605.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">html-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;html&#45;ce -->\\n\",\n       \"<g id=\\\"edge8\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;html-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M59.11,-1180.82C83.44,-1267.33 155.41,-1523.15 175.1,-1593.13\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"62.55,-1180.13 56.47,-1171.45 55.81,-1182.02 62.55,-1180.13\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html -->\\n\",\n       \"<g id=\\\"node17\\\" class=\\\"node\\\">\\n\",\n       \"<title>html</title>\\n\",\n       \"<path fill=\\\"#fc9272\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-1197C196.12,-1197 166.12,-1197 166.12,-1197 160.12,-1197 154.12,-1191 154.12,-1185 154.12,-1185 154.12,-1173 154.12,-1173 154.12,-1167 160.12,-1161 166.12,-1161 166.12,-1161 196.12,-1161 196.12,-1161 202.12,-1161 208.12,-1167 208.12,-1173 208.12,-1173 208.12,-1185 208.12,-1185 208.12,-1191 202.12,-1197 196.12,-1197\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-1173.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;html -->\\n\",\n       \"<g id=\\\"edge10\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;html</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M88.03,-1159.74C109.25,-1164.18 135.36,-1169.64 154.35,-1173.61\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"88.81,-1156.33 78.3,-1157.71 87.37,-1163.18 88.81,-1156.33\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;c -->\\n\",\n       \"<g id=\\\"node20\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-c</title>\\n\",\n       \"<path fill=\\\"#cb181d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M197,-1143C197,-1143 165.25,-1143 165.25,-1143 159.25,-1143 153.25,-1137 153.25,-1131 153.25,-1131 153.25,-1119 153.25,-1119 153.25,-1113 159.25,-1107 165.25,-1107 165.25,-1107 197,-1107 197,-1107 203,-1107 209,-1113 209,-1119 209,-1119 209,-1131 209,-1131 209,-1137 203,-1143 197,-1143\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-1119.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">latex-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;latex&#45;c -->\\n\",\n       \"<g id=\\\"edge15\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;latex-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M87.88,-1144.29C108.8,-1139.91 134.5,-1134.54 153.46,-1130.58\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"87.37,-1140.82 78.3,-1146.29 88.81,-1147.67 87.37,-1140.82\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;c -->\\n\",\n       \"<g id=\\\"node28\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-c</title>\\n\",\n       \"<path fill=\\\"#cb181d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M214.25,-981C214.25,-981 148,-981 148,-981 142,-981 136,-975 136,-969 136,-969 136,-957 136,-957 136,-951 142,-945 148,-945 148,-945 214.25,-945 214.25,-945 220.25,-945 226.25,-951 226.25,-957 226.25,-957 226.25,-969 226.25,-969 226.25,-975 220.25,-981 214.25,-981\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-957.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">markdown-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;markdown&#45;c -->\\n\",\n       \"<g id=\\\"edge23\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;markdown-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M69.62,-1124.74C96.45,-1085.48 145.23,-1014.08 167.92,-980.87\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"66.75,-1122.74 64,-1132.97 72.53,-1126.69 66.75,-1122.74\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;c -->\\n\",\n       \"<g id=\\\"node78\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-c</title>\\n\",\n       \"<path fill=\\\"#67000d\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M196.12,-765C196.12,-765 166.12,-765 166.12,-765 160.12,-765 154.12,-759 154.12,-753 154.12,-753 154.12,-741 154.12,-741 154.12,-735 160.12,-729 166.12,-729 166.12,-729 196.12,-729 196.12,-729 202.12,-729 208.12,-735 208.12,-741 208.12,-741 208.12,-753 208.12,-753 208.12,-759 202.12,-765 196.12,-765\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"181.12\\\" y=\\\"-741.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">text-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;c&#45;&gt;text&#45;c -->\\n\",\n       \"<g id=\\\"edge75\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-c-&gt;text-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M60.06,-1123.57C85.02,-1045.31 154.21,-828.29 174.48,-764.72\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"56.88,-1122.04 57.17,-1132.63 63.55,-1124.17 56.88,-1122.04\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;bce -->\\n\",\n       \"<g id=\\\"node14\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-bce</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M333.38,-1764C333.38,-1764 288.88,-1764 288.88,-1764 282.88,-1764 276.88,-1758 276.88,-1752 276.88,-1752 276.88,-1740 276.88,-1740 276.88,-1734 282.88,-1728 288.88,-1728 288.88,-1728 333.38,-1728 333.38,-1728 339.38,-1728 345.38,-1734 345.38,-1740 345.38,-1740 345.38,-1752 345.38,-1752 345.38,-1758 339.38,-1764 333.38,-1764\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1740.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce&#45;&gt;html&#45;bce -->\\n\",\n       \"<g id=\\\"edge6\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-ce-&gt;html-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M198,-1638.56C212.51,-1662.04 235.72,-1695.59 262.25,-1719 266.69,-1722.91 271.78,-1726.52 276.96,-1729.73\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"201.09,-1636.92 192.93,-1630.17 195.1,-1640.54 201.09,-1636.92\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;e -->\\n\",\n       \"<g id=\\\"node16\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-e</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.25,-1710C326.25,-1710 296,-1710 296,-1710 290,-1710 284,-1704 284,-1698 284,-1698 284,-1686 284,-1686 284,-1680 290,-1674 296,-1674 296,-1674 326.25,-1674 326.25,-1674 332.25,-1674 338.25,-1680 338.25,-1686 338.25,-1686 338.25,-1698 338.25,-1698 338.25,-1704 332.25,-1710 326.25,-1710\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1686.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce&#45;&gt;html&#45;e -->\\n\",\n       \"<g id=\\\"edge9\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-ce-&gt;html-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M216.66,-1635.15C230.65,-1644.7 247.06,-1655.62 262.25,-1665 269.23,-1669.31 276.93,-1673.77 284.07,-1677.8\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"218.88,-1632.43 208.65,-1629.65 214.91,-1638.2 218.88,-1632.43\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;ce -->\\n\",\n       \"<g id=\\\"node21\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-ce</title>\\n\",\n       \"<path fill=\\\"#a50f15\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M330.75,-1656C330.75,-1656 291.5,-1656 291.5,-1656 285.5,-1656 279.5,-1650 279.5,-1644 279.5,-1644 279.5,-1632 279.5,-1632 279.5,-1626 285.5,-1620 291.5,-1620 291.5,-1620 330.75,-1620 330.75,-1620 336.75,-1620 342.75,-1626 342.75,-1632 342.75,-1632 342.75,-1644 342.75,-1644 342.75,-1650 336.75,-1656 330.75,-1656\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1632.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">latex-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce&#45;&gt;latex&#45;ce -->\\n\",\n       \"<g id=\\\"edge16\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-ce-&gt;latex-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M222.52,-1619.52C240.98,-1623.41 262.48,-1627.95 279.56,-1631.55\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"223.48,-1616.15 212.97,-1617.51 222.03,-1623 223.48,-1616.15\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;ce -->\\n\",\n       \"<g id=\\\"node29\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-ce</title>\\n\",\n       \"<path fill=\\\"#a50f15\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M348,-1575C348,-1575 274.25,-1575 274.25,-1575 268.25,-1575 262.25,-1569 262.25,-1563 262.25,-1563 262.25,-1551 262.25,-1551 262.25,-1545 268.25,-1539 274.25,-1539 274.25,-1539 348,-1539 348,-1539 354,-1539 360,-1545 360,-1551 360,-1551 360,-1563 360,-1563 360,-1569 354,-1575 348,-1575\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1551.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">markdown-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce&#45;&gt;markdown&#45;ce -->\\n\",\n       \"<g id=\\\"edge24\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-ce-&gt;markdown-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M221.72,-1594.29C236.34,-1588.13 252.95,-1581.12 267.79,-1574.86\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"220.74,-1590.91 212.89,-1598.02 223.46,-1597.36 220.74,-1590.91\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;ce -->\\n\",\n       \"<g id=\\\"node81\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-ce</title>\\n\",\n       \"<path fill=\\\"#a50f15\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M327.38,-1386C327.38,-1386 294.88,-1386 294.88,-1386 288.88,-1386 282.88,-1380 282.88,-1374 282.88,-1374 282.88,-1362 282.88,-1362 282.88,-1356 288.88,-1350 294.88,-1350 294.88,-1350 327.38,-1350 327.38,-1350 333.38,-1350 339.38,-1356 339.38,-1362 339.38,-1362 339.38,-1374 339.38,-1374 339.38,-1380 333.38,-1386 327.38,-1386\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1362.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\" fill=\\\"white\\\">text-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;ce&#45;&gt;text&#45;ce -->\\n\",\n       \"<g id=\\\"edge76\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-ce-&gt;text-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M196.9,-1582.95C223.48,-1532.49 278.63,-1427.79 300.7,-1385.89\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"193.81,-1581.31 192.24,-1591.79 200,-1584.58 193.81,-1581.31\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;be -->\\n\",\n       \"<g id=\\\"node15\\\" class=\\\"node\\\">\\n\",\n       \"<title>html-be</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M467.5,-1845C467.5,-1845 429.75,-1845 429.75,-1845 423.75,-1845 417.75,-1839 417.75,-1833 417.75,-1833 417.75,-1821 417.75,-1821 417.75,-1815 423.75,-1809 429.75,-1809 429.75,-1809 467.5,-1809 467.5,-1809 473.5,-1809 479.5,-1815 479.5,-1821 479.5,-1821 479.5,-1833 479.5,-1833 479.5,-1839 473.5,-1845 467.5,-1845\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1821.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">html-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- html&#45;bce&#45;&gt;html&#45;be -->\\n\",\n       \"<g id=\\\"edge7\\\" class=\\\"edge\\\">\\n\",\n       \"<title>html-bce-&gt;html-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M355.02,-1769.83C356.72,-1770.88 358.38,-1771.94 360,-1773 376.75,-1783.94 379.08,-1789.33 396,-1800 402.93,-1804.37 410.64,-1808.68 417.95,-1812.53\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"356.84,-1766.83 346.47,-1764.67 353.23,-1772.83 356.84,-1766.83\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bc -->\\n\",\n       \"<g id=\\\"node18\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-bc</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M330.75,-1197C330.75,-1197 291.5,-1197 291.5,-1197 285.5,-1197 279.5,-1191 279.5,-1185 279.5,-1185 279.5,-1173 279.5,-1173 279.5,-1167 285.5,-1161 291.5,-1161 291.5,-1161 330.75,-1161 330.75,-1161 336.75,-1161 342.75,-1167 342.75,-1173 342.75,-1173 342.75,-1185 342.75,-1185 342.75,-1191 336.75,-1197 330.75,-1197\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1173.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;b -->\\n\",\n       \"<g id=\\\"node19\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M464.88,-1251C464.88,-1251 432.38,-1251 432.38,-1251 426.38,-1251 420.38,-1245 420.38,-1239 420.38,-1239 420.38,-1227 420.38,-1227 420.38,-1221 426.38,-1215 432.38,-1215 432.38,-1215 464.88,-1215 464.88,-1215 470.88,-1215 476.88,-1221 476.88,-1227 476.88,-1227 476.88,-1239 476.88,-1239 476.88,-1245 470.88,-1251 464.88,-1251\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1227.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bc&#45;&gt;latex&#45;b -->\\n\",\n       \"<g id=\\\"edge11\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-bc-&gt;latex-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M353.17,-1195.36C375.01,-1204.06 401.26,-1214.52 420.53,-1222.2\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.53,-1192.13 343.94,-1191.68 351.93,-1198.63 354.53,-1192.13\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;bc -->\\n\",\n       \"<g id=\\\"node71\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-1197C463.62,-1197 433.62,-1197 433.62,-1197 427.62,-1197 421.62,-1191 421.62,-1185 421.62,-1185 421.62,-1173 421.62,-1173 421.62,-1167 427.62,-1161 433.62,-1161 433.62,-1161 463.62,-1161 463.62,-1161 469.62,-1161 475.62,-1167 475.62,-1173 475.62,-1173 475.62,-1185 475.62,-1185 475.62,-1191 469.62,-1197 463.62,-1197\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1173.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bc&#45;&gt;tex&#45;bc -->\\n\",\n       \"<g id=\\\"edge64\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-bc-&gt;tex-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M354,-1179C376.19,-1179 402.73,-1179 421.87,-1179\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.05,-1175.5 344.05,-1179 354.05,-1182.5 354.05,-1175.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;b -->\\n\",\n       \"<g id=\\\"node70\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1251C601.5,-1251 571.5,-1251 571.5,-1251 565.5,-1251 559.5,-1245 559.5,-1239 559.5,-1239 559.5,-1227 559.5,-1227 559.5,-1221 565.5,-1215 571.5,-1215 571.5,-1215 601.5,-1215 601.5,-1215 607.5,-1215 613.5,-1221 613.5,-1227 613.5,-1227 613.5,-1239 613.5,-1239 613.5,-1245 607.5,-1251 601.5,-1251\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1227.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;b&#45;&gt;tex&#45;b -->\\n\",\n       \"<g id=\\\"edge63\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-b-&gt;tex-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M488.2,-1233C511.12,-1233 539.56,-1233 559.76,-1233\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"488.31,-1229.5 478.31,-1233 488.31,-1236.5 488.31,-1229.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;c&#45;&gt;latex&#45;bc -->\\n\",\n       \"<g id=\\\"edge12\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-c-&gt;latex-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.44,-1140.74C238.61,-1148.83 261.67,-1158.56 279.74,-1166.18\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"220.93,-1137.57 210.35,-1136.91 218.21,-1144.02 220.93,-1137.57\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex -->\\n\",\n       \"<g id=\\\"node25\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex</title>\\n\",\n       \"<path fill=\\\"#fc9272\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-1143C326.12,-1143 296.12,-1143 296.12,-1143 290.12,-1143 284.12,-1137 284.12,-1131 284.12,-1131 284.12,-1119 284.12,-1119 284.12,-1113 290.12,-1107 296.12,-1107 296.12,-1107 326.12,-1107 326.12,-1107 332.12,-1107 338.12,-1113 338.12,-1119 338.12,-1119 338.12,-1131 338.12,-1131 338.12,-1137 332.12,-1143 326.12,-1143\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1119.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;c&#45;&gt;latex -->\\n\",\n       \"<g id=\\\"edge18\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-c-&gt;latex</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M220.22,-1125C240.86,-1125 265.82,-1125 284.2,-1125\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"220.47,-1121.5 210.47,-1125 220.47,-1128.5 220.47,-1121.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;c -->\\n\",\n       \"<g id=\\\"node74\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-c</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-1089C326.12,-1089 296.12,-1089 296.12,-1089 290.12,-1089 284.12,-1083 284.12,-1077 284.12,-1077 284.12,-1065 284.12,-1065 284.12,-1059 290.12,-1053 296.12,-1053 296.12,-1053 326.12,-1053 326.12,-1053 332.12,-1053 338.12,-1059 338.12,-1065 338.12,-1065 338.12,-1077 338.12,-1077 338.12,-1083 332.12,-1089 326.12,-1089\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1065.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;c&#45;&gt;tex&#45;c -->\\n\",\n       \"<g id=\\\"edge67\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-c-&gt;tex-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.36,-1109.29C240.16,-1100.52 265.57,-1089.8 284.2,-1081.94\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"218.21,-1105.98 210.35,-1113.09 220.93,-1112.43 218.21,-1105.98\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bce -->\\n\",\n       \"<g id=\\\"node22\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-bce</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M472,-1791C472,-1791 425.25,-1791 425.25,-1791 419.25,-1791 413.25,-1785 413.25,-1779 413.25,-1779 413.25,-1767 413.25,-1767 413.25,-1761 419.25,-1755 425.25,-1755 425.25,-1755 472,-1755 472,-1755 478,-1755 484,-1761 484,-1767 484,-1767 484,-1779 484,-1779 484,-1785 478,-1791 472,-1791\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1767.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;ce&#45;&gt;latex&#45;bce -->\\n\",\n       \"<g id=\\\"edge13\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-ce-&gt;latex-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M352.12,-1657.77C354.96,-1659.99 357.64,-1662.4 360,-1665 386.5,-1694.15 369.04,-1717.27 396,-1746 400.91,-1751.24 407.07,-1755.65 413.41,-1759.28\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.1,-1654.89 343.86,-1652.16 350.17,-1660.68 354.1,-1654.89\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;e -->\\n\",\n       \"<g id=\\\"node24\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-e</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M464.88,-1737C464.88,-1737 432.38,-1737 432.38,-1737 426.38,-1737 420.38,-1731 420.38,-1725 420.38,-1725 420.38,-1713 420.38,-1713 420.38,-1707 426.38,-1701 432.38,-1701 432.38,-1701 464.88,-1701 464.88,-1701 470.88,-1701 476.88,-1707 476.88,-1713 476.88,-1713 476.88,-1725 476.88,-1725 476.88,-1731 470.88,-1737 464.88,-1737\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1713.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;ce&#45;&gt;latex&#45;e -->\\n\",\n       \"<g id=\\\"edge17\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-ce-&gt;latex-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M352.26,-1660.12C354.9,-1661.73 357.5,-1663.37 360,-1665 376.75,-1675.94 379.08,-1681.33 396,-1692 403.79,-1696.91 412.56,-1701.74 420.63,-1705.93\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.31,-1657.26 343.92,-1655.18 350.74,-1663.29 354.31,-1657.26\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;ce -->\\n\",\n       \"<g id=\\\"node75\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-ce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-1683C463.62,-1683 433.62,-1683 433.62,-1683 427.62,-1683 421.62,-1677 421.62,-1671 421.62,-1671 421.62,-1659 421.62,-1659 421.62,-1653 427.62,-1647 433.62,-1647 433.62,-1647 463.62,-1647 463.62,-1647 469.62,-1647 475.62,-1653 475.62,-1659 475.62,-1659 475.62,-1671 475.62,-1671 475.62,-1677 469.62,-1683 463.62,-1683\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1659.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;ce&#45;&gt;tex&#45;ce -->\\n\",\n       \"<g id=\\\"edge68\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-ce-&gt;tex-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M353.7,-1646.28C375.94,-1650.72 402.64,-1656.04 421.87,-1659.87\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.51,-1642.88 344.02,-1644.36 353.14,-1649.74 354.51,-1642.88\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;be -->\\n\",\n       \"<g id=\\\"node23\\\" class=\\\"node\\\">\\n\",\n       \"<title>latex-be</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M606.5,-1845C606.5,-1845 566.5,-1845 566.5,-1845 560.5,-1845 554.5,-1839 554.5,-1833 554.5,-1833 554.5,-1821 554.5,-1821 554.5,-1815 560.5,-1809 566.5,-1809 566.5,-1809 606.5,-1809 606.5,-1809 612.5,-1809 618.5,-1815 618.5,-1821 618.5,-1821 618.5,-1833 618.5,-1833 618.5,-1839 612.5,-1845 606.5,-1845\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1821.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">latex-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bce&#45;&gt;latex&#45;be -->\\n\",\n       \"<g id=\\\"edge14\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-bce-&gt;latex-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M494.56,-1790.86C514.37,-1798.73 537.13,-1807.78 554.93,-1814.85\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"495.9,-1787.63 485.32,-1787.19 493.32,-1794.13 495.9,-1787.63\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;bce -->\\n\",\n       \"<g id=\\\"node72\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M604.62,-1791C604.62,-1791 568.38,-1791 568.38,-1791 562.38,-1791 556.38,-1785 556.38,-1779 556.38,-1779 556.38,-1767 556.38,-1767 556.38,-1761 562.38,-1755 568.38,-1755 568.38,-1755 604.62,-1755 604.62,-1755 610.62,-1755 616.62,-1761 616.62,-1767 616.62,-1767 616.62,-1779 616.62,-1779 616.62,-1785 610.62,-1791 604.62,-1791\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1767.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;bce&#45;&gt;tex&#45;bce -->\\n\",\n       \"<g id=\\\"edge65\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-bce-&gt;tex-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M495.16,-1773C515.51,-1773 538.87,-1773 556.74,-1773\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"495.43,-1769.5 485.43,-1773 495.43,-1776.5 495.43,-1769.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;be -->\\n\",\n       \"<g id=\\\"node73\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-be</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M715.75,-1845C715.75,-1845 685.75,-1845 685.75,-1845 679.75,-1845 673.75,-1839 673.75,-1833 673.75,-1833 673.75,-1821 673.75,-1821 673.75,-1815 679.75,-1809 685.75,-1809 685.75,-1809 715.75,-1809 715.75,-1809 721.75,-1809 727.75,-1815 727.75,-1821 727.75,-1821 727.75,-1833 727.75,-1833 727.75,-1839 721.75,-1845 715.75,-1845\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"700.75\\\" y=\\\"-1821.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;be&#45;&gt;tex&#45;be -->\\n\",\n       \"<g id=\\\"edge66\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-be-&gt;tex-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M629.93,-1827C644.69,-1827 660.8,-1827 673.81,-1827\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"629.98,-1823.5 619.98,-1827 629.98,-1830.5 629.98,-1823.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex&#45;e -->\\n\",\n       \"<g id=\\\"node76\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex-e</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1737C601.5,-1737 571.5,-1737 571.5,-1737 565.5,-1737 559.5,-1731 559.5,-1725 559.5,-1725 559.5,-1713 559.5,-1713 559.5,-1707 565.5,-1701 571.5,-1701 571.5,-1701 601.5,-1701 601.5,-1701 607.5,-1701 613.5,-1707 613.5,-1713 613.5,-1713 613.5,-1725 613.5,-1725 613.5,-1731 607.5,-1737 601.5,-1737\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1713.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;e&#45;&gt;tex&#45;e -->\\n\",\n       \"<g id=\\\"edge69\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-e-&gt;tex-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M488.2,-1719C511.12,-1719 539.56,-1719 559.76,-1719\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"488.31,-1715.5 478.31,-1719 488.31,-1722.5 488.31,-1715.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- tex -->\\n\",\n       \"<g id=\\\"node77\\\" class=\\\"node\\\">\\n\",\n       \"<title>tex</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-1143C463.62,-1143 433.62,-1143 433.62,-1143 427.62,-1143 421.62,-1137 421.62,-1131 421.62,-1131 421.62,-1119 421.62,-1119 421.62,-1113 427.62,-1107 433.62,-1107 433.62,-1107 463.62,-1107 463.62,-1107 469.62,-1107 475.62,-1113 475.62,-1119 475.62,-1119 475.62,-1131 475.62,-1131 475.62,-1137 469.62,-1143 463.62,-1143\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1119.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">tex</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- latex&#45;&gt;tex -->\\n\",\n       \"<g id=\\\"edge70\\\" class=\\\"edge\\\">\\n\",\n       \"<title>latex-&gt;tex</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M349.36,-1125C372.41,-1125 401.41,-1125 421.92,-1125\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"349.44,-1121.5 339.44,-1125 349.44,-1128.5 349.44,-1121.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bc -->\\n\",\n       \"<g id=\\\"node26\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M348,-1035C348,-1035 274.25,-1035 274.25,-1035 268.25,-1035 262.25,-1029 262.25,-1023 262.25,-1023 262.25,-1011 262.25,-1011 262.25,-1005 268.25,-999 274.25,-999 274.25,-999 348,-999 348,-999 354,-999 360,-1005 360,-1011 360,-1011 360,-1023 360,-1023 360,-1029 354,-1035 348,-1035\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-1011.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;b -->\\n\",\n       \"<g id=\\\"node27\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M482.12,-1089C482.12,-1089 415.12,-1089 415.12,-1089 409.12,-1089 403.12,-1083 403.12,-1077 403.12,-1077 403.12,-1065 403.12,-1065 403.12,-1059 409.12,-1053 415.12,-1053 415.12,-1053 482.12,-1053 482.12,-1053 488.12,-1053 494.12,-1059 494.12,-1065 494.12,-1065 494.12,-1077 494.12,-1077 494.12,-1083 488.12,-1089 482.12,-1089\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1065.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bc&#45;&gt;markdown&#45;b -->\\n\",\n       \"<g id=\\\"edge19\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bc-&gt;markdown-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M367.86,-1039.21C379.62,-1043.9 391.88,-1048.79 403.16,-1053.28\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"369.24,-1035.99 358.65,-1035.54 366.64,-1042.5 369.24,-1035.99\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;bc -->\\n\",\n       \"<g id=\\\"node35\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.75,-1035C463.75,-1035 433.5,-1035 433.5,-1035 427.5,-1035 421.5,-1029 421.5,-1023 421.5,-1023 421.5,-1011 421.5,-1011 421.5,-1005 427.5,-999 433.5,-999 433.5,-999 463.75,-999 463.75,-999 469.75,-999 475.75,-1005 475.75,-1011 475.75,-1011 475.75,-1023 475.75,-1023 475.75,-1029 469.75,-1035 463.75,-1035\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1011.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bc&#45;&gt;md&#45;bc -->\\n\",\n       \"<g id=\\\"edge28\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bc-&gt;md-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M371.28,-1017C388.86,-1017 407.22,-1017 421.53,-1017\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"371.41,-1013.5 361.41,-1017 371.41,-1020.5 371.41,-1013.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;bc -->\\n\",\n       \"<g id=\\\"node43\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M465.25,-981C465.25,-981 432,-981 432,-981 426,-981 420,-975 420,-969 420,-969 420,-957 420,-957 420,-951 426,-945 432,-945 432,-945 465.25,-945 465.25,-945 471.25,-945 477.25,-951 477.25,-957 477.25,-957 477.25,-969 477.25,-969 477.25,-975 471.25,-981 465.25,-981\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-957.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bc&#45;&gt;mld&#45;bc -->\\n\",\n       \"<g id=\\\"edge36\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bc-&gt;mld-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M367.69,-994.85C385.74,-987.66 404.99,-979.99 420.07,-973.98\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"366.64,-991.5 358.65,-998.46 369.24,-998.01 366.64,-991.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;b -->\\n\",\n       \"<g id=\\\"node34\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1116C601.5,-1116 571.5,-1116 571.5,-1116 565.5,-1116 559.5,-1110 559.5,-1104 559.5,-1104 559.5,-1092 559.5,-1092 559.5,-1086 565.5,-1080 571.5,-1080 571.5,-1080 601.5,-1080 601.5,-1080 607.5,-1080 613.5,-1086 613.5,-1092 613.5,-1092 613.5,-1104 613.5,-1104 613.5,-1110 607.5,-1116 601.5,-1116\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1092.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;b&#45;&gt;md&#45;b -->\\n\",\n       \"<g id=\\\"edge27\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-b-&gt;md-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M505.29,-1082.06C524.09,-1085.8 544.19,-1089.79 559.56,-1092.85\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"506.09,-1078.65 495.6,-1080.14 504.73,-1085.52 506.09,-1078.65\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;b -->\\n\",\n       \"<g id=\\\"node42\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1062C601.5,-1062 571.5,-1062 571.5,-1062 565.5,-1062 559.5,-1056 559.5,-1050 559.5,-1050 559.5,-1038 559.5,-1038 559.5,-1032 565.5,-1026 571.5,-1026 571.5,-1026 601.5,-1026 601.5,-1026 607.5,-1026 613.5,-1032 613.5,-1038 613.5,-1038 613.5,-1050 613.5,-1050 613.5,-1056 607.5,-1062 601.5,-1062\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1038.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;b&#45;&gt;mld&#45;b -->\\n\",\n       \"<g id=\\\"edge35\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-b-&gt;mld-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M505.29,-1059.94C524.09,-1056.2 544.19,-1052.21 559.56,-1049.15\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"504.73,-1056.48 495.6,-1061.86 506.09,-1063.35 504.73,-1056.48\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;c&#45;&gt;markdown&#45;bc -->\\n\",\n       \"<g id=\\\"edge20\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-c-&gt;markdown-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M235.34,-985.45C246.13,-990 257.34,-994.73 267.69,-999.1\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"236.72,-982.23 226.14,-981.57 233.99,-988.68 236.72,-982.23\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown -->\\n\",\n       \"<g id=\\\"node33\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown</title>\\n\",\n       \"<path fill=\\\"#fc9272\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M338.62,-981C338.62,-981 283.62,-981 283.62,-981 277.62,-981 271.62,-975 271.62,-969 271.62,-969 271.62,-957 271.62,-957 271.62,-951 277.62,-945 283.62,-945 283.62,-945 338.62,-945 338.62,-945 344.62,-945 350.62,-951 350.62,-957 350.62,-957 350.62,-969 350.62,-969 350.62,-975 344.62,-981 338.62,-981\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-957.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;c&#45;&gt;markdown -->\\n\",\n       \"<g id=\\\"edge26\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-c-&gt;markdown</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M237.59,-963C249.19,-963 261.17,-963 271.97,-963\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"237.69,-959.5 227.69,-963 237.69,-966.5 237.69,-959.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;c -->\\n\",\n       \"<g id=\\\"node38\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-c</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-927C326.12,-927 296.12,-927 296.12,-927 290.12,-927 284.12,-921 284.12,-915 284.12,-915 284.12,-903 284.12,-903 284.12,-897 290.12,-891 296.12,-891 296.12,-891 326.12,-891 326.12,-891 332.12,-891 338.12,-897 338.12,-903 338.12,-903 338.12,-915 338.12,-915 338.12,-921 332.12,-927 326.12,-927\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-903.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;c&#45;&gt;md&#45;c -->\\n\",\n       \"<g id=\\\"edge31\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-c-&gt;md-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M235.17,-940.62C252.22,-933.43 270.32,-925.79 284.47,-919.82\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"233.99,-937.32 226.14,-944.43 236.72,-943.77 233.99,-937.32\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;c -->\\n\",\n       \"<g id=\\\"node46\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-c</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-873C326.12,-873 296.12,-873 296.12,-873 290.12,-873 284.12,-867 284.12,-861 284.12,-861 284.12,-849 284.12,-849 284.12,-843 290.12,-837 296.12,-837 296.12,-837 326.12,-837 326.12,-837 332.12,-837 338.12,-843 338.12,-849 338.12,-849 338.12,-861 338.12,-861 338.12,-867 332.12,-873 326.12,-873\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-849.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;c&#45;&gt;mld&#45;c -->\\n\",\n       \"<g id=\\\"edge39\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-c-&gt;mld-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M204.55,-936.83C219.78,-919.97 240.96,-898.25 262.25,-882 269.08,-876.79 277.02,-871.9 284.45,-867.76\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"202.19,-934.22 198.16,-944.02 207.42,-938.87 202.19,-934.22\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bce -->\\n\",\n       \"<g id=\\\"node30\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M489.25,-1629C489.25,-1629 408,-1629 408,-1629 402,-1629 396,-1623 396,-1617 396,-1617 396,-1605 396,-1605 396,-1599 402,-1593 408,-1593 408,-1593 489.25,-1593 489.25,-1593 495.25,-1593 501.25,-1599 501.25,-1605 501.25,-1605 501.25,-1617 501.25,-1617 501.25,-1623 495.25,-1629 489.25,-1629\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1605.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;ce&#45;&gt;markdown&#45;bce -->\\n\",\n       \"<g id=\\\"edge21\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-ce-&gt;markdown-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M367.75,-1579.17C379.39,-1583.81 391.51,-1588.64 402.7,-1593.1\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"369.24,-1575.99 358.65,-1575.54 366.64,-1582.5 369.24,-1575.99\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;e -->\\n\",\n       \"<g id=\\\"node32\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-e</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M482.12,-1575C482.12,-1575 415.12,-1575 415.12,-1575 409.12,-1575 403.12,-1569 403.12,-1563 403.12,-1563 403.12,-1551 403.12,-1551 403.12,-1545 409.12,-1539 415.12,-1539 415.12,-1539 482.12,-1539 482.12,-1539 488.12,-1539 494.12,-1545 494.12,-1551 494.12,-1551 494.12,-1563 494.12,-1563 494.12,-1569 488.12,-1575 482.12,-1575\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1551.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;ce&#45;&gt;markdown&#45;e -->\\n\",\n       \"<g id=\\\"edge25\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-ce-&gt;markdown-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M371.41,-1557C382.17,-1557 393.22,-1557 403.45,-1557\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"371.41,-1553.5 361.41,-1557 371.41,-1560.5 371.41,-1553.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;ce -->\\n\",\n       \"<g id=\\\"node39\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-ce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.75,-1521C463.75,-1521 433.5,-1521 433.5,-1521 427.5,-1521 421.5,-1515 421.5,-1509 421.5,-1509 421.5,-1497 421.5,-1497 421.5,-1491 427.5,-1485 433.5,-1485 433.5,-1485 463.75,-1485 463.75,-1485 469.75,-1485 475.75,-1491 475.75,-1497 475.75,-1497 475.75,-1509 475.75,-1509 475.75,-1515 469.75,-1521 463.75,-1521\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1497.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;ce&#45;&gt;md&#45;ce -->\\n\",\n       \"<g id=\\\"edge32\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-ce-&gt;md-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M367.75,-1534.83C386.42,-1527.39 406.37,-1519.44 421.66,-1513.35\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"366.64,-1531.5 358.65,-1538.46 369.24,-1538.01 366.64,-1531.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;ce -->\\n\",\n       \"<g id=\\\"node47\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-ce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M465.25,-1467C465.25,-1467 432,-1467 432,-1467 426,-1467 420,-1461 420,-1455 420,-1455 420,-1443 420,-1443 420,-1437 426,-1431 432,-1431 432,-1431 465.25,-1431 465.25,-1431 471.25,-1431 477.25,-1437 477.25,-1443 477.25,-1443 477.25,-1455 477.25,-1455 477.25,-1461 471.25,-1467 465.25,-1467\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1443.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;ce&#45;&gt;mld&#45;ce -->\\n\",\n       \"<g id=\\\"edge40\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-ce-&gt;mld-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M335.63,-1530.68C351.59,-1513.77 373.77,-1492.04 396,-1476 403.46,-1470.62 412.15,-1465.65 420.23,-1461.48\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"333.15,-1528.21 328.91,-1537.93 338.28,-1532.98 333.15,-1528.21\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;be -->\\n\",\n       \"<g id=\\\"node31\\\" class=\\\"node\\\">\\n\",\n       \"<title>markdown-be</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M623.75,-1683C623.75,-1683 549.25,-1683 549.25,-1683 543.25,-1683 537.25,-1677 537.25,-1671 537.25,-1671 537.25,-1659 537.25,-1659 537.25,-1653 543.25,-1647 549.25,-1647 549.25,-1647 623.75,-1647 623.75,-1647 629.75,-1647 635.75,-1653 635.75,-1659 635.75,-1659 635.75,-1671 635.75,-1671 635.75,-1677 629.75,-1683 623.75,-1683\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1659.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">markdown-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bce&#45;&gt;markdown&#45;be -->\\n\",\n       \"<g id=\\\"edge22\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bce-&gt;markdown-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M505.4,-1633.17C517.07,-1637.81 529.23,-1642.64 540.45,-1647.1\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"506.86,-1629.98 496.28,-1629.54 504.28,-1636.49 506.86,-1629.98\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;bce -->\\n\",\n       \"<g id=\\\"node36\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M605.38,-1629C605.38,-1629 567.62,-1629 567.62,-1629 561.62,-1629 555.62,-1623 555.62,-1617 555.62,-1617 555.62,-1605 555.62,-1605 555.62,-1599 561.62,-1593 567.62,-1593 567.62,-1593 605.38,-1593 605.38,-1593 611.38,-1593 617.38,-1599 617.38,-1605 617.38,-1605 617.38,-1617 617.38,-1617 617.38,-1623 611.38,-1629 605.38,-1629\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1605.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bce&#45;&gt;md&#45;bce -->\\n\",\n       \"<g id=\\\"edge29\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bce-&gt;md-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M512.43,-1611C527.53,-1611 542.97,-1611 555.74,-1611\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"512.51,-1607.5 502.51,-1611 512.51,-1614.5 512.51,-1607.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;bce -->\\n\",\n       \"<g id=\\\"node44\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M606.88,-1575C606.88,-1575 566.12,-1575 566.12,-1575 560.12,-1575 554.12,-1569 554.12,-1563 554.12,-1563 554.12,-1551 554.12,-1551 554.12,-1545 560.12,-1539 566.12,-1539 566.12,-1539 606.88,-1539 606.88,-1539 612.88,-1539 618.88,-1545 618.88,-1551 618.88,-1551 618.88,-1563 618.88,-1563 618.88,-1569 612.88,-1575 606.88,-1575\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1551.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;bce&#45;&gt;mld&#45;bce -->\\n\",\n       \"<g id=\\\"edge37\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-bce-&gt;mld-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M505.11,-1588.95C521.84,-1582.3 539.61,-1575.24 554.17,-1569.45\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"504.28,-1585.51 496.28,-1592.46 506.86,-1592.02 504.28,-1585.51\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;be -->\\n\",\n       \"<g id=\\\"node37\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-be</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M716.25,-1710C716.25,-1710 685.25,-1710 685.25,-1710 679.25,-1710 673.25,-1704 673.25,-1698 673.25,-1698 673.25,-1686 673.25,-1686 673.25,-1680 679.25,-1674 685.25,-1674 685.25,-1674 716.25,-1674 716.25,-1674 722.25,-1674 728.25,-1680 728.25,-1686 728.25,-1686 728.25,-1698 728.25,-1698 728.25,-1704 722.25,-1710 716.25,-1710\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"700.75\\\" y=\\\"-1686.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;be&#45;&gt;md&#45;be -->\\n\",\n       \"<g id=\\\"edge30\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-be-&gt;md-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M646.47,-1679.18C655.88,-1681.45 665.19,-1683.69 673.33,-1685.65\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"647.44,-1675.82 636.9,-1676.88 645.81,-1682.62 647.44,-1675.82\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;be -->\\n\",\n       \"<g id=\\\"node45\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-be</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M717.75,-1656C717.75,-1656 683.75,-1656 683.75,-1656 677.75,-1656 671.75,-1650 671.75,-1644 671.75,-1644 671.75,-1632 671.75,-1632 671.75,-1626 677.75,-1620 683.75,-1620 683.75,-1620 717.75,-1620 717.75,-1620 723.75,-1620 729.75,-1626 729.75,-1632 729.75,-1632 729.75,-1644 729.75,-1644 729.75,-1650 723.75,-1656 717.75,-1656\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"700.75\\\" y=\\\"-1632.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;be&#45;&gt;mld&#45;be -->\\n\",\n       \"<g id=\\\"edge38\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-be-&gt;mld-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M646.55,-1650.8C655.34,-1648.68 664.03,-1646.59 671.76,-1644.73\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"645.81,-1647.38 636.9,-1653.12 647.44,-1654.18 645.81,-1647.38\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md&#45;e -->\\n\",\n       \"<g id=\\\"node40\\\" class=\\\"node\\\">\\n\",\n       \"<title>md-e</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1521C601.5,-1521 571.5,-1521 571.5,-1521 565.5,-1521 559.5,-1515 559.5,-1509 559.5,-1509 559.5,-1497 559.5,-1497 559.5,-1491 565.5,-1485 571.5,-1485 571.5,-1485 601.5,-1485 601.5,-1485 607.5,-1485 613.5,-1491 613.5,-1497 613.5,-1497 613.5,-1509 613.5,-1509 613.5,-1515 607.5,-1521 601.5,-1521\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1497.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;e&#45;&gt;md&#45;e -->\\n\",\n       \"<g id=\\\"edge33\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-e-&gt;md-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M504.76,-1535.09C523.72,-1527.55 544.04,-1519.48 559.56,-1513.31\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"503.52,-1531.81 495.52,-1538.76 506.11,-1538.32 503.52,-1531.81\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld&#45;e -->\\n\",\n       \"<g id=\\\"node48\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld-e</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1467C601.5,-1467 571.5,-1467 571.5,-1467 565.5,-1467 559.5,-1461 559.5,-1455 559.5,-1455 559.5,-1443 559.5,-1443 559.5,-1437 565.5,-1431 571.5,-1431 571.5,-1431 601.5,-1431 601.5,-1431 607.5,-1431 613.5,-1437 613.5,-1443 613.5,-1443 613.5,-1455 613.5,-1455 613.5,-1461 607.5,-1467 601.5,-1467\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1443.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;e&#45;&gt;mld&#45;e -->\\n\",\n       \"<g id=\\\"edge41\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-e-&gt;mld-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M498.4,-1532.43C499.38,-1531.64 500.33,-1530.83 501.25,-1530 522.7,-1510.71 516.08,-1495.59 537.25,-1476 543.87,-1469.87 552.14,-1464.6 559.95,-1460.39\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"496.41,-1529.55 490.3,-1538.21 500.48,-1535.25 496.41,-1529.55\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- md -->\\n\",\n       \"<g id=\\\"node41\\\" class=\\\"node\\\">\\n\",\n       \"<title>md</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-927C463.62,-927 433.62,-927 433.62,-927 427.62,-927 421.62,-921 421.62,-915 421.62,-915 421.62,-903 421.62,-903 421.62,-897 427.62,-891 433.62,-891 433.62,-891 463.62,-891 463.62,-891 469.62,-891 475.62,-897 475.62,-903 475.62,-903 475.62,-915 475.62,-915 475.62,-921 469.62,-927 463.62,-927\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-903.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">md</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;&gt;md -->\\n\",\n       \"<g id=\\\"edge34\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-&gt;md</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M361.08,-943.49C381.67,-935.28 404.78,-926.08 421.93,-919.24\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"359.99,-940.16 352,-947.11 362.58,-946.66 359.99,-940.16\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mld -->\\n\",\n       \"<g id=\\\"node49\\\" class=\\\"node\\\">\\n\",\n       \"<title>mld</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-873C463.62,-873 433.62,-873 433.62,-873 427.62,-873 421.62,-867 421.62,-861 421.62,-861 421.62,-849 421.62,-849 421.62,-843 427.62,-837 433.62,-837 433.62,-837 463.62,-837 463.62,-837 469.62,-837 475.62,-843 475.62,-849 475.62,-849 475.62,-861 475.62,-861 475.62,-867 469.62,-873 463.62,-873\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-849.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mld</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- markdown&#45;&gt;mld -->\\n\",\n       \"<g id=\\\"edge42\\\" class=\\\"edge\\\">\\n\",\n       \"<title>markdown-&gt;mld</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M357.18,-938.48C358.15,-937.67 359.09,-936.84 360,-936 381.14,-916.38 374.55,-901.29 396,-882 403.52,-875.24 413.04,-869.64 421.86,-865.33\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"355.12,-935.66 349.16,-944.42 359.28,-941.28 355.12,-935.66\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;b -->\\n\",\n       \"<g id=\\\"node50\\\" class=\\\"node\\\">\\n\",\n       \"<title>mssql-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M331.12,-603C331.12,-603 291.12,-603 291.12,-603 285.12,-603 279.12,-597 279.12,-591 279.12,-591 279.12,-579 279.12,-579 279.12,-573 285.12,-567 291.12,-567 291.12,-567 331.12,-567 331.12,-567 337.12,-567 343.12,-573 343.12,-579 343.12,-579 343.12,-591 343.12,-591 343.12,-597 337.12,-603 331.12,-603\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-579.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mssql-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- ms_sql&#45;b -->\\n\",\n       \"<g id=\\\"node51\\\" class=\\\"node\\\">\\n\",\n       \"<title>ms_sql-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M472.38,-657C472.38,-657 424.88,-657 424.88,-657 418.88,-657 412.88,-651 412.88,-645 412.88,-645 412.88,-633 412.88,-633 412.88,-627 418.88,-621 424.88,-621 424.88,-621 472.38,-621 472.38,-621 478.38,-621 484.38,-627 484.38,-633 484.38,-633 484.38,-645 484.38,-645 484.38,-651 478.38,-657 472.38,-657\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-633.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">ms_sql-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;b&#45;&gt;ms_sql&#45;b -->\\n\",\n       \"<g id=\\\"edge43\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-b-&gt;ms_sql-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M353.4,-601.45C372.52,-609.07 394.99,-618.02 413.19,-625.28\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.86,-598.26 344.28,-597.81 352.27,-604.77 354.86,-598.26\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql_server&#45;b -->\\n\",\n       \"<g id=\\\"node64\\\" class=\\\"node\\\">\\n\",\n       \"<title>sql_server-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M481.75,-603C481.75,-603 415.5,-603 415.5,-603 409.5,-603 403.5,-597 403.5,-591 403.5,-591 403.5,-579 403.5,-579 403.5,-573 409.5,-567 415.5,-567 415.5,-567 481.75,-567 481.75,-567 487.75,-567 493.75,-573 493.75,-579 493.75,-579 493.75,-591 493.75,-591 493.75,-597 487.75,-603 481.75,-603\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-579.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">sql_server-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;b&#45;&gt;sql_server&#45;b -->\\n\",\n       \"<g id=\\\"edge57\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-b-&gt;sql_server-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M354.37,-585C370.03,-585 387.83,-585 403.64,-585\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.39,-581.5 344.39,-585 354.39,-588.5 354.39,-581.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sqlserver&#45;b -->\\n\",\n       \"<g id=\\\"node68\\\" class=\\\"node\\\">\\n\",\n       \"<title>sqlserver-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M478,-549C478,-549 419.25,-549 419.25,-549 413.25,-549 407.25,-543 407.25,-537 407.25,-537 407.25,-525 407.25,-525 407.25,-519 413.25,-513 419.25,-513 419.25,-513 478,-513 478,-513 484,-513 490,-519 490,-525 490,-525 490,-537 490,-537 490,-543 484,-549 478,-549\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-525.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">sqlserver-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;b&#45;&gt;sqlserver&#45;b -->\\n\",\n       \"<g id=\\\"edge61\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-b-&gt;sqlserver-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M353.19,-568.63C370.41,-561.77 390.36,-553.82 407.48,-547\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"352.27,-565.23 344.28,-572.19 354.86,-571.74 352.27,-565.23\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;&gt;mssql&#45;b -->\\n\",\n       \"<g id=\\\"edge45\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-&gt;mssql-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M217.35,-468.71C220.58,-471.24 223.62,-474.01 226.25,-477 252.23,-506.62 235.75,-528.85 262.25,-558 267,-563.23 273,-567.69 279.14,-571.39\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"219.39,-465.86 209.17,-463.08 215.42,-471.63 219.39,-465.86\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- ms_sql -->\\n\",\n       \"<g id=\\\"node53\\\" class=\\\"node\\\">\\n\",\n       \"<title>ms_sql</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M328.88,-549C328.88,-549 293.38,-549 293.38,-549 287.38,-549 281.38,-543 281.38,-537 281.38,-537 281.38,-525 281.38,-525 281.38,-519 287.38,-513 293.38,-513 293.38,-513 328.88,-513 328.88,-513 334.88,-513 340.88,-519 340.88,-525 340.88,-525 340.88,-537 340.88,-537 340.88,-543 334.88,-549 328.88,-549\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-525.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">ms_sql</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;&gt;ms_sql -->\\n\",\n       \"<g id=\\\"edge44\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-&gt;ms_sql</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M217.53,-471.26C220.5,-473.16 223.44,-475.09 226.25,-477 242.8,-488.23 245.5,-493.06 262.25,-504 268.32,-507.97 275.01,-511.96 281.41,-515.61\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"219.66,-468.46 209.33,-466.11 215.94,-474.39 219.66,-468.46\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sql_server -->\\n\",\n       \"<g id=\\\"node65\\\" class=\\\"node\\\">\\n\",\n       \"<title>sql_server</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M338.25,-495C338.25,-495 284,-495 284,-495 278,-495 272,-489 272,-483 272,-483 272,-471 272,-471 272,-465 278,-459 284,-459 284,-459 338.25,-459 338.25,-459 344.25,-459 350.25,-465 350.25,-471 350.25,-471 350.25,-483 350.25,-483 350.25,-489 344.25,-495 338.25,-495\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-471.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">sql_server</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;&gt;sql_server -->\\n\",\n       \"<g id=\\\"edge58\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-&gt;sql_server</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.01,-457.78C235.67,-461.29 255.33,-465.44 272.12,-468.98\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"220.02,-454.42 209.51,-455.78 218.57,-461.26 220.02,-454.42\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sqlserver -->\\n\",\n       \"<g id=\\\"node69\\\" class=\\\"node\\\">\\n\",\n       \"<title>sqlserver</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M334.5,-441C334.5,-441 287.75,-441 287.75,-441 281.75,-441 275.75,-435 275.75,-429 275.75,-429 275.75,-417 275.75,-417 275.75,-411 281.75,-405 287.75,-405 287.75,-405 334.5,-405 334.5,-405 340.5,-405 346.5,-411 346.5,-417 346.5,-417 346.5,-429 346.5,-429 346.5,-435 340.5,-441 334.5,-441\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-417.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">sqlserver</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mssql&#45;&gt;sqlserver -->\\n\",\n       \"<g id=\\\"edge62\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mssql-&gt;sqlserver</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.23,-442.17C237.14,-438.39 258.5,-433.89 276,-430.2\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"218.57,-438.74 209.51,-444.22 220.02,-445.58 218.57,-438.74\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- mysql&#45;b -->\\n\",\n       \"<g id=\\\"node55\\\" class=\\\"node\\\">\\n\",\n       \"<title>mysql-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M331.12,-387C331.12,-387 291.12,-387 291.12,-387 285.12,-387 279.12,-381 279.12,-375 279.12,-375 279.12,-363 279.12,-363 279.12,-357 285.12,-351 291.12,-351 291.12,-351 331.12,-351 331.12,-351 337.12,-351 343.12,-357 343.12,-363 343.12,-363 343.12,-375 343.12,-375 343.12,-381 337.12,-387 331.12,-387\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-363.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">mysql-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- mysql&#45;&gt;mysql&#45;b -->\\n\",\n       \"<g id=\\\"edge47\\\" class=\\\"edge\\\">\\n\",\n       \"<title>mysql-&gt;mysql-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.31,-369C238.35,-369 261.25,-369 279.3,-369\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"219.54,-365.5 209.54,-369 219.54,-372.5 219.54,-365.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle&#45;b -->\\n\",\n       \"<g id=\\\"node57\\\" class=\\\"node\\\">\\n\",\n       \"<title>oracle-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M331.5,-333C331.5,-333 290.75,-333 290.75,-333 284.75,-333 278.75,-327 278.75,-321 278.75,-321 278.75,-309 278.75,-309 278.75,-303 284.75,-297 290.75,-297 290.75,-297 331.5,-297 331.5,-297 337.5,-297 343.5,-303 343.5,-309 343.5,-309 343.5,-321 343.5,-321 343.5,-327 337.5,-333 331.5,-333\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-309.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">oracle-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle&#45;&gt;oracle&#45;b -->\\n\",\n       \"<g id=\\\"edge49\\\" class=\\\"edge\\\">\\n\",\n       \"<title>oracle-&gt;oracle-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.49,-315C238.33,-315 260.92,-315 278.83,-315\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"219.54,-311.5 209.54,-315 219.54,-318.5 219.54,-311.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle_db -->\\n\",\n       \"<g id=\\\"node59\\\" class=\\\"node\\\">\\n\",\n       \"<title>oracle_db</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M336.75,-279C336.75,-279 285.5,-279 285.5,-279 279.5,-279 273.5,-273 273.5,-267 273.5,-267 273.5,-255 273.5,-255 273.5,-249 279.5,-243 285.5,-243 285.5,-243 336.75,-243 336.75,-243 342.75,-243 348.75,-249 348.75,-255 348.75,-255 348.75,-267 348.75,-267 348.75,-273 342.75,-279 336.75,-279\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-255.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">oracle_db</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle&#45;&gt;oracle_db -->\\n\",\n       \"<g id=\\\"edge52\\\" class=\\\"edge\\\">\\n\",\n       \"<title>oracle-&gt;oracle_db</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M218.3,-299.74C235.59,-292.44 256.25,-283.73 273.59,-276.41\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"217.28,-296.37 209.42,-303.48 220,-302.82 217.28,-296.37\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle_db&#45;b -->\\n\",\n       \"<g id=\\\"node58\\\" class=\\\"node\\\">\\n\",\n       \"<title>oracle_db-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M480.25,-333C480.25,-333 417,-333 417,-333 411,-333 405,-327 405,-321 405,-321 405,-309 405,-309 405,-303 411,-297 417,-297 417,-297 480.25,-297 480.25,-297 486.25,-297 492.25,-303 492.25,-309 492.25,-309 492.25,-321 492.25,-321 492.25,-327 486.25,-333 480.25,-333\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-309.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">oracle_db-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- oracle&#45;b&#45;&gt;oracle_db&#45;b -->\\n\",\n       \"<g id=\\\"edge51\\\" class=\\\"edge\\\">\\n\",\n       \"<title>oracle-b-&gt;oracle_db-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M354.49,-315C370.62,-315 388.99,-315 405.13,-315\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"354.73,-311.5 344.72,-315 354.72,-318.5 354.73,-311.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgresql&#45;b -->\\n\",\n       \"<g id=\\\"node60\\\" class=\\\"node\\\">\\n\",\n       \"<title>postgresql-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M344.25,-225C344.25,-225 278,-225 278,-225 272,-225 266,-219 266,-213 266,-213 266,-201 266,-201 266,-195 272,-189 278,-189 278,-189 344.25,-189 344.25,-189 350.25,-189 356.25,-195 356.25,-201 356.25,-201 356.25,-213 356.25,-213 356.25,-219 350.25,-225 344.25,-225\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-201.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">postgresql-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgres&#45;b -->\\n\",\n       \"<g id=\\\"node61\\\" class=\\\"node\\\">\\n\",\n       \"<title>postgres-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M476.5,-225C476.5,-225 420.75,-225 420.75,-225 414.75,-225 408.75,-219 408.75,-213 408.75,-213 408.75,-201 408.75,-201 408.75,-195 414.75,-189 420.75,-189 420.75,-189 476.5,-189 476.5,-189 482.5,-189 488.5,-195 488.5,-201 488.5,-201 488.5,-213 488.5,-213 488.5,-219 482.5,-225 476.5,-225\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-201.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">postgres-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgresql&#45;b&#45;&gt;postgres&#45;b -->\\n\",\n       \"<g id=\\\"edge53\\\" class=\\\"edge\\\">\\n\",\n       \"<title>postgresql-b-&gt;postgres-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M367.55,-207C381.42,-207 396.01,-207 408.87,-207\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"367.63,-203.5 357.63,-207 367.63,-210.5 367.63,-203.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgresql&#45;&gt;postgresql&#45;b -->\\n\",\n       \"<g id=\\\"edge55\\\" class=\\\"edge\\\">\\n\",\n       \"<title>postgresql-&gt;postgresql-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M231.35,-207C242.81,-207 254.93,-207 266.14,-207\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"231.7,-203.5 221.7,-207 231.7,-210.5 231.7,-203.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgres -->\\n\",\n       \"<g id=\\\"node63\\\" class=\\\"node\\\">\\n\",\n       \"<title>postgres</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M333,-171C333,-171 289.25,-171 289.25,-171 283.25,-171 277.25,-165 277.25,-159 277.25,-159 277.25,-147 277.25,-147 277.25,-141 283.25,-135 289.25,-135 289.25,-135 333,-135 333,-135 339,-135 345,-141 345,-147 345,-147 345,-159 345,-159 345,-165 339,-171 333,-171\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-147.57\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">postgres</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- postgresql&#45;&gt;postgres -->\\n\",\n       \"<g id=\\\"edge54\\\" class=\\\"edge\\\">\\n\",\n       \"<title>postgresql-&gt;postgres</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M230.77,-186.48C246.44,-179.87 263.41,-172.71 277.62,-166.71\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"229.43,-183.24 221.58,-190.36 232.15,-189.69 229.43,-183.24\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- sqlite&#45;b -->\\n\",\n       \"<g id=\\\"node67\\\" class=\\\"node\\\">\\n\",\n       \"<title>sqlite-b</title>\\n\",\n       \"<path fill=\\\"#fee0d2\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M328.88,-117C328.88,-117 293.38,-117 293.38,-117 287.38,-117 281.38,-111 281.38,-105 281.38,-105 281.38,-93 281.38,-93 281.38,-87 287.38,-81 293.38,-81 293.38,-81 328.88,-81 328.88,-81 334.88,-81 340.88,-87 340.88,-93 340.88,-93 340.88,-105 340.88,-105 340.88,-111 334.88,-117 328.88,-117\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-93.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">sqlite-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- sqlite&#45;&gt;sqlite&#45;b -->\\n\",\n       \"<g id=\\\"edge59\\\" class=\\\"edge\\\">\\n\",\n       \"<title>sqlite-&gt;sqlite-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.17,-118.19C239.05,-113.99 263.18,-108.9 281.59,-105.02\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"218.57,-114.74 209.51,-120.22 220.02,-121.58 218.57,-114.74\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;b -->\\n\",\n       \"<g id=\\\"node79\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-b</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-819C326.12,-819 296.12,-819 296.12,-819 290.12,-819 284.12,-813 284.12,-807 284.12,-807 284.12,-795 284.12,-795 284.12,-789 290.12,-783 296.12,-783 296.12,-783 326.12,-783 326.12,-783 332.12,-783 338.12,-789 338.12,-795 338.12,-795 338.12,-807 338.12,-807 338.12,-813 332.12,-819 326.12,-819\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-795.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;c&#45;&gt;text&#45;b -->\\n\",\n       \"<g id=\\\"edge71\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-c-&gt;text-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M218.49,-762.34C239.47,-771.19 265.36,-782.11 284.26,-790.09\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"220,-759.18 209.42,-758.52 217.28,-765.63 220,-759.18\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;bc -->\\n\",\n       \"<g id=\\\"node80\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M327.38,-765C327.38,-765 294.88,-765 294.88,-765 288.88,-765 282.88,-759 282.88,-753 282.88,-753 282.88,-741 282.88,-741 282.88,-735 288.88,-729 294.88,-729 294.88,-729 327.38,-729 327.38,-729 333.38,-729 339.38,-735 339.38,-741 339.38,-741 339.38,-753 339.38,-753 339.38,-759 333.38,-765 327.38,-765\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-741.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;c&#45;&gt;text&#45;bc -->\\n\",\n       \"<g id=\\\"edge72\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-c-&gt;text-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M219.41,-747C239.73,-747 264.44,-747 282.94,-747\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"219.54,-743.5 209.54,-747 219.54,-750.5 219.54,-743.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text -->\\n\",\n       \"<g id=\\\"node85\\\" class=\\\"node\\\">\\n\",\n       \"<title>text</title>\\n\",\n       \"<path fill=\\\"#fc9272\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-711C326.12,-711 296.12,-711 296.12,-711 290.12,-711 284.12,-705 284.12,-699 284.12,-699 284.12,-687 284.12,-687 284.12,-681 290.12,-675 296.12,-675 296.12,-675 326.12,-675 326.12,-675 332.12,-675 338.12,-681 338.12,-687 338.12,-687 338.12,-699 338.12,-699 338.12,-705 332.12,-711 326.12,-711\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-687.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;c&#45;&gt;text -->\\n\",\n       \"<g id=\\\"edge78\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-c-&gt;text</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M218.49,-731.66C239.47,-722.81 265.36,-711.89 284.26,-703.91\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"217.28,-728.37 209.42,-735.48 220,-734.82 217.28,-728.37\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;c -->\\n\",\n       \"<g id=\\\"node90\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-c</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M326.12,-657C326.12,-657 296.12,-657 296.12,-657 290.12,-657 284.12,-651 284.12,-645 284.12,-645 284.12,-633 284.12,-633 284.12,-627 290.12,-621 296.12,-621 296.12,-621 326.12,-621 326.12,-621 332.12,-621 338.12,-627 338.12,-633 338.12,-633 338.12,-645 338.12,-645 338.12,-651 332.12,-657 326.12,-657\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"311.12\\\" y=\\\"-633.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-c</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;c&#45;&gt;txt&#45;c -->\\n\",\n       \"<g id=\\\"edge83\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-c-&gt;txt-c</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M204.55,-720.83C219.78,-703.97 240.96,-682.25 262.25,-666 269.08,-660.79 277.02,-655.9 284.45,-651.76\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"202.19,-718.22 198.16,-728.02 207.42,-722.87 202.19,-718.22\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;b -->\\n\",\n       \"<g id=\\\"node86\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-b</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-819C463.62,-819 433.62,-819 433.62,-819 427.62,-819 421.62,-813 421.62,-807 421.62,-807 421.62,-795 421.62,-795 421.62,-789 427.62,-783 433.62,-783 433.62,-783 463.62,-783 463.62,-783 469.62,-783 475.62,-789 475.62,-795 475.62,-795 475.62,-807 475.62,-807 475.62,-813 469.62,-819 463.62,-819\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-795.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-b</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;b&#45;&gt;txt&#45;b -->\\n\",\n       \"<g id=\\\"edge79\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-b-&gt;txt-b</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M349.36,-801C372.41,-801 401.41,-801 421.92,-801\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"349.44,-797.5 339.44,-801 349.44,-804.5 349.44,-797.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;bc -->\\n\",\n       \"<g id=\\\"node87\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-bc</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-765C463.62,-765 433.62,-765 433.62,-765 427.62,-765 421.62,-759 421.62,-753 421.62,-753 421.62,-741 421.62,-741 421.62,-735 427.62,-729 433.62,-729 433.62,-729 463.62,-729 463.62,-729 469.62,-729 475.62,-735 475.62,-741 475.62,-741 475.62,-753 475.62,-753 475.62,-759 469.62,-765 463.62,-765\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-741.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-bc</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;bc&#45;&gt;txt&#45;bc -->\\n\",\n       \"<g id=\\\"edge80\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-bc-&gt;txt-bc</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M350.6,-747C373.45,-747 401.81,-747 421.95,-747\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"350.73,-743.5 340.73,-747 350.73,-750.5 350.73,-743.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;bce -->\\n\",\n       \"<g id=\\\"node82\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M468.62,-1413C468.62,-1413 428.62,-1413 428.62,-1413 422.62,-1413 416.62,-1407 416.62,-1401 416.62,-1401 416.62,-1389 416.62,-1389 416.62,-1383 422.62,-1377 428.62,-1377 428.62,-1377 468.62,-1377 468.62,-1377 474.62,-1377 480.62,-1383 480.62,-1389 480.62,-1389 480.62,-1401 480.62,-1401 480.62,-1407 474.62,-1413 468.62,-1413\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1389.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;ce&#45;&gt;text&#45;bce -->\\n\",\n       \"<g id=\\\"edge73\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-ce-&gt;text-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M350.34,-1375.61C371.35,-1379.8 397.07,-1384.93 416.79,-1388.86\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"351.2,-1372.22 340.7,-1373.69 349.83,-1379.08 351.2,-1372.22\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;e -->\\n\",\n       \"<g id=\\\"node84\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-e</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-1359C463.62,-1359 433.62,-1359 433.62,-1359 427.62,-1359 421.62,-1353 421.62,-1347 421.62,-1347 421.62,-1335 421.62,-1335 421.62,-1329 427.62,-1323 433.62,-1323 433.62,-1323 463.62,-1323 463.62,-1323 469.62,-1323 475.62,-1329 475.62,-1335 475.62,-1335 475.62,-1347 475.62,-1347 475.62,-1353 469.62,-1359 463.62,-1359\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1335.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;ce&#45;&gt;text&#45;e -->\\n\",\n       \"<g id=\\\"edge77\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-ce-&gt;text-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M350.28,-1360.4C373.19,-1355.83 401.72,-1350.15 421.95,-1346.12\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"349.83,-1356.92 340.7,-1362.31 351.2,-1363.78 349.83,-1356.92\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;ce -->\\n\",\n       \"<g id=\\\"node91\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-ce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-1305C463.62,-1305 433.62,-1305 433.62,-1305 427.62,-1305 421.62,-1299 421.62,-1293 421.62,-1293 421.62,-1281 421.62,-1281 421.62,-1275 427.62,-1269 433.62,-1269 433.62,-1269 463.62,-1269 463.62,-1269 469.62,-1269 475.62,-1275 475.62,-1281 475.62,-1281 475.62,-1293 475.62,-1293 475.62,-1299 469.62,-1305 463.62,-1305\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-1281.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-ce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;ce&#45;&gt;txt&#45;ce -->\\n\",\n       \"<g id=\\\"edge84\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-ce-&gt;txt-ce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M347.82,-1344.01C362.55,-1334.38 379.91,-1323.36 396,-1314 404.22,-1309.22 413.36,-1304.31 421.64,-1300.01\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"346.25,-1340.85 339.83,-1349.28 350.1,-1346.7 346.25,-1340.85\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;be -->\\n\",\n       \"<g id=\\\"node83\\\" class=\\\"node\\\">\\n\",\n       \"<title>text-be</title>\\n\",\n       \"<path fill=\\\"#fcbba1\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M603.12,-1413C603.12,-1413 569.88,-1413 569.88,-1413 563.88,-1413 557.88,-1407 557.88,-1401 557.88,-1401 557.88,-1389 557.88,-1389 557.88,-1383 563.88,-1377 569.88,-1377 569.88,-1377 603.12,-1377 603.12,-1377 609.12,-1377 615.12,-1383 615.12,-1389 615.12,-1389 615.12,-1401 615.12,-1401 615.12,-1407 609.12,-1413 603.12,-1413\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1389.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">text-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;bce&#45;&gt;text&#45;be -->\\n\",\n       \"<g id=\\\"edge74\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-bce-&gt;text-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M491.94,-1395C513.49,-1395 539.06,-1395 558.02,-1395\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"491.97,-1391.5 481.97,-1395 491.97,-1398.5 491.97,-1391.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;bce -->\\n\",\n       \"<g id=\\\"node88\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-bce</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M602.75,-1359C602.75,-1359 570.25,-1359 570.25,-1359 564.25,-1359 558.25,-1353 558.25,-1347 558.25,-1347 558.25,-1335 558.25,-1335 558.25,-1329 564.25,-1323 570.25,-1323 570.25,-1323 602.75,-1323 602.75,-1323 608.75,-1323 614.75,-1329 614.75,-1335 614.75,-1335 614.75,-1347 614.75,-1347 614.75,-1353 608.75,-1359 602.75,-1359\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1335.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-bce</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;bce&#45;&gt;txt&#45;bce -->\\n\",\n       \"<g id=\\\"edge81\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-bce-&gt;txt-bce</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M491.12,-1378.51C513.01,-1369.81 539.22,-1359.39 558.47,-1351.74\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"489.86,-1375.24 481.86,-1382.19 492.45,-1381.75 489.86,-1375.24\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;be -->\\n\",\n       \"<g id=\\\"node89\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-be</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M715.75,-1413C715.75,-1413 685.75,-1413 685.75,-1413 679.75,-1413 673.75,-1407 673.75,-1401 673.75,-1401 673.75,-1389 673.75,-1389 673.75,-1383 679.75,-1377 685.75,-1377 685.75,-1377 715.75,-1377 715.75,-1377 721.75,-1377 727.75,-1383 727.75,-1389 727.75,-1389 727.75,-1401 727.75,-1401 727.75,-1407 721.75,-1413 715.75,-1413\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"700.75\\\" y=\\\"-1389.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-be</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;be&#45;&gt;txt&#45;be -->\\n\",\n       \"<g id=\\\"edge82\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-be-&gt;txt-be</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M626.07,-1395C641.94,-1395 659.9,-1395 674.11,-1395\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"626.47,-1391.5 616.47,-1395 626.47,-1398.5 626.47,-1391.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt&#45;e -->\\n\",\n       \"<g id=\\\"node92\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt-e</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M601.5,-1305C601.5,-1305 571.5,-1305 571.5,-1305 565.5,-1305 559.5,-1299 559.5,-1293 559.5,-1293 559.5,-1281 559.5,-1281 559.5,-1275 565.5,-1269 571.5,-1269 571.5,-1269 601.5,-1269 601.5,-1269 607.5,-1269 613.5,-1275 613.5,-1281 613.5,-1281 613.5,-1293 613.5,-1293 613.5,-1299 607.5,-1305 601.5,-1305\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"586.5\\\" y=\\\"-1281.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt-e</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;e&#45;&gt;txt&#45;e -->\\n\",\n       \"<g id=\\\"edge85\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-e-&gt;txt-e</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M486.02,-1326.54C509.27,-1317.29 538.87,-1305.53 559.72,-1297.25\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"484.91,-1323.21 476.91,-1330.16 487.49,-1329.72 484.91,-1323.21\\\"/>\\n\",\n       \"</g>\\n\",\n       \"<!-- txt -->\\n\",\n       \"<g id=\\\"node93\\\" class=\\\"node\\\">\\n\",\n       \"<title>txt</title>\\n\",\n       \"<path fill=\\\"#fff5f0\\\" stroke=\\\"black\\\" stroke-width=\\\"0\\\" d=\\\"M463.62,-711C463.62,-711 433.62,-711 433.62,-711 427.62,-711 421.62,-705 421.62,-699 421.62,-699 421.62,-687 421.62,-687 421.62,-681 427.62,-675 433.62,-675 433.62,-675 463.62,-675 463.62,-675 469.62,-675 475.62,-681 475.62,-687 475.62,-687 475.62,-699 475.62,-699 475.62,-705 469.62,-711 463.62,-711\\\"/>\\n\",\n       \"<text text-anchor=\\\"middle\\\" x=\\\"448.62\\\" y=\\\"-687.58\\\" font-family=\\\"Arial\\\" font-size=\\\"14.00\\\">txt</text>\\n\",\n       \"</g>\\n\",\n       \"<!-- text&#45;&gt;txt -->\\n\",\n       \"<g id=\\\"edge86\\\" class=\\\"edge\\\">\\n\",\n       \"<title>text-&gt;txt</title>\\n\",\n       \"<path fill=\\\"none\\\" stroke=\\\"black\\\" d=\\\"M349.36,-693C372.41,-693 401.41,-693 421.92,-693\\\"/>\\n\",\n       \"<polygon fill=\\\"black\\\" stroke=\\\"black\\\" points=\\\"349.44,-689.5 339.44,-693 349.44,-696.5 349.44,-689.5\\\"/>\\n\",\n       \"</g>\\n\",\n       \"</g>\\n\",\n       \"</svg>\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.SVG object>\"\n      ]\n     },\n     \"execution_count\": 188,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.SVG(\\\"../../mocodo/resources/relation_templates/_graph.svg\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Les teintes les plus foncées correspondent approximativement aux gabarits les plus complexes. Les autres ne sont souvent que des alias, par exemple, `tex.yaml` renvoie directement à `latex.yaml` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 189,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style>pre { line-height: 125%; }\\n\",\n       \"td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \".output_html .hll { background-color: #ffffcc }\\n\",\n       \".output_html { background: #f8f8f8; }\\n\",\n       \".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\\n\",\n       \".output_html .err { border: 1px solid #FF0000 } /* Error */\\n\",\n       \".output_html .k { color: #008000; font-weight: bold } /* Keyword */\\n\",\n       \".output_html .o { color: #666666 } /* Operator */\\n\",\n       \".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\\n\",\n       \".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\\n\",\n       \".output_html .cp { color: #9C6500 } /* Comment.Preproc */\\n\",\n       \".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\\n\",\n       \".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\\n\",\n       \".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\\n\",\n       \".output_html .gd { color: #A00000 } /* Generic.Deleted */\\n\",\n       \".output_html .ge { font-style: italic } /* Generic.Emph */\\n\",\n       \".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\\n\",\n       \".output_html .gr { color: #E40000 } /* Generic.Error */\\n\",\n       \".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\\n\",\n       \".output_html .gi { color: #008400 } /* Generic.Inserted */\\n\",\n       \".output_html .go { color: #717171 } /* Generic.Output */\\n\",\n       \".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\\n\",\n       \".output_html .gs { font-weight: bold } /* Generic.Strong */\\n\",\n       \".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\\n\",\n       \".output_html .gt { color: #0044DD } /* Generic.Traceback */\\n\",\n       \".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\\n\",\n       \".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\\n\",\n       \".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\\n\",\n       \".output_html .kp { color: #008000 } /* Keyword.Pseudo */\\n\",\n       \".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\\n\",\n       \".output_html .kt { color: #B00040 } /* Keyword.Type */\\n\",\n       \".output_html .m { color: #666666 } /* Literal.Number */\\n\",\n       \".output_html .s { color: #BA2121 } /* Literal.String */\\n\",\n       \".output_html .na { color: #687822 } /* Name.Attribute */\\n\",\n       \".output_html .nb { color: #008000 } /* Name.Builtin */\\n\",\n       \".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\\n\",\n       \".output_html .no { color: #880000 } /* Name.Constant */\\n\",\n       \".output_html .nd { color: #AA22FF } /* Name.Decorator */\\n\",\n       \".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\\n\",\n       \".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\\n\",\n       \".output_html .nf { color: #0000FF } /* Name.Function */\\n\",\n       \".output_html .nl { color: #767600 } /* Name.Label */\\n\",\n       \".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\\n\",\n       \".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\\n\",\n       \".output_html .nv { color: #19177C } /* Name.Variable */\\n\",\n       \".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\\n\",\n       \".output_html .w { color: #bbbbbb } /* Text.Whitespace */\\n\",\n       \".output_html .mb { color: #666666 } /* Literal.Number.Bin */\\n\",\n       \".output_html .mf { color: #666666 } /* Literal.Number.Float */\\n\",\n       \".output_html .mh { color: #666666 } /* Literal.Number.Hex */\\n\",\n       \".output_html .mi { color: #666666 } /* Literal.Number.Integer */\\n\",\n       \".output_html .mo { color: #666666 } /* Literal.Number.Oct */\\n\",\n       \".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\\n\",\n       \".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\\n\",\n       \".output_html .sc { color: #BA2121 } /* Literal.String.Char */\\n\",\n       \".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\\n\",\n       \".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\\n\",\n       \".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\\n\",\n       \".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\\n\",\n       \".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\\n\",\n       \".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\\n\",\n       \".output_html .sx { color: #008000 } /* Literal.String.Other */\\n\",\n       \".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\\n\",\n       \".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\\n\",\n       \".output_html .ss { color: #19177C } /* Literal.String.Symbol */\\n\",\n       \".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\\n\",\n       \".output_html .fm { color: #0000FF } /* Name.Function.Magic */\\n\",\n       \".output_html .vc { color: #19177C } /* Name.Variable.Class */\\n\",\n       \".output_html .vg { color: #19177C } /* Name.Variable.Global */\\n\",\n       \".output_html .vi { color: #19177C } /* Name.Variable.Instance */\\n\",\n       \".output_html .vm { color: #19177C } /* Name.Variable.Magic */\\n\",\n       \".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\\\"highlight\\\"><pre><span></span><span class=\\\"nt\\\">parent</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex&#39;</span>\\n\",\n       \"</pre></div>\\n\"\n      ],\n      \"text/latex\": [\n       \"\\\\begin{Verbatim}[commandchars=\\\\\\\\\\\\{\\\\}]\\n\",\n       \"\\\\PY{n+nt}{parent}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\end{Verbatim}\\n\"\n      ],\n      \"text/plain\": [\n       \"parent: 'latex'\"\n      ]\n     },\n     \"execution_count\": 189,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Code(\\\"../../mocodo/resources/relation_templates/tex.yaml\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La clé `\\\"parent\\\"` donne le chemin ou le nom du gabarit dont on souhaite créer une version dérivée :\\n\",\n    \"\\n\",\n    \"- une chaîne terminée par `.yaml` est interprétée comme un chemin ;\\n\",\n    \"- sinon, comme le nom d'un gabarit de la distribution.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Tous les gabarits textuels (`text.yaml`, `latex.yaml`, `markdown.yaml`, `html.yaml` et leurs alias) dérivent des gabarits `html-c.yaml` (version avec affichage des contraintes) et `html-ce.yaml` (version avec affichage des contraintes et des explications).\\n\",\n    \"\\n\",\n    \"Par exemple, le gabarit `latex` se borne à ajouter un message d'aide pour la ligne de commande et à empêcher l'ajout des contraintes d'unicité et d'optionalité :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 190,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style>pre { line-height: 125%; }\\n\",\n       \"td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \".output_html .hll { background-color: #ffffcc }\\n\",\n       \".output_html { background: #f8f8f8; }\\n\",\n       \".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\\n\",\n       \".output_html .err { border: 1px solid #FF0000 } /* Error */\\n\",\n       \".output_html .k { color: #008000; font-weight: bold } /* Keyword */\\n\",\n       \".output_html .o { color: #666666 } /* Operator */\\n\",\n       \".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\\n\",\n       \".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\\n\",\n       \".output_html .cp { color: #9C6500 } /* Comment.Preproc */\\n\",\n       \".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\\n\",\n       \".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\\n\",\n       \".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\\n\",\n       \".output_html .gd { color: #A00000 } /* Generic.Deleted */\\n\",\n       \".output_html .ge { font-style: italic } /* Generic.Emph */\\n\",\n       \".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\\n\",\n       \".output_html .gr { color: #E40000 } /* Generic.Error */\\n\",\n       \".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\\n\",\n       \".output_html .gi { color: #008400 } /* Generic.Inserted */\\n\",\n       \".output_html .go { color: #717171 } /* Generic.Output */\\n\",\n       \".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\\n\",\n       \".output_html .gs { font-weight: bold } /* Generic.Strong */\\n\",\n       \".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\\n\",\n       \".output_html .gt { color: #0044DD } /* Generic.Traceback */\\n\",\n       \".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\\n\",\n       \".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\\n\",\n       \".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\\n\",\n       \".output_html .kp { color: #008000 } /* Keyword.Pseudo */\\n\",\n       \".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\\n\",\n       \".output_html .kt { color: #B00040 } /* Keyword.Type */\\n\",\n       \".output_html .m { color: #666666 } /* Literal.Number */\\n\",\n       \".output_html .s { color: #BA2121 } /* Literal.String */\\n\",\n       \".output_html .na { color: #687822 } /* Name.Attribute */\\n\",\n       \".output_html .nb { color: #008000 } /* Name.Builtin */\\n\",\n       \".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\\n\",\n       \".output_html .no { color: #880000 } /* Name.Constant */\\n\",\n       \".output_html .nd { color: #AA22FF } /* Name.Decorator */\\n\",\n       \".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\\n\",\n       \".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\\n\",\n       \".output_html .nf { color: #0000FF } /* Name.Function */\\n\",\n       \".output_html .nl { color: #767600 } /* Name.Label */\\n\",\n       \".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\\n\",\n       \".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\\n\",\n       \".output_html .nv { color: #19177C } /* Name.Variable */\\n\",\n       \".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\\n\",\n       \".output_html .w { color: #bbbbbb } /* Text.Whitespace */\\n\",\n       \".output_html .mb { color: #666666 } /* Literal.Number.Bin */\\n\",\n       \".output_html .mf { color: #666666 } /* Literal.Number.Float */\\n\",\n       \".output_html .mh { color: #666666 } /* Literal.Number.Hex */\\n\",\n       \".output_html .mi { color: #666666 } /* Literal.Number.Integer */\\n\",\n       \".output_html .mo { color: #666666 } /* Literal.Number.Oct */\\n\",\n       \".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\\n\",\n       \".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\\n\",\n       \".output_html .sc { color: #BA2121 } /* Literal.String.Char */\\n\",\n       \".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\\n\",\n       \".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\\n\",\n       \".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\\n\",\n       \".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\\n\",\n       \".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\\n\",\n       \".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\\n\",\n       \".output_html .sx { color: #008000 } /* Literal.String.Other */\\n\",\n       \".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\\n\",\n       \".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\\n\",\n       \".output_html .ss { color: #19177C } /* Literal.String.Symbol */\\n\",\n       \".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\\n\",\n       \".output_html .fm { color: #0000FF } /* Name.Function.Magic */\\n\",\n       \".output_html .vc { color: #19177C } /* Name.Variable.Class */\\n\",\n       \".output_html .vg { color: #19177C } /* Name.Variable.Global */\\n\",\n       \".output_html .vi { color: #19177C } /* Name.Variable.Instance */\\n\",\n       \".output_html .vm { color: #19177C } /* Name.Variable.Magic */\\n\",\n       \".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\\\"highlight\\\"><pre><span></span><span class=\\\"nt\\\">help_en</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;convert</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">the</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">conceptual</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">model</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">into</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">a</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">relational</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">schema</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">in</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">LaTeX</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">format&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">help_fr</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;convertit</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">le</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">modèle</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">conceptuel</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">en</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">un</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">schéma</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">relationnel</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">au</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">format</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">LaTeX&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">help_zh</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;将概念模型转换为</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">LaTeX</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">格式的关系模式&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">fr_examples</span><span class=\\\"p\\\">:</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">example</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">explanation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;version</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">de</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">base&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">2</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">example</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex:b&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">explanation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;avec</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">_boilerplate_&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">3</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">example</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex:c&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">explanation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;avec</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">contraintes</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">d</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">unicité</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">et</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">d</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">optionalité&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">4</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">example</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex:e&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">explanation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;avec</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">explications&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">5</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">example</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex:bce&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">explanation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;avec</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">_boilerplate_,</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">contraintes</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">et</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">explications&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">parent</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex-c&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">add_unicity_constraints</span><span class=\\\"p\\\">:</span>\\n\",\n       \"<span class=\\\"nt\\\">add_optionality_constraints</span><span class=\\\"p\\\">:</span>\\n\",\n       \"</pre></div>\\n\"\n      ],\n      \"text/latex\": [\n       \"\\\\begin{Verbatim}[commandchars=\\\\\\\\\\\\{\\\\}]\\n\",\n       \"\\\\PY{n+nt}{help\\\\PYZus{}en}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{convert}\\\\PY{n+nv}{ }\\\\PY{l+s}{the}\\\\PY{n+nv}{ }\\\\PY{l+s}{conceptual}\\\\PY{n+nv}{ }\\\\PY{l+s}{model}\\\\PY{n+nv}{ }\\\\PY{l+s}{into}\\\\PY{n+nv}{ }\\\\PY{l+s}{a}\\\\PY{n+nv}{ }\\\\PY{l+s}{relational}\\\\PY{n+nv}{ }\\\\PY{l+s}{schema}\\\\PY{n+nv}{ }\\\\PY{l+s}{in}\\\\PY{n+nv}{ }\\\\PY{l+s}{LaTeX}\\\\PY{n+nv}{ }\\\\PY{l+s}{format}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{help\\\\PYZus{}fr}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{convertit}\\\\PY{n+nv}{ }\\\\PY{l+s}{le}\\\\PY{n+nv}{ }\\\\PY{l+s}{modèle}\\\\PY{n+nv}{ }\\\\PY{l+s}{conceptuel}\\\\PY{n+nv}{ }\\\\PY{l+s}{en}\\\\PY{n+nv}{ }\\\\PY{l+s}{un}\\\\PY{n+nv}{ }\\\\PY{l+s}{schéma}\\\\PY{n+nv}{ }\\\\PY{l+s}{relationnel}\\\\PY{n+nv}{ }\\\\PY{l+s}{au}\\\\PY{n+nv}{ }\\\\PY{l+s}{format}\\\\PY{n+nv}{ }\\\\PY{l+s}{LaTeX}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{help\\\\PYZus{}zh}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{将概念模型转换为}\\\\PY{n+nv}{ }\\\\PY{l+s}{LaTeX}\\\\PY{n+nv}{ }\\\\PY{l+s}{格式的关系模式}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{fr\\\\PYZus{}examples}\\\\PY{p}{:}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{example}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{explanation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{version}\\\\PY{n+nv}{ }\\\\PY{l+s}{de}\\\\PY{n+nv}{ }\\\\PY{l+s}{base}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{2}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{example}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex:b}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{explanation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{avec}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZus{}boilerplate\\\\PYZus{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{3}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{example}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex:c}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{explanation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{avec}\\\\PY{n+nv}{ }\\\\PY{l+s}{contraintes}\\\\PY{n+nv}{ }\\\\PY{l+s}{d}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{unicité}\\\\PY{n+nv}{ }\\\\PY{l+s}{et}\\\\PY{n+nv}{ }\\\\PY{l+s}{d}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{optionalité}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{4}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{example}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex:e}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{explanation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{avec}\\\\PY{n+nv}{ }\\\\PY{l+s}{explications}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{5}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{example}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex:bce}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{explanation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{avec}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZus{}boilerplate\\\\PYZus{},}\\\\PY{n+nv}{ }\\\\PY{l+s}{contraintes}\\\\PY{n+nv}{ }\\\\PY{l+s}{et}\\\\PY{n+nv}{ }\\\\PY{l+s}{explications}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{parent}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex\\\\PYZhy{}c}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{add\\\\PYZus{}unicity\\\\PYZus{}constraints}\\\\PY{p}{:}\\n\",\n       \"\\\\PY{n+nt}{add\\\\PYZus{}optionality\\\\PYZus{}constraints}\\\\PY{p}{:}\\n\",\n       \"\\\\end{Verbatim}\\n\"\n      ],\n      \"text/plain\": [\n       \"help_en: 'convert the conceptual model into a relational schema in LaTeX format'\\n\",\n       \"help_fr: 'convertit le modèle conceptuel en un schéma relationnel au format LaTeX'\\n\",\n       \"help_zh: '将概念模型转换为 LaTeX 格式的关系模式'\\n\",\n       \"fr_examples:\\n\",\n       \"  - order: 1\\n\",\n       \"    example: 'latex'\\n\",\n       \"    explanation: 'version de base'\\n\",\n       \"  - order: 2\\n\",\n       \"    example: 'latex:b'\\n\",\n       \"    explanation: 'avec _boilerplate_'\\n\",\n       \"  - order: 3\\n\",\n       \"    example: 'latex:c'\\n\",\n       \"    explanation: 'avec contraintes d''unicité et d''optionalité'\\n\",\n       \"  - order: 4\\n\",\n       \"    example: 'latex:e'\\n\",\n       \"    explanation: 'avec explications'\\n\",\n       \"  - order: 5\\n\",\n       \"    example: 'latex:bce'\\n\",\n       \"    explanation: 'avec _boilerplate_, contraintes et explications'\\n\",\n       \"parent: 'latex-c'\\n\",\n       \"add_unicity_constraints:\\n\",\n       \"add_optionality_constraints:\"\n      ]\n     },\n     \"execution_count\": 190,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Code(\\\"../../mocodo/resources/relation_templates/latex.yaml\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Si maintenant on regarde le contenu de son parent `latex-c` :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 191,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<style>pre { line-height: 125%; }\\n\",\n       \"td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \"span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n\",\n       \".output_html .hll { background-color: #ffffcc }\\n\",\n       \".output_html { background: #f8f8f8; }\\n\",\n       \".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\\n\",\n       \".output_html .err { border: 1px solid #FF0000 } /* Error */\\n\",\n       \".output_html .k { color: #008000; font-weight: bold } /* Keyword */\\n\",\n       \".output_html .o { color: #666666 } /* Operator */\\n\",\n       \".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\\n\",\n       \".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\\n\",\n       \".output_html .cp { color: #9C6500 } /* Comment.Preproc */\\n\",\n       \".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\\n\",\n       \".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\\n\",\n       \".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\\n\",\n       \".output_html .gd { color: #A00000 } /* Generic.Deleted */\\n\",\n       \".output_html .ge { font-style: italic } /* Generic.Emph */\\n\",\n       \".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\\n\",\n       \".output_html .gr { color: #E40000 } /* Generic.Error */\\n\",\n       \".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\\n\",\n       \".output_html .gi { color: #008400 } /* Generic.Inserted */\\n\",\n       \".output_html .go { color: #717171 } /* Generic.Output */\\n\",\n       \".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\\n\",\n       \".output_html .gs { font-weight: bold } /* Generic.Strong */\\n\",\n       \".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\\n\",\n       \".output_html .gt { color: #0044DD } /* Generic.Traceback */\\n\",\n       \".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\\n\",\n       \".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\\n\",\n       \".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\\n\",\n       \".output_html .kp { color: #008000 } /* Keyword.Pseudo */\\n\",\n       \".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\\n\",\n       \".output_html .kt { color: #B00040 } /* Keyword.Type */\\n\",\n       \".output_html .m { color: #666666 } /* Literal.Number */\\n\",\n       \".output_html .s { color: #BA2121 } /* Literal.String */\\n\",\n       \".output_html .na { color: #687822 } /* Name.Attribute */\\n\",\n       \".output_html .nb { color: #008000 } /* Name.Builtin */\\n\",\n       \".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\\n\",\n       \".output_html .no { color: #880000 } /* Name.Constant */\\n\",\n       \".output_html .nd { color: #AA22FF } /* Name.Decorator */\\n\",\n       \".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\\n\",\n       \".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\\n\",\n       \".output_html .nf { color: #0000FF } /* Name.Function */\\n\",\n       \".output_html .nl { color: #767600 } /* Name.Label */\\n\",\n       \".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\\n\",\n       \".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\\n\",\n       \".output_html .nv { color: #19177C } /* Name.Variable */\\n\",\n       \".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\\n\",\n       \".output_html .w { color: #bbbbbb } /* Text.Whitespace */\\n\",\n       \".output_html .mb { color: #666666 } /* Literal.Number.Bin */\\n\",\n       \".output_html .mf { color: #666666 } /* Literal.Number.Float */\\n\",\n       \".output_html .mh { color: #666666 } /* Literal.Number.Hex */\\n\",\n       \".output_html .mi { color: #666666 } /* Literal.Number.Integer */\\n\",\n       \".output_html .mo { color: #666666 } /* Literal.Number.Oct */\\n\",\n       \".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\\n\",\n       \".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\\n\",\n       \".output_html .sc { color: #BA2121 } /* Literal.String.Char */\\n\",\n       \".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\\n\",\n       \".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\\n\",\n       \".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\\n\",\n       \".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\\n\",\n       \".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\\n\",\n       \".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\\n\",\n       \".output_html .sx { color: #008000 } /* Literal.String.Other */\\n\",\n       \".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\\n\",\n       \".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\\n\",\n       \".output_html .ss { color: #19177C } /* Literal.String.Symbol */\\n\",\n       \".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\\n\",\n       \".output_html .fm { color: #0000FF } /* Name.Function.Magic */\\n\",\n       \".output_html .vc { color: #19177C } /* Name.Variable.Class */\\n\",\n       \".output_html .vg { color: #19177C } /* Name.Variable.Global */\\n\",\n       \".output_html .vi { color: #19177C } /* Name.Variable.Instance */\\n\",\n       \".output_html .vm { color: #19177C } /* Name.Variable.Magic */\\n\",\n       \".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\\\"highlight\\\"><pre><span></span><span class=\\\"nt\\\">parent</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;html-c&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">extension</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;tex&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">highlight</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;latex&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">column_separator</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;,</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">compose_relation</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;</span><span class=\\\"nv\\\">  </span><span class=\\\"s\\\">\\\\item</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">\\\\relat{{{this_relation_name}}}</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">({columns})&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">compose_relational_schema</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;%</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">Generated</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">by</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">Mocodo</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">{version}\\\\n\\\\n\\\\begin{{itemize}}\\\\n{relations}\\\\n\\\\end{{itemize}}\\\\n&#39;</span>\\n\",\n       \"<span class=\\\"nt\\\">transform_relation</span><span class=\\\"p\\\">:</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1000</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Compose</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">normal</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">attributes&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;&lt;span</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">class=</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">normal</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">&gt;(.+?)&lt;/span&gt;&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\\\\\attr{\\\\1}&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1100</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Compose</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">primary</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">keys&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;&lt;span</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">class=</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">primary</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">&gt;(.+?)&lt;/span&gt;&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\\\\\prim{\\\\1}&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1200</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Compose</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">foreign</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">primary</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">keys&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;&lt;span</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">class=</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">foreign</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">primary</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">&gt;#(.+?)&lt;/span&gt;&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\\\\\foreign{\\\\\\\\prim{\\\\1}}&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1300</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Compose</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">foreign</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">attributes&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;&lt;span</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">class=</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">foreign</span><span class=\\\"se\\\">&#39;&#39;</span><span class=\\\"s\\\">&gt;#(.+?)&lt;/span&gt;&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\\\\\foreign{\\\\1}&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1400</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Exponents&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;(&lt;sup&gt;.*u)(\\\\d)(.*&lt;/sup&gt;)&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\1_\\\\2\\\\3&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">iterated</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">true</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1500</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Exponents&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">&lt;sup&gt;(.+?)&lt;/sup&gt;&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;$^{\\\\1}$&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">  </span><span class=\\\"p p-Indicator\\\">-</span><span class=\\\"w\\\"> </span><span class=\\\"nt\\\">order</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"l l-Scalar l-Scalar-Plain\\\">1600</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">comment</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;Escape</span><span class=\\\"nv\\\"> </span><span class=\\\"s\\\">underlines&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">search</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;_&#39;</span>\\n\",\n       \"<span class=\\\"w\\\">    </span><span class=\\\"nt\\\">replace</span><span class=\\\"p\\\">:</span><span class=\\\"w\\\"> </span><span class=\\\"s\\\">&#39;\\\\_&#39;</span>\\n\",\n       \"</pre></div>\\n\"\n      ],\n      \"text/latex\": [\n       \"\\\\begin{Verbatim}[commandchars=\\\\\\\\\\\\{\\\\}]\\n\",\n       \"\\\\PY{n+nt}{parent}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{html\\\\PYZhy{}c}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{extension}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{tex}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{highlight}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{latex}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{column\\\\PYZus{}separator}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{,}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{compose\\\\PYZus{}relation}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{n+nv}{  }\\\\PY{l+s}{\\\\PYZbs{}item}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZbs{}relat\\\\PYZob{}\\\\PYZob{}\\\\PYZob{}this\\\\PYZus{}relation\\\\PYZus{}name\\\\PYZcb{}\\\\PYZcb{}\\\\PYZcb{}}\\\\PY{n+nv}{ }\\\\PY{l+s}{(\\\\PYZob{}columns\\\\PYZcb{})}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{compose\\\\PYZus{}relational\\\\PYZus{}schema}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZpc{}}\\\\PY{n+nv}{ }\\\\PY{l+s}{Generated}\\\\PY{n+nv}{ }\\\\PY{l+s}{by}\\\\PY{n+nv}{ }\\\\PY{l+s}{Mocodo}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZob{}version\\\\PYZcb{}\\\\PYZbs{}n\\\\PYZbs{}n\\\\PYZbs{}begin\\\\PYZob{}\\\\PYZob{}itemize\\\\PYZcb{}\\\\PYZcb{}\\\\PYZbs{}n\\\\PYZob{}relations\\\\PYZcb{}\\\\PYZbs{}n\\\\PYZbs{}end\\\\PYZob{}\\\\PYZob{}itemize\\\\PYZcb{}\\\\PYZcb{}\\\\PYZbs{}n}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{n+nt}{transform\\\\PYZus{}relation}\\\\PY{p}{:}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1000}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Compose}\\\\PY{n+nv}{ }\\\\PY{l+s}{normal}\\\\PY{n+nv}{ }\\\\PY{l+s}{attributes}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZlt{}span}\\\\PY{n+nv}{ }\\\\PY{l+s}{class=}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{normal}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZgt{}(.+?)\\\\PYZlt{}/span\\\\PYZgt{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}\\\\PYZbs{}attr\\\\PYZob{}\\\\PYZbs{}1\\\\PYZcb{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1100}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Compose}\\\\PY{n+nv}{ }\\\\PY{l+s}{primary}\\\\PY{n+nv}{ }\\\\PY{l+s}{keys}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZlt{}span}\\\\PY{n+nv}{ }\\\\PY{l+s}{class=}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{primary}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZgt{}(.+?)\\\\PYZlt{}/span\\\\PYZgt{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}\\\\PYZbs{}prim\\\\PYZob{}\\\\PYZbs{}1\\\\PYZcb{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1200}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Compose}\\\\PY{n+nv}{ }\\\\PY{l+s}{foreign}\\\\PY{n+nv}{ }\\\\PY{l+s}{primary}\\\\PY{n+nv}{ }\\\\PY{l+s}{keys}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZlt{}span}\\\\PY{n+nv}{ }\\\\PY{l+s}{class=}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{foreign}\\\\PY{n+nv}{ }\\\\PY{l+s}{primary}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZgt{}\\\\PYZsh{}(.+?)\\\\PYZlt{}/span\\\\PYZgt{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}\\\\PYZbs{}foreign\\\\PYZob{}\\\\PYZbs{}\\\\PYZbs{}prim\\\\PYZob{}\\\\PYZbs{}1\\\\PYZcb{}\\\\PYZcb{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1300}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Compose}\\\\PY{n+nv}{ }\\\\PY{l+s}{foreign}\\\\PY{n+nv}{ }\\\\PY{l+s}{attributes}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZlt{}span}\\\\PY{n+nv}{ }\\\\PY{l+s}{class=}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{foreign}\\\\PY{l+s+se}{\\\\PYZsq{}\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZgt{}\\\\PYZsh{}(.+?)\\\\PYZlt{}/span\\\\PYZgt{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}\\\\PYZbs{}foreign\\\\PYZob{}\\\\PYZbs{}1\\\\PYZcb{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1400}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Exponents}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{(\\\\PYZlt{}sup\\\\PYZgt{}.*u)(\\\\PYZbs{}d)(.*\\\\PYZlt{}/sup\\\\PYZgt{})}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}1\\\\PYZus{}\\\\PYZbs{}2\\\\PYZbs{}3}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{iterated}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{true}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1500}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Exponents}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{n+nv}{ }\\\\PY{l+s}{\\\\PYZlt{}sup\\\\PYZgt{}(.+?)\\\\PYZlt{}/sup\\\\PYZgt{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZdl{}\\\\PYZca{}\\\\PYZob{}\\\\PYZbs{}1\\\\PYZcb{}\\\\PYZdl{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{  }\\\\PY{p+pIndicator}{\\\\PYZhy{}}\\\\PY{+w}{ }\\\\PY{n+nt}{order}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+lScalar+lScalarPlain}{1600}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{comment}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{Escape}\\\\PY{n+nv}{ }\\\\PY{l+s}{underlines}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{search}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZus{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\PY{+w}{    }\\\\PY{n+nt}{replace}\\\\PY{p}{:}\\\\PY{+w}{ }\\\\PY{l+s}{\\\\PYZsq{}}\\\\PY{l+s}{\\\\PYZbs{}\\\\PYZus{}}\\\\PY{l+s}{\\\\PYZsq{}}\\n\",\n       \"\\\\end{Verbatim}\\n\"\n      ],\n      \"text/plain\": [\n       \"parent: 'html-c'\\n\",\n       \"extension: 'tex'\\n\",\n       \"highlight: 'latex'\\n\",\n       \"column_separator: ', '\\n\",\n       \"compose_relation: '  \\\\item \\\\relat{{{this_relation_name}}} ({columns})'\\n\",\n       \"compose_relational_schema: '% Generated by Mocodo {version}\\\\n\\\\n\\\\begin{{itemize}}\\\\n{relations}\\\\n\\\\end{{itemize}}\\\\n'\\n\",\n       \"transform_relation:\\n\",\n       \"  - order: 1000\\n\",\n       \"    comment: 'Compose normal attributes'\\n\",\n       \"    search: '<span class=''normal''>(.+?)</span>'\\n\",\n       \"    replace: '\\\\\\\\attr{\\\\1}'\\n\",\n       \"  - order: 1100\\n\",\n       \"    comment: 'Compose primary keys'\\n\",\n       \"    search: '<span class=''primary''>(.+?)</span>'\\n\",\n       \"    replace: '\\\\\\\\prim{\\\\1}'\\n\",\n       \"  - order: 1200\\n\",\n       \"    comment: 'Compose foreign primary keys'\\n\",\n       \"    search: '<span class=''foreign primary''>#(.+?)</span>'\\n\",\n       \"    replace: '\\\\\\\\foreign{\\\\\\\\prim{\\\\1}}'\\n\",\n       \"  - order: 1300\\n\",\n       \"    comment: 'Compose foreign attributes'\\n\",\n       \"    search: '<span class=''foreign''>#(.+?)</span>'\\n\",\n       \"    replace: '\\\\\\\\foreign{\\\\1}'\\n\",\n       \"  - order: 1400\\n\",\n       \"    comment: 'Exponents'\\n\",\n       \"    search: '(<sup>.*u)(\\\\d)(.*</sup>)'\\n\",\n       \"    replace: '\\\\1_\\\\2\\\\3'\\n\",\n       \"    iterated: true\\n\",\n       \"  - order: 1500\\n\",\n       \"    comment: 'Exponents'\\n\",\n       \"    search: ' <sup>(.+?)</sup>'\\n\",\n       \"    replace: '$^{\\\\1}$'\\n\",\n       \"  - order: 1600\\n\",\n       \"    comment: 'Escape underlines'\\n\",\n       \"    search: '_'\\n\",\n       \"    replace: '\\\\_'\"\n      ]\n     },\n     \"execution_count\": 191,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"display.Code(\\\"../../mocodo/resources/relation_templates/latex-c.yaml\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"... on voit que les opérations consistent simplement à modifier le séparateur de colonne, à composer les tables et le schéma relationnel complet avec un _boilerplate_, et enfin à remplacer les balises HTML par leur équivalent en  $\\\\LaTeX$. Toute la logique complexe est traitée dans le gabarit `html-c`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Exemples de création de gabarit dérivé <a id=\\\"t_relation\\\"></a>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le gabarit SQL par défaut rend explicite la contrainte `NOT NULL` des clés primaires :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 192,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE PERSONNE (\\n\",\n       \"  PRIMARY KEY (id_personne),\\n\",\n       \"  id_personne VARCHAR(8) NOT NULL,\\n\",\n       \"  nom         VARCHAR(255)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%%mocodo -t sql\\n\",\n    \"PERSONNE: id. personne [VARCHAR(8)], nom [VARCHAR(255)]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Supposons que cette redondance nous défrise, et voyons comment l'éliminer. Pour cela, examinons le contenu du gabarit `sql.yaml` :\\n\",\n    \"\\n\",\n    \"![](examples/sql_template_1.png)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"La contrainte d'optionalité `{optionality}` apparaît à côté de `PRIMARY KEY` en lignes 28 et 31. Nous pouvons donc simplement remplacer les valeurs associées à `compose_primary_key` et `compose_primary_foreign_key` par des copies supprimant cette mention :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 193,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Overwriting new_sql.yaml\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%file new_sql.yaml\\n\",\n    \"parent: 'sql'\\n\",\n    \"compose_primary_key: '{label} {datatype}\\\\nPRIMARY KEY ({label})'\\n\",\n    \"compose_primary_foreign_key: '{label} {datatype}\\\\nPRIMARY KEY ({label})\\\\nFOREIGN KEY ({label}) REFERENCES {outer_source} ({non_disambiguated_label})'\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pour tester ce nouveau gabarit, nous devons ajouter la sous-option `-t relation` avec en sous-argument le chemin complet du fichier créé :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 194,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE PERSONNE (\\n\",\n       \"  PRIMARY KEY (id_personne),\\n\",\n       \"  id_personne VARCHAR(8),\\n\",\n       \"  nom         VARCHAR(255)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t relation:new_sql.yaml\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Mission accomplie !\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Nous aurions pu procéder autrement. Reprenons le gabarit original :\\n\",\n    \"    \\n\",\n    \"![](examples/sql_template_2.png)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le dictionnaire `transform_relation` spécifie une séquence de réécritures à appliquer à chacune des clauses `CREATE TABLE` (composées ligne 37). La première accumule toutes les lignes contenant `PRIMARY KEY` en fin de table (où elles seront concaténées avant d'être ramenées au début). Nous devons donc intervenir _avant_ que `NOT NULL` ne soit séparé de `PRIMARY KEY`. Pour cela, définissons un gabarit qui se borne à **insérer** avant cette transformation (de numéro d'ordre 100) une suppression des `NOT NULL` incriminés :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 195,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Overwriting new_sql.yaml\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%%file new_sql.yaml\\n\",\n    \"parent: 'sql'\\n\",\n    \"transform_relation:\\n\",\n    \"  - order: 50\\n\",\n    \"    comment: 'Suppress PK NN redundancy.'\\n\",\n    \"    search: ' NOT NULL\\\\nPRIMARY KEY'\\n\",\n    \"    replace: '\\\\nPRIMARY KEY'\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le résultat est le même :\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 196,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"\\n\",\n       \"<div style=\\\"position: relative; height: 3ex; background-color: transparent\\\">\\n\",\n       \"<hr style=\\\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\\\">\\n\",\n       \"<span style=\\\"position: absolute; right: 0; color: #BBB\\\">\\n\",\n       \"<tt>\\n\",\n       \"sandbox_ddl.sql\\n\",\n       \"</tt>\\n\",\n       \"</span>\\n\",\n       \"</div>\\n\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/markdown\": [\n       \"```sql\\n\",\n       \"CREATE TABLE PERSONNE (\\n\",\n       \"  PRIMARY KEY (id_personne),\\n\",\n       \"  id_personne VARCHAR(8),\\n\",\n       \"  nom         VARCHAR(255)\\n\",\n       \");\\n\",\n       \"\\n\",\n       \"```\"\n      ],\n      \"text/plain\": [\n       \"<IPython.core.display.Markdown object>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"%mocodo -i sandbox -t relation:new_sql.yaml\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**NB.** Les gabarits définis par l'utilisateur n'ont **pas** vocation à être placés dans le répertoire `relation_templates` de la distribution. Votre nouveau gabarit `new_sql` ne peut donc pas être invoqué aussi simplement que les gabarits officiels (i.e., avec `-t new_sql`). Si vous faites une modification ou un ajout que vous voulez voir inclus dans la distribution, n'hésitez pas à faire une PR.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Mécanisme de mise à jour\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Le mécanisme de mise à jour des clés dépend de la scalarité de leur valeur associée.\\n\",\n    \"\\n\",\n    \"**Cas scalaire.**\\n\",\n    \"\\n\",\n    \"Pour les valeurs scalaires (chaînes, nombres, booléens, `null`), selon la présence d'une entrée donnée dans le gabarit enfant et/ou le gabarit parent, l'association clé-valeur correspondante sera créée, mise à jour ou conservée :\\n\",\n    \"\\n\",\n    \"| enfant | parent | résultat     |\\n\",\n    \"|--------|--------|--------------|\\n\",\n    \"| oui    | non    | création     |\\n\",\n    \"| oui    | oui    | mise à jour  |\\n\",\n    \"| non    | oui    | conservation |\\n\",\n    \"\\n\",\n    \"Il n'y a pas de moyen de supprimer une association clé-valeur, mais étant donné que toutes celles qui sont absentes se voient substituer une association par défaut, il est équivalent de spécifier explicitement la valeur-défaut.\\n\",\n    \"\\n\",\n    \"**Cas non scalaire.**\\n\",\n    \"\\n\",\n    \"Dans les gabarits de relations de Mocodo, une seule catégorie de valeur non scalaire est possible : la liste de dictionnaires. Dans l'exemple précédent, c'est le cas de `transform_relation`.\\n\",\n    \"\\n\",\n    \"Une clé `\\\"order\\\"` est systématiquement présente dans chacun des dictionnaires de la liste. Selon la présence d'un dictionnaire de numéro d'ordre donné dans le gabarit enfant et/ou le gabarit parent, ce dictionnaire sera inséré, supprimé, mis à jour ou conservé :\\n\",\n    \"\\n\",\n    \"| enfant | parent | résultat     |\\n\",\n    \"|--------|--------|--------------|\\n\",\n    \"| oui    | non    | insertion    |\\n\",\n    \"| oui    | oui    | si les clés sont parmi {`\\\"order\\\"`, `\\\"comment\\\"`} : suppression<br> s'il y a plusieurs clés : [mise à jour](https://docs.python.org/3/library/stdtypes.html#dict.update) |\\n\",\n    \"| non    | oui    | conservation |\\n\",\n    \"\\n\",\n    \"**Nouveauté de la version 4.0.** Si une clé d'un gabarit enfant est associée à une liste vide, cette association remplace l'éventuelle association existante.\\n\",\n    \"\\n\",\n    \"**Remarque.** Les numéros d'ordre utilisés dans les dictionnaires sont des multiples de 100. Si vous voulez créer des gabarits dérivés, évitez par précaution les multiples de 10 : cela augmentera les chances que votre gabarit survive à une mise à jour de l'un de ses ancêtres. Vous pouvez aussi partir d'une copie de ceux-ci, sachant que vous renoncez alors aux bénéfices de leurs éventuelles mises à jour.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Annexe C : Crédits\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"- **Auteur**\\n\",\n    \"  - Aristide Grange, Université de Lorraine, Metz, [LCOMS](http://lcoms.univ-lorraine.fr).\\n\",\n    \"- **Administration système**\\n\",\n    \"  - Cyril Minette.\\n\",\n    \"- **Outils**\\n\",\n    \"  - Aspect visuel\\n\",\n    \"    - [Color Brewer](http://colorbrewer2.org) (Cynthia Brewer).\\n\",\n    \"    - [Real Favicon Generator](http://realfavicongenerator.net) (Philippe Bernard).\\n\",\n    \"    - [reset.css](http://meyerweb.com/eric/tools/css/reset/) (Eric Meyer).\\n\",\n    \"  - JavaScript\\n\",\n    \"    - [JQuery](http://jquery.com/) (John Resig).\\n\",\n    \"    - [JS-Cookie](https://github.com/js-cookie/js-cookie) (Klaus Hartl).\\n\",\n    \"    - [Ace Editor](https://ace.c9.io) ([Cloud9 IDE](https://c9.io/) et [Mozilla](https://mozilla.org/)).\\n\",\n    \"  - Python\\n\",\n    \"    - [Distance de Damerau-Levenshtein](http://mwh.geek.nz/2009/04/26/python-damerau-levenshtein-distance/) (Michael Homer).\\n\",\n    \"    - [Lark Parser](https://github.com/lark-parser/lark) (Erez Shinan).\\n\",\n    \"    - [CairoSVG](https://cairosvg.org) ([CourtBouillon](https://www.courtbouillon.org)).\\n\",\n    \"    - [Pyperclip](https://github.com/asweigart/pyperclip) (Al Sweigart).\\n\",\n    \"  - Services de rendu\\n\",\n    \"    - [Kroki.io](https://kroki.io) (Guillaume Grossetie).\\n\",\n    \"    - [QR Code Generator](https://goqr.me/api/) (Foundata GmbH).\\n\",\n    \"- **Divers**\\n\",\n    \"  - [Modern SQL](https://modern-sql.com) (Markus Winand).\\n\",\n    \"  - [DBML](https://dbml.dbdiagram.io/home/) ([Holistics](https://www.holistics.io)).\\n\",\n    \"  - [D2](https://d2lang.com) ([Terrastruct](https://terrastruct.com)).\\n\",\n    \"  - [Basthon](https://basthon.fr) (Romain Casati).\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.9.13\"\n  },\n  \"toc\": {\n   \"base_numbering\": 1,\n   \"nav_menu\": {},\n   \"number_sections\": true,\n   \"sideBar\": true,\n   \"skip_h1_title\": false,\n   \"title_cell\": \"Mocodo\",\n   \"title_sidebar\": \"Mocodo\",\n   \"toc_cell\": true,\n   \"toc_position\": {\n    \"height\": \"499.575px\",\n    \"left\": \"40px\",\n    \"top\": \"132px\",\n    \"width\": \"260.568px\"\n   },\n   \"toc_section_display\": true,\n   \"toc_window_display\": true\n  },\n  \"varInspector\": {\n   \"cols\": {\n    \"lenName\": 16,\n    \"lenType\": 16,\n    \"lenVar\": 40\n   },\n   \"kernels_config\": {\n    \"python\": {\n     \"delete_cmd_postfix\": \"\",\n     \"delete_cmd_prefix\": \"del \",\n     \"library\": \"var_list.py\",\n     \"varRefreshCmd\": \"print(var_dic_list())\"\n    },\n    \"r\": {\n     \"delete_cmd_postfix\": \") \",\n     \"delete_cmd_prefix\": \"rm(\",\n     \"library\": \"var_list.r\",\n     \"varRefreshCmd\": \"cat(var_dic_list()) \"\n    }\n   },\n   \"types_to_exclude\": [\n    \"module\",\n    \"function\",\n    \"builtin_function_or_method\",\n    \"instance\",\n    \"_Feature\"\n   ],\n   \"window_display\": false\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 4\n}\n"
  },
  {
    "path": "doc/readme/ccp.mcd",
    "content": "%%mocodo --colors ocean\nCLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [INTEGER]\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "doc/tutorial.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"init_cell\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"%reload_ext mocodo\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Basic\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Tutoriel interactif (1/2)\\n\",\n    \"% Un petit zoo de la syntaxe de Mocodo, avec quelques possibilités de base :\\n\",\n    \"% entité, association, attribut, identifiant, cardinalité, patte, rôle.\\n\",\n    \"% \\n\",\n    \"% MCD adapté de : The entity-relationship model—toward a unified view of data\\n\",\n    \"% (Chen, 1976).\\n\",\n    \"\\n\",\n    \"AYANT-DROIT: num. ayant-droit, nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, 11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Entité\\n\",\n    \"% Pour créer une entité E, écrivez sur une ligne « E: ».\\n\",\n    \"% Bon à savoir : les lignes commençant par « % » sont des commentaires.\\n\",\n    \"\\n\",\n    \"Produit:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Identifiant et attributs d'entité\\n\",\n    \"% Donnez-lui des attributs en écrivant « E: attr_1, attr_2, ... ».\\n\",\n    \"% L'usage des espaces, accents et signes de ponctuation corrects est conseillé :\\n\",\n    \"% « Réf. produit » est plus lisible que « refproduit » et pourra toujours être\\n\",\n    \"% « appauvri » ultérieurement (bouton Éditer).\\n\",\n    \"%\\n\",\n    \"% Astuce : pour passer à l'exemple suivant, tapez [↓], [↓], [⏎] (ou seulement\\n\",\n    \"% [→] sous Firefox).\\n\",\n    \"\\n\",\n    \"Produit: Réf. produit, Libellé, Prix unitaire\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Identifiant composite\\n\",\n    \"% Vous avez remarqué que, par défaut, le premier attribut est considéré comme\\n\",\n    \"% un identifiant, et donc souligné. Pour souligner d'autres attributs, il faut\\n\",\n    \"% les préfixer d'un tiret bas.\\n\",\n    \"\\n\",\n    \"Gratte-ciel: latitude, _longitude, nom, hauteur, année de construction\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Association\\n\",\n    \"% Pour une association A entre plusieurs entités E1, E2, ..., écrivez sur une\\n\",\n    \"% ligne « A, XX E1, XX E2, ... ».\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, XX Commande, XX Produit\\n\",\n    \"Commande: num. commande, date, montant\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Cardinalités\\n\",\n    \"% Si vous connaissez le couple de cardinalités d'une patte, mettez 01, 11, 0N\\n\",\n    \"% ou 1N à la place du XX de l'entité distinguée par cette patte.\\n\",\n    \"%\\n\",\n    \"% NB. Cliquez sur le bouton Éditer et sélectionnez « Correction des fautes de\\n\",\n    \"% frappe dans le cardinalités » pour transformer « ON » en « 0N » ci-dessous.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, ON Produit\\n\",\n    \"Commande: num. commande, date, montant\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Attribut d'association\\n\",\n    \"% Pour ajouter des attributs à une association, faites comme pour une entité :\\n\",\n    \"% mettez un deux-points au bout de la ligne, puis listez les attributs en les\\n\",\n    \"% séparant par des virgules.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Association de dépendance fonctionnelle\\n\",\n    \"% Si votre association a une cardinalité 11, mais aucun attribut, vous pouvez\\n\",\n    \"% la nommer « DF » : Mocodo la représentera par un cercle.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Association réflexive\\n\",\n    \"% En répétant le nom d'une entité dans la définition d'une association, vous\\n\",\n    \"% rendez celle-ci réflexive.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo --mld\\n\",\n    \"% Schéma relationnel\\n\",\n    \"% Allez sous l'onglet Options, cochez « Schéma relationnel expliqué », puis\\n\",\n    \"% rafraîchissez la figure : une liste des tables apparaît au-dessous. Cliquez\\n\",\n    \"% sur n'importe quelle ligne pour mieux comprendre comment elle a été obtenue.\\n\",\n    \"%\\n\",\n    \"% Dans la table « Client », remarquez les colonnes « Réf. client » et « Réf.\\n\",\n    \"% client 2 » : ce n'est pas très satisfaisant...\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t mld\\n\",\n    \"% Rôles\\n\",\n    \"% Dans ce MCD, on a ajouté la chaîne « parrain » sur la patte 0,N de PARRAINER.\\n\",\n    \"% Cette technique permet de préserver la sémantique des associations disparues.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N [parrain] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t diagram\\n\",\n    \"% Diagramme relationnel (1)\\n\",\n    \"% Cochez « Diagramme relationnel en Mocodo », rafraîchissez la figure et allez\\n\",\n    \"% sous l'onglet Autres sorties. Vous y trouvez un texte-source que vous pouvez\\n\",\n    \"% copier-coller (⧉) ici pour voir apparaître un autre type de schéma.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N [parrain] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Diagramme relationnel (2)\\n\",\n    \"% Voici le résultat de la manipulation précédente. Les associations ont cédé la\\n\",\n    \"% place à des flèches entre les clés étrangères et les clés primaires d'origine.\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \":\\n\",\n    \"Inclure: #num. commande > Commande > num. commande, _#réf. produit > Produit > réf. produit, quantité\\n\",\n    \":\\n\",\n    \"Commande: num. commande, date, montant, #réf. client > Client > réf. client\\n\",\n    \":\\n\",\n    \"Client: réf. client, nom, prénom, adresse, #réf. client parrain > Client > réf. client, date parrainage\\n\",\n    \":\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t guess:types\\n\",\n    \"% Inférence de types\\n\",\n    \"% Cliquez sur le lapin magique, puis sélectionnez : « deviner les types à\\n\",\n    \"% partir du nom des attributs » (en français ou en anglais). Bien sûr, vous\\n\",\n    \"% pourrez toujours rectifier ceux-ci au besoin.\\n\",\n    \"% Notez que l'inférence donne de meilleurs résultats si les libellés sont écrits\\n\",\n    \"% de façon standard : Mocodo proposera un type pour « réf. produit », mais pas\\n\",\n    \"% pour « refproduit ».\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N [parrain] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t sql\\n\",\n    \"% Génération du DDL\\n\",\n    \"% Maintenant que le MCD est typé, cochez « Script SQL de création des tables »,\\n\",\n    \"% rafraîchissez et allez voir le résultat sous l'onglet Autres sorties. Notez en\\n\",\n    \"% particulier les contraintes de clés étrangères à la fin. Notez aussi que les\\n\",\n    \"% les libellés originaux ont été automatiquement « appauvris » : ainsi, « réf.\\n\",\n    \"% produit » est devenu « ref_produit », etc. Cela rend le code SQL plus portable\\n\",\n    \"% et simplifie les références lors de l'utilisation de la base.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit [VARCHAR(8)], libellé [VARCHAR(50)], prix unitaire [DECIMAL(10,2)]\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité [INTEGER]\\n\",\n    \"Commande: num. commande [VARCHAR(8)], date [DATE], montant [DECIMAL(10,2)]\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client [VARCHAR(8)], nom [VARCHAR(255)], prénom [VARCHAR(255)], adresse [VARCHAR(30)]\\n\",\n    \"Parrainer, 01 Client, 0N [parrain] Client : date parrainage [DATE]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Schéma sur plusieurs rangées\\n\",\n    \"% Pour finir la première partie du tutoriel, quelques notions de mise en page.\\n\",\n    \"% Les boîtes (entités et association) définies sur des lignes consécutives sont\\n\",\n    \"% alignées horizontalement sur la même rangée d'une grille invisible. Pour créer\\n\",\n    \"% une nouvelle rangée, il suffit de sauter une ligne entre deux clauses.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Réarrangement automatique\\n\",\n    \"% Quand le schéma devient confus, faites un double clic sur la tablette de\\n\",\n    \"% chocolat pour le réarranger aléatoirement. L'algorithme veille à éviter\\n\",\n    \"% les croisements et à minimiser la longueur des pattes. Essayez !\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Réarrangement automatique avec contraintes\\n\",\n    \"% Cliquez sur la tablette de chocolat pour faire apparaître d'autres options de\\n\",\n    \"% réorganisation. Celles-ci tentent de plonger le MCD sur la grille actuelle, ou\\n\",\n    \"% en largeur d'abord (pour un document paginé), ou en équilibrant les dimensions\\n\",\n    \"% (pour un diaporama).\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01 Client, 0N Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Entraînement au passage au relationnel\\n\",\n    \"% Cochez l'option « Masquage et génération aléatoire », cliquez le bouton qui\\n\",\n    \"% vient d'apparaître et sélectionnez « Créer un MCD d'entraînement à la\\n\",\n    \"% conversion en relationnel ». Apparaît un MCD avec des libellés aléatoires,\\n\",\n    \"% et dont la structure met en œuvre une certaine diversité de cas. Essayez de\\n\",\n    \"% le convertir en relationnel, et comparez votre solution à celle de Mocodo.\\n\",\n    \"\\n\",\n    \"LOREM: ipsum, dolor, amet\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Pour aller plus loin...\\n\",\n    \"% Si vous débutez dans les bases de données, les exemples précédents devraient\\n\",\n    \"% suffire à votre bonheur. Dans le cas contraire, cochez l'option « Tutoriel\\n\",\n    \"% interactif (2/2) » et revenez ici.\\n\",\n    \"\\n\",\n    \"À suivre...: ou pas!\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Advanced\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo --mld\\n\",\n    \"% Tutoriel interactif (2/2)\\n\",\n    \"% Une variation du MCD de Chen avec deux notions plus avancées : entité faible\\n\",\n    \"% et contrainte sur associations ; ainsi que trois nouvelles fonctionnalités :\\n\",\n    \"% flèches, calques, messages au survol.\\n\",\n    \"\\n\",\n    \"AYANT-DROIT: nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, _11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\\n\",\n    \"\\n\",\n    \"  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Entité faible (ou identification relative)\\n\",\n    \"% Préfixez d'un tiret bas une cardinalité 11 pour « affaiblir » l'entité qu'elle\\n\",\n    \"% distingue, et dont l'identifiant sera alors souligné en pointillés.\\n\",\n    \"%\\n\",\n    \"% NB. De façon non conventionnelle, Mocodo souligne le 11 pour indiquer que le\\n\",\n    \"% « renforcement » de l'identifiant va passer par là. Voyez la documentation\\n\",\n    \"% pour des options alternatives.\\n\",\n    \"\\n\",\n    \"Œuvre: cote œuvre, titre, date parution\\n\",\n    \"DF, 1N Œuvre, _11 Exemplaire\\n\",\n    \"Exemplaire: num. exemplaire, état du livre, date d'achat\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Entité faible sans identifiant\\n\",\n    \"% Préfixez d'un tiret bas le premier attribut pour l'exclure de l'identifiant,\\n\",\n    \"% p. ex. pour une entité faible sans discriminateur.\\n\",\n    \"\\n\",\n    \"Pavillon: id. pavillon, surface, nombre d'étages\\n\",\n    \"Posséder, 01 Pavillon, _11 Piscine\\n\",\n    \"Piscine: _surface, volume\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Identifiants candidats\\n\",\n    \"% Préfixez d'un « i_ » les attributs formant le ième identifiant alternatif.\\n\",\n    \"% Ce numéro apparaîtra dans une gouttière latérale, ainsi qu'un symbole ID en\\n\",\n    \"% face des attributs que vous aurez retenus pour l'identifiant. Le code SQL\\n\",\n    \"% généré inclura une contrainte d'unicité pour chacun des groupes concernés.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11 Commande\\n\",\n    \"Client: réf. client, 1_nom, 1_prénom, adresse, 2_mail\\n\",\n    \"Parrainer, 01 Client, 0N [parrain] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t mld sql\\n\",\n    \"% Héritage (ou spécialisation)\\n\",\n    \"% Pour spécialiser une entité E en une ou plusieurs autres entités E1, E2, ...\\n\",\n    \"% écrivez « /\\\\ E <- E1, E2, ... ».\\n\",\n    \"%\\n\",\n    \"% NB. Vous pouvez insérer X (exclusion) et/ou T (totalité) entre les barres\\n\",\n    \"% obliques, ajouter une liste d'attributs ou modifier la sémantique et/ou la\\n\",\n    \"% représentation graphique de l'héritage en remplaçant la flèche par <=, ->,\\n\",\n    \"% =>, <<=, <<-, ->> =>>. Voir la documentation.\\n\",\n    \"\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"\\n\",\n    \"/X\\\\ Client <- Particulier, Employé, Administratif\\n\",\n    \"\\n\",\n    \"Particulier:\\n\",\n    \"Employé: siret entreprise\\n\",\n    \"Administratif: nom ministère\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t mld:c --select mcd mld\\n\",\n    \"% Agrégation (ou pseudo-entité)\\n\",\n    \"% Préfixez de « / » une cardinalité pour entourer d'une enveloppe pointillée\\n\",\n    \"% l'association et les autres entités participantes.\\n\",\n    \"% Ici, la dépendance fonctionnelle (date, numéro) => id. client se traduit au\\n\",\n    \"% niveau relationnel par un identifiant réduit pour Réserver, ainsi qu'une\\n\",\n    \"% contrainte de non-optionalité pour id. client. Les contraintes apparaissent\\n\",\n    \"% dans les sorties SQL, mais vous pouvez aussi les visualiser au niveau du MLD\\n\",\n    \"% en cochant l'option « Contraintes d'unicité et d'optionalité ».\\n\",\n    \"%\\n\",\n    \"% NB. La représentation usuelle (non prise en charge par Mocodo) insérerait\\n\",\n    \"% une association entre Client et Réserver.\\n\",\n    \"\\n\",\n    \"Date: date\\n\",\n    \"Réserver, /1N Client, 1N Chambre, 0N Date: durée\\n\",\n    \"Chambre: numéro, prix\\n\",\n    \"\\n\",\n    \"Client: id. client\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t mld:c sql --select mcd mld\\n\",\n    \"% Agrégation et contraintes d'unicité\\n\",\n    \"% La conversion en relationnel d'un agrégat avec une cardinalité maximale 1\\n\",\n    \"% ajoute une contrainte d'unicité sur la clé étrangère.\\n\",\n    \"\\n\",\n    \"Voilier: num voilier, longueur\\n\",\n    \"Offrir, 0N Voilier, 0N Semaine, /11 Réservation: tarif\\n\",\n    \"Semaine: num semaine, 1_date début\\n\",\n    \"\\n\",\n    \"Réservation: num résa, arrhes, date résa\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Agrégation multiple\\n\",\n    \"% Mocodo gère correctement les cas difficiles à modéliser dans la notation Look\\n\",\n    \"% Here de Merise. Par exemple, deux dépendances fonctionnelles simultanées :\\n\",\n    \"% - (Projet, Employé) => Site.\\n\",\n    \"% - (Employé, Site) => Projet.\\n\",\n    \"\\n\",\n    \"Projet: projet\\n\",\n    \"Affecter, /1N Site, /1N Projet, 0N Employé\\n\",\n    \"Site: site\\n\",\n    \"\\n\",\n    \"Employé: employé\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Contrainte d'intégrité fonctionnelle (CIF)\\n\",\n    \"% Les mêmes cas de figure peuvent aussi être rendus visuellement par des CIF à\\n\",\n    \"% unicité complète (le seul type de CIF pris en charge par Mocodo).\\n\",\n    \"\\n\",\n    \"Date: date\\n\",\n    \"Réserver, /1N Client, 1N Chambre, 0N Date: durée\\n\",\n    \"Chambre: numéro, prix\\n\",\n    \"    \\n\",\n    \"Client: id. client\\n\",\n    \"    \\n\",\n    \"(CIF) ->Client, --Chambre, --Date, ..Réserver: Date, Client\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Autres contraintes sur associations\\n\",\n    \"% Ajoutez à votre MCD diverses contraintes sous forme de lettres parenthésées\\n\",\n    \"% et liées aux boîtes par des traits fléchés ou non, pleins ou pointillés, ou\\n\",\n    \"% même invisibles. Ces contraintes sont purement décoratives, et ignorées lors\\n\",\n    \"% du passage au relationnel.\\n\",\n    \"%\\n\",\n    \"% NB : par défaut, le centre de la contrainte coïncide avec le barycentre des\\n\",\n    \"% boîtes qu'elle met en jeu.\\n\",\n    \"%\\n\",\n    \"% Source du MCD : Merise, deuxième génération (Nanci et Espinasse, 2001).\\n\",\n    \"\\n\",\n    \":::\\n\",\n    \"Dépôt: num dépôt, surface\\n\",\n    \"\\n\",\n    \":\\n\",\n    \"Louer, 11 Commande, 0N Dépôt\\n\",\n    \":\\n\",\n    \"Stocker, 1N Dépôt, 1N Article: quantité\\n\",\n    \"\\n\",\n    \"Commande: num. commande, date\\n\",\n    \"Composer, 1N Commande, 0N Article\\n\",\n    \":\\n\",\n    \"Article: réf. article, prix\\n\",\n    \"\\n\",\n    \"(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande, Stocker\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Explication interactive d'une contrainte\\n\",\n    \"% Le survol d'une contrainte suivie d'un texte entre crochets affiche celui-ci\\n\",\n    \"% dans un bandeau. Essayez !\\n\",\n    \"\\n\",\n    \"Projet: num. projet, nom projet\\n\",\n    \":\\n\",\n    \"Fournir, 1N Projet, 1N Pièce, 1N Société: quantité\\n\",\n    \"Société: num. société, raison sociale\\n\",\n    \"\\n\",\n    \"Requérir, 1N Projet, 0N Pièce: quantité\\n\",\n    \":\\n\",\n    \"Pièce: réf. pièce, libellé pièce\\n\",\n    \"\\n\",\n    \"(I) [Toute pièce fournie doit avoir été requise.] ..Pièce, ->Requérir, --Fournir, Projet\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Explication interactive des cardinalités\\n\",\n    \"% Même fonctionnalité pour les cardinalités. Si l'élément survolé est en bas\\n\",\n    \"% du diagramme, le bandeau apparaît en haut, et vice versa.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N [Une commande inclut au moins un produit.] Commande, 0N [Un produit peut être commandé un nombre quelconque de fois.] Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N [Un client peut passer zéro (prospect) ou plusieurs commandes.] Client, 11 [Une commande est passée par un et un seul client.] Commande\\n\",\n    \"Client: réf. client, nom, adresse\\n\",\n    \"Parrainer, 01 [Un client peut avoir été parrainé ou non.] Client, 0N [Un client peut parrainer d'autres clients.] Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Flèche sur une patte\\n\",\n    \"% En suffixant de « < » ou « > » des cardinalités, vous créez une flèche dont\\n\",\n    \"% la direction se lit de l'association à l'entité.\\n\",\n    \"\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"Inclure, 1N Commande, 0N> Produit: quantité\\n\",\n    \"Commande: num. commande, date, montant\\n\",\n    \"DF, 0N Client, 11> Commande\\n\",\n    \"Client: réf. client, nom, prénom, adresse\\n\",\n    \"Parrainer, 01> Client, 0N< Client : date parrainage\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Dévoilement progressif du schéma\\n\",\n    \"% Indentez (i.e., insérez des espaces au début de) certaines clauses pour créer\\n\",\n    \"% des calques. Les boîtes définies avec la même indentation sont tracées sur le\\n\",\n    \"% même calque. Les calques sont ordonnés par indentation croissante. Sous Mocodo\\n\",\n    \"% online, pour faciliter la mise au point, le schéma est directement dévoilé.\\n\",\n    \"\\n\",\n    \"      Parrainer, 01 Client, 0N Client : date parrainage\\n\",\n    \"Produit: réf. produit, libellé, prix unitaire\\n\",\n    \"  Inclure, 1N Commande, 0N Produit: quantité\\n\",\n    \" \\n\",\n    \"    Client: réf. client, nom, prénom, adresse\\n\",\n    \"    DF, 0N Client, 11 Commande\\n\",\n    \"  Commande: num. commande, date, montant\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo \\n\",\n    \"% Boîtes homonymes\\n\",\n    \"% Le dernier chiffre ou tiret bas d'un nom d'entité ou d'association n'est pas\\n\",\n    \"% affiché. C'est bon à savoir, p. ex. pour monnayer une entité « fictive » trop\\n\",\n    \"% pattue : ici, on évite les croisements en créant deux entités Date.\\n\",\n    \"\\n\",\n    \"Association 9_, XX Entité 3_, XX Date1\\n\",\n    \"Date1: date\\n\",\n    \"Association 10_, XX Entité 1_, XX Date1\\n\",\n    \"Association 11_, XX Entité 1_, XX Entité 2_, XX Date2\\n\",\n    \":\\n\",\n    \"\\n\",\n    \"Entité 3_:\\n\",\n    \"Association 8_, XX Entité 3_, XX Entité 1_, XX Date1\\n\",\n    \"Entité 1_:\\n\",\n    \"Entité 2_:\\n\",\n    \"Date2: date\\n\",\n    \"\\n\",\n    \"Association 5_, XX Entité 4_, XX Entité 3_\\n\",\n    \"Entité 4_:\\n\",\n    \"Association 6_, XX Entité 4_, XX Entité 1_\\n\",\n    \"Association 7_, XX Entité 1_, XX Entité 2_, XX Date2\\n\",\n    \":\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Vue en extension\\n\",\n    \"% La même fonctionnalité permet de créer une vue en extension (à droite du MCD).\\n\",\n    \"% Notez qu'il n'y a pas besoin de suffixe pour créer plusieurs associations DF.\\n\",\n    \"% Notez également les lignes réduites à des deux-points : ceux-ci sont traités\\n\",\n    \"% comme des boîtes « fantômes », et jouent le rôle d'espaces horizontaux.\\n\",\n    \"\\n\",\n    \"ŒUVRE1: cote, titre, date de publication\\n\",\n    \":::\\n\",\n    \"ŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\\n\",\n    \":\\n\",\n    \"  \\n\",\n    \"DF, 1N ŒUVRE1, _11 EXEMPLAIRE1\\n\",\n    \"::\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE2\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE3\\n\",\n    \"DF, XX ŒUVRE2, XX EXEMPLAIRE4\\n\",\n    \"\\n\",\n    \"EXEMPLAIRE1: numéro d'exemplaire, état, date d'achat\\n\",\n    \"::\\n\",\n    \"EXEMPLAIRE2: 1, bon état, 12/6/1975\\n\",\n    \"EXEMPLAIRE3: 2, bon état, 1/8/1977\\n\",\n    \"EXEMPLAIRE4: 3, reliure rongée, 3/4/2005\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t explode arrange sql --seed=1 --select mcd sql\\n\",\n    \"% Décomposition des associations ternaires (1)\\n\",\n    \"% Cochez l'option « Décomposition d'associations » et double-cliquez le bouton\\n\",\n    \"% qui vient d'apparaître : l'association Fournir est remplacée par une entité\\n\",\n    \"% de même nom pourvue d'un identifiant générique et assortie de trois DF.\\n\",\n    \"\\n\",\n    \"AYANT-DROIT: nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, _11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo -t explode:weak arrange sql --seed=1 --select mcd sql\\n\",\n    \"% Décomposition des associations ternaires (2)\\n\",\n    \"% Cochez maintenant l'option « Entité faible » : l'entité Fournir devient une\\n\",\n    \"% entité faible sans identifiant. Vous pouvez vérifier que les schémas sont\\n\",\n    \"% conceptuellement équivalents, et produisent les mêmes sorties relationnelles\\n\",\n    \"% (MLD) et physiques (MPD).\\n\",\n    \"\\n\",\n    \"AYANT-DROIT: nom ayant-droit, lien\\n\",\n    \"DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\\n\",\n    \"REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\\n\",\n    \"PIÈCE: réf. pièce, libellé pièce\\n\",\n    \"COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\\n\",\n    \"\\n\",\n    \"DF, _11 AYANT-DROIT, 0N EMPLOYÉ\\n\",\n    \"EMPLOYÉ: matricule, nom employé\\n\",\n    \"PROJET: num. projet, nom projet\\n\",\n    \"FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\\n\",\n    \"\\n\",\n    \"DÉPARTEMENT: num. département, nom département\\n\",\n    \"EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\\n\",\n    \"TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\\n\",\n    \"SOCIÉTÉ: num. société, raison sociale\\n\",\n    \"CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%mocodo\\n\",\n    \"% Pour aller plus loin...\\n\",\n    \"% Chacune des opérations que Mocodo online présente sous la forme de bouton ou\\n\",\n    \"% de case à cocher consiste en un simple appel à la commande « mocodo » avec\\n\",\n    \"% une séquence fixe d'options. En installant Mocodo, vous pourrez composer ces\\n\",\n    \"% séquences librement, ce qui vous ouvrira d'autres perspectives : création de\\n\",\n    \"% jeux de tests, génération d'examens avec un sujet distinct par étudiant,\\n\",\n    \"% automatisation des corrections, etc. Pour l'heure, l'étape suivante semble\\n\",\n    \"% être la lecture de la documentation (lien en bas de page), qui vous donnera\\n\",\n    \"% un éventail complet des possibilités, et peut-être d'autres idées !\\n\",\n    \"\\n\",\n    \"À suivre...: ou pas!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {\n    \"init_cell\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"0. Tutoriel interactif (1/2)\\n\",\n      \"1. Entité\\n\",\n      \"2. Identifiant et attributs d'entité\\n\",\n      \"3. Identifiant composite\\n\",\n      \"4. Association\\n\",\n      \"5. Cardinalités\\n\",\n      \"6. Attribut d'association\\n\",\n      \"7. Association de dépendance fonctionnelle\\n\",\n      \"8. Association réflexive\\n\",\n      \"9. Schéma relationnel\\n\",\n      \"10. Rôles\\n\",\n      \"11. Diagramme relationnel (1)\\n\",\n      \"12. Diagramme relationnel (2)\\n\",\n      \"13. Inférence de types\\n\",\n      \"14. Génération du DDL\\n\",\n      \"15. Schéma sur plusieurs rangées\\n\",\n      \"16. Réarrangement automatique\\n\",\n      \"17. Réarrangement automatique avec contraintes\\n\",\n      \"18. Entraînement au passage au relationnel\\n\",\n      \"19. Pour aller plus loin...\\n\",\n      \"20. Tutoriel interactif (2/2)\\n\",\n      \"21. Entité faible (ou identification relative)\\n\",\n      \"22. Entité faible sans identifiant\\n\",\n      \"23. Identifiants candidats\\n\",\n      \"24. Héritage (ou spécialisation)\\n\",\n      \"25. Agrégation (ou pseudo-entité)\\n\",\n      \"26. Agrégation et contraintes d'unicité\\n\",\n      \"27. Agrégation multiple\\n\",\n      \"28. Contrainte d'intégrité fonctionnelle (CIF)\\n\",\n      \"29. Autres contraintes sur associations\\n\",\n      \"30. Explication interactive d'une contrainte\\n\",\n      \"31. Explication interactive des cardinalités\\n\",\n      \"32. Flèche sur une patte\\n\",\n      \"33. Dévoilement progressif du schéma\\n\",\n      \"34. Boîtes homonymes\\n\",\n      \"35. Vue en extension\\n\",\n      \"36. Décomposition des associations ternaires (1)\\n\",\n      \"37. Décomposition des associations ternaires (2)\\n\",\n      \"38. Pour aller plus loin...\\n\",\n      \"Updated 39 files in tutorial_lib folder.\\n\",\n      \"Updated mocodo.js.\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"from pathlib import Path\\n\",\n    \"import os\\n\",\n    \"import re\\n\",\n    \"import json\\n\",\n    \"\\n\",\n    \"def boxed_text(lines):\\n\",\n    \"    width = len(max(lines, key=len))\\n\",\n    \"    lines[0] = \\\" \\\" * max(0, (width - len(lines[0])) // 2) + lines[0].upper()\\n\",\n    \"    lines[0:0] = [\\\"\\\"]\\n\",\n    \"    lines[2:2] = [\\\"\\\"]\\n\",\n    \"    lines.append(\\\"\\\")\\n\",\n    \"    result = []\\n\",\n    \"    result.append(\\\"%\\\" * (width + 6))\\n\",\n    \"    for line in lines:\\n\",\n    \"        spaces = \\\" \\\" * (width - len(line))\\n\",\n    \"        result.append(\\\"%  \\\" + line + spaces + \\\"  %\\\")\\n\",\n    \"    result.append(\\\"%\\\" * (width + 6))\\n\",\n    \"    result.append(\\\"\\\")\\n\",\n    \"    return \\\"\\\\n\\\".join(result)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"os.system(\\\"rm tutorial_lib/*.mcd\\\")\\n\",\n    \"path = Path(\\\"tutorial.ipynb\\\")\\n\",\n    \"doc = json.loads(path.read_text())\\n\",\n    \"cells = []\\n\",\n    \"i = 0\\n\",\n    \"titles = []\\n\",\n    \"for cell in doc[\\\"cells\\\"]:\\n\",\n    \"    if cell[\\\"cell_type\\\"] == \\\"code\\\":\\n\",\n    \"        source = cell[\\\"source\\\"]\\n\",\n    \"        if source and source[0].startswith(\\\"%%mocodo\\\"):\\n\",\n    \"            title = source[1][1:].strip()\\n\",\n    \"            print(f\\\"{i}. {title}\\\")\\n\",\n    \"            titles.append(f'\\\"{title}\\\"')\\n\",\n    \"            lines = []\\n\",\n    \"            for (j, line) in enumerate(source[1:]):\\n\",\n    \"                if not line.startswith(\\\"%\\\"):\\n\",\n    \"                    text = boxed_text(lines) + \\\"\\\".join(source[j+1:])\\n\",\n    \"                    break\\n\",\n    \"                lines.append(line[2:-1])\\n\",\n    \"            Path(f\\\"tutorial_lib/tuto-{i:04d}.mcd\\\").write_text(text)\\n\",\n    \"            Path(f\\\"../web/box/tuto-{i:04d}.mcd\\\").write_text(text)\\n\",\n    \"            i += 1\\n\",\n    \"    elif cell[\\\"source\\\"] and cell[\\\"source\\\"][0].startswith(\\\"# Advanced\\\"):\\n\",\n    \"        basic_tutorial_limit = str(i)\\n\",\n    \"print(f\\\"Updated {i} files in tutorial_lib folder.\\\")\\n\",\n    \"js_path = Path(\\\"../web/mocodo.js\\\")\\n\",\n    \"code = js_path.read_text()\\n\",\n    \"(code, n) = re.subn(r'(?<=var tutorialOptions = )\\\\[.+?\\\\]', f\\\"[{', '.join(titles)}]\\\", code)\\n\",\n    \"if n == 0:\\n\",\n    \"    raise RuntimeError(\\\"Unable to update tutorialOptions!\\\")\\n\",\n    \"(code, n) = re.subn(r'(?<=var basicTutorialLimit = )\\\\d+', basic_tutorial_limit, code)\\n\",\n    \"if n == 0:\\n\",\n    \"    raise RuntimeError(\\\"Unable to update basicTutorialLimit!\\\")\\n\",\n    \"js_path.write_text(code)\\n\",\n    \"print(\\\"Updated mocodo.js.\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"anaconda-cloud\": {},\n  \"celltoolbar\": \"Initialization Cell\",\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.9.13\"\n  },\n  \"toc\": {\n   \"base_numbering\": 1,\n   \"nav_menu\": {},\n   \"number_sections\": false,\n   \"sideBar\": true,\n   \"skip_h1_title\": false,\n   \"title_cell\": \"Table of Contents\",\n   \"title_sidebar\": \"Contents\",\n   \"toc_cell\": false,\n   \"toc_position\": {},\n   \"toc_section_display\": \"block\",\n   \"toc_window_display\": true\n  },\n  \"varInspector\": {\n   \"cols\": {\n    \"lenName\": 16,\n    \"lenType\": 16,\n    \"lenVar\": 40\n   },\n   \"kernels_config\": {\n    \"python\": {\n     \"delete_cmd_postfix\": \"\",\n     \"delete_cmd_prefix\": \"del \",\n     \"library\": \"var_list.py\",\n     \"varRefreshCmd\": \"print(var_dic_list())\"\n    },\n    \"r\": {\n     \"delete_cmd_postfix\": \") \",\n     \"delete_cmd_prefix\": \"rm(\",\n     \"library\": \"var_list.r\",\n     \"varRefreshCmd\": \"cat(var_dic_list()) \"\n    }\n   },\n   \"types_to_exclude\": [\n    \"module\",\n    \"function\",\n    \"builtin_function_or_method\",\n    \"instance\",\n    \"_Feature\"\n   ],\n   \"window_display\": false\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "doc/tutorial_lib/tuto-0000.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                           TUTORIEL INTERACTIF (1/2)                           %\n%                                                                               %\n%  Un petit zoo de la syntaxe de Mocodo, avec quelques possibilités de base :   %\n%  entité, association, attribut, identifiant, cardinalité, patte, rôle.        %\n%                                                                               %\n%  MCD adapté de : The entity-relationship model—toward a unified view of data  %\n%  (Chen, 1976).                                                                %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nAYANT-DROIT: num. ayant-droit, nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, 11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ"
  },
  {
    "path": "doc/tutorial_lib/tuto-0001.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                         %\n%                                 ENTITÉ                                  %\n%                                                                         %\n%  Pour créer une entité E, écrivez sur une ligne « E: ».                 %\n%  Bon à savoir : les lignes commençant par « % » sont des commentaires.  %\n%                                                                         %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit:"
  },
  {
    "path": "doc/tutorial_lib/tuto-0002.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                        IDENTIFIANT ET ATTRIBUTS D'ENTITÉ                         %\n%                                                                                  %\n%  Donnez-lui des attributs en écrivant « E: attr_1, attr_2, ... ».                %\n%  L'usage des espaces, accents et signes de ponctuation corrects est conseillé :  %\n%  « Réf. produit » est plus lisible que « refproduit » et pourra toujours être    %\n%  « appauvri » ultérieurement (bouton Éditer).                                    %\n%                                                                                  %\n%  Astuce : pour passer à l'exemple suivant, tapez [↓], [↓], [⏎] (ou seulement     %\n%  [→] sous Firefox).                                                              %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: Réf. produit, Libellé, Prix unitaire"
  },
  {
    "path": "doc/tutorial_lib/tuto-0003.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                             IDENTIFIANT COMPOSITE                              %\n%                                                                                %\n%  Vous avez remarqué que, par défaut, le premier attribut est considéré comme   %\n%  un identifiant, et donc souligné. Pour souligner d'autres attributs, il faut  %\n%  les préfixer d'un tiret bas.                                                  %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nGratte-ciel: latitude, _longitude, nom, hauteur, année de construction"
  },
  {
    "path": "doc/tutorial_lib/tuto-0004.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                                  ASSOCIATION                                  %\n%                                                                               %\n%  Pour une association A entre plusieurs entités E1, E2, ..., écrivez sur une  %\n%  ligne « A, XX E1, XX E2, ... ».                                              %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, XX Commande, XX Produit\nCommande: num. commande, date, montant"
  },
  {
    "path": "doc/tutorial_lib/tuto-0005.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                                 CARDINALITÉS                                  %\n%                                                                               %\n%  Si vous connaissez le couple de cardinalités d'une patte, mettez 01, 11, 0N  %\n%  ou 1N à la place du XX de l'entité distinguée par cette patte.               %\n%                                                                               %\n%  NB. Cliquez sur le bouton Éditer et sélectionnez « Correction des fautes de  %\n%  frappe dans le cardinalités » pour transformer « ON » en « 0N » ci-dessous.  %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, ON Produit\nCommande: num. commande, date, montant"
  },
  {
    "path": "doc/tutorial_lib/tuto-0006.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                             ATTRIBUT D'ASSOCIATION                             %\n%                                                                                %\n%  Pour ajouter des attributs à une association, faites comme pour une entité :  %\n%  mettez un deux-points au bout de la ligne, puis listez les attributs en les   %\n%  séparant par des virgules.                                                    %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant"
  },
  {
    "path": "doc/tutorial_lib/tuto-0007.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                    ASSOCIATION DE DÉPENDANCE FONCTIONNELLE                    %\n%                                                                               %\n%  Si votre association a une cardinalité 11, mais aucun attribut, vous pouvez  %\n%  la nommer « DF » : Mocodo la représentera par un cercle.                     %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse"
  },
  {
    "path": "doc/tutorial_lib/tuto-0008.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                              %\n%                            ASSOCIATION RÉFLEXIVE                             %\n%                                                                              %\n%  En répétant le nom d'une entité dans la définition d'une association, vous  %\n%  rendez celle-ci réflexive.                                                  %\n%                                                                              %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0009.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                               SCHÉMA RELATIONNEL                               %\n%                                                                                %\n%  Allez sous l'onglet Options, cochez « Schéma relationnel expliqué », puis     %\n%  rafraîchissez la figure : une liste des tables apparaît au-dessous. Cliquez   %\n%  sur n'importe quelle ligne pour mieux comprendre comment elle a été obtenue.  %\n%                                                                                %\n%  Dans la table « Client », remarquez les colonnes « Réf. client » et « Réf.    %\n%  client 2 » : ce n'est pas très satisfaisant...                                %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0010.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                 %\n%                                      RÔLES                                      %\n%                                                                                 %\n%  Dans ce MCD, on a ajouté la chaîne « parrain » sur la patte 0,N de PARRAINER.  %\n%  Cette technique permet de préserver la sémantique des associations disparues.  %\n%                                                                                 %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N [parrain] Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0011.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                           DIAGRAMME RELATIONNEL (1)                            %\n%                                                                                %\n%  Cochez « Diagramme relationnel en Mocodo », rafraîchissez la figure et allez  %\n%  sous l'onglet Autres sorties. Vous y trouvez un texte-source que vous pouvez  %\n%  copier-coller (⧉) ici pour voir apparaître un autre type de schéma.           %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N [parrain] Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0012.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                            DIAGRAMME RELATIONNEL (2)                             %\n%                                                                                  %\n%  Voici le résultat de la manipulation précédente. Les associations ont cédé la   %\n%  place à des flèches entre les clés étrangères et les clés primaires d'origine.  %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n:\nProduit: réf. produit, libellé, prix unitaire\n:\nInclure: #num. commande > Commande > num. commande, _#réf. produit > Produit > réf. produit, quantité\n:\nCommande: num. commande, date, montant, #réf. client > Client > réf. client\n:\nClient: réf. client, nom, prénom, adresse, #réf. client parrain > Client > réf. client, date parrainage\n:"
  },
  {
    "path": "doc/tutorial_lib/tuto-0013.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                                INFÉRENCE DE TYPES                                %\n%                                                                                  %\n%  Cliquez sur le lapin magique, puis sélectionnez : « deviner les types à         %\n%  partir du nom des attributs » (en français ou en anglais). Bien sûr, vous       %\n%  pourrez toujours rectifier ceux-ci au besoin.                                   %\n%  Notez que l'inférence donne de meilleurs résultats si les libellés sont écrits  %\n%  de façon standard : Mocodo proposera un type pour « réf. produit », mais pas    %\n%  pour « refproduit ».                                                            %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N [parrain] Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0014.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                                GÉNÉRATION DU DDL                                 %\n%                                                                                  %\n%  Maintenant que le MCD est typé, cochez « Script SQL de création des tables »,   %\n%  rafraîchissez et allez voir le résultat sous l'onglet Autres sorties. Notez en  %\n%  particulier les contraintes de clés étrangères à la fin. Notez aussi que les    %\n%  les libellés originaux ont été automatiquement « appauvris » : ainsi, « réf.    %\n%  produit » est devenu « ref_produit », etc. Cela rend le code SQL plus portable  %\n%  et simplifie les références lors de l'utilisation de la base.                   %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit [VARCHAR(8)], libellé [VARCHAR(50)], prix unitaire [DECIMAL(10,2)]\nInclure, 1N Commande, 0N Produit: quantité [INTEGER]\nCommande: num. commande [VARCHAR(8)], date [DATE], montant [DECIMAL(10,2)]\nDF, 0N Client, 11 Commande\nClient: réf. client [VARCHAR(8)], nom [VARCHAR(255)], prénom [VARCHAR(255)], adresse [VARCHAR(30)]\nParrainer, 01 Client, 0N [parrain] Client : date parrainage [DATE]"
  },
  {
    "path": "doc/tutorial_lib/tuto-0015.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                           SCHÉMA SUR PLUSIEURS RANGÉES                           %\n%                                                                                  %\n%  Pour finir la première partie du tutoriel, quelques notions de mise en page.    %\n%  Les boîtes (entités et association) définies sur des lignes consécutives sont   %\n%  alignées horizontalement sur la même rangée d'une grille invisible. Pour créer  %\n%  une nouvelle rangée, il suffit de sauter une ligne entre deux clauses.          %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\n\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0016.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                            %\n%                         RÉARRANGEMENT AUTOMATIQUE                          %\n%                                                                            %\n%  Quand le schéma devient confus, faites un double clic sur la tablette de  %\n%  chocolat pour le réarranger aléatoirement. L'algorithme veille à éviter   %\n%  les croisements et à minimiser la longueur des pattes. Essayez !          %\n%                                                                            %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\n\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0017.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                    RÉARRANGEMENT AUTOMATIQUE AVEC CONTRAINTES                    %\n%                                                                                  %\n%  Cliquez sur la tablette de chocolat pour faire apparaître d'autres options de   %\n%  réorganisation. Celles-ci tentent de plonger le MCD sur la grille actuelle, ou  %\n%  en largeur d'abord (pour un document paginé), ou en équilibrant les dimensions  %\n%  (pour un diaporama).                                                            %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\n\nDF, 0N Client, 11 Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01 Client, 0N Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0018.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                    ENTRAÎNEMENT AU PASSAGE AU RELATIONNEL                     %\n%                                                                               %\n%  Cochez l'option « Masquage et génération aléatoire », cliquez le bouton qui  %\n%  vient d'apparaître et sélectionnez « Créer un MCD d'entraînement à la        %\n%  conversion en relationnel ». Apparaît un MCD avec des libellés aléatoires,   %\n%  et dont la structure met en œuvre une certaine diversité de cas. Essayez de  %\n%  le convertir en relationnel, et comparez votre solution à celle de Mocodo.   %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nLOREM: ipsum, dolor, amet"
  },
  {
    "path": "doc/tutorial_lib/tuto-0019.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                            POUR ALLER PLUS LOIN...                             %\n%                                                                                %\n%  Si vous débutez dans les bases de données, les exemples précédents devraient  %\n%  suffire à votre bonheur. Dans le cas contraire, cochez l'option « Tutoriel    %\n%  interactif (2/2) » et revenez ici.                                            %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nÀ suivre...: ou pas!"
  },
  {
    "path": "doc/tutorial_lib/tuto-0020.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                           TUTORIEL INTERACTIF (2/2)                            %\n%                                                                                %\n%  Une variation du MCD de Chen avec deux notions plus avancées : entité faible  %\n%  et contrainte sur associations ; ainsi que trois nouvelles fonctionnalités :  %\n%  flèches, calques, messages au survol.                                         %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET"
  },
  {
    "path": "doc/tutorial_lib/tuto-0021.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                    ENTITÉ FAIBLE (OU IDENTIFICATION RELATIVE)                    %\n%                                                                                  %\n%  Préfixez d'un tiret bas une cardinalité 11 pour « affaiblir » l'entité qu'elle  %\n%  distingue, et dont l'identifiant sera alors souligné en pointillés.             %\n%                                                                                  %\n%  NB. De façon non conventionnelle, Mocodo souligne le 11 pour indiquer que le    %\n%  « renforcement » de l'identifiant va passer par là. Voyez la documentation      %\n%  pour des options alternatives.                                                  %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nŒuvre: cote œuvre, titre, date parution\nDF, 1N Œuvre, _11 Exemplaire\nExemplaire: num. exemplaire, état du livre, date d'achat"
  },
  {
    "path": "doc/tutorial_lib/tuto-0022.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                         ENTITÉ FAIBLE SANS IDENTIFIANT                         %\n%                                                                                %\n%  Préfixez d'un tiret bas le premier attribut pour l'exclure de l'identifiant,  %\n%  p. ex. pour une entité faible sans discriminateur.                            %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nPavillon: id. pavillon, surface, nombre d'étages\nPosséder, 01 Pavillon, _11 Piscine\nPiscine: _surface, volume"
  },
  {
    "path": "doc/tutorial_lib/tuto-0023.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                            IDENTIFIANTS CANDIDATS                             %\n%                                                                               %\n%  Préfixez d'un « i_ » les attributs formant le ième identifiant alternatif.   %\n%  Ce numéro apparaîtra dans une gouttière latérale, ainsi qu'un symbole ID en  %\n%  face des attributs que vous aurez retenus pour l'identifiant. Le code SQL    %\n%  généré inclura une contrainte d'unicité pour chacun des groupes concernés.   %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11 Commande\nClient: réf. client, 1_nom, 1_prénom, adresse, 2_mail\nParrainer, 01 Client, 0N [parrain] Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0024.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                          HÉRITAGE (OU SPÉCIALISATION)                          %\n%                                                                                %\n%  Pour spécialiser une entité E en une ou plusieurs autres entités E1, E2, ...  %\n%  écrivez « /\\ E <- E1, E2, ... ».                                              %\n%                                                                                %\n%  NB. Vous pouvez insérer X (exclusion) et/ou T (totalité) entre les barres     %\n%  obliques, ajouter une liste d'attributs ou modifier la sémantique et/ou la    %\n%  représentation graphique de l'héritage en remplaçant la flèche par <=, ->,    %\n%  =>, <<=, <<-, ->> =>>. Voir la documentation.                                 %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nClient: réf. client, nom, prénom, adresse\n\n/X\\ Client <- Particulier, Employé, Administratif\n\nParticulier:\nEmployé: siret entreprise\nAdministratif: nom ministère"
  },
  {
    "path": "doc/tutorial_lib/tuto-0025.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                         AGRÉGATION (OU PSEUDO-ENTITÉ)                          %\n%                                                                                %\n%  Préfixez de « / » une cardinalité pour entourer d'une enveloppe pointillée    %\n%  l'association et les autres entités participantes.                            %\n%  Ici, la dépendance fonctionnelle (date, numéro) => id. client se traduit au   %\n%  niveau relationnel par un identifiant réduit pour Réserver, ainsi qu'une      %\n%  contrainte de non-optionalité pour id. client. Les contraintes apparaissent   %\n%  dans les sorties SQL, mais vous pouvez aussi les visualiser au niveau du MLD  %\n%  en cochant l'option « Contraintes d'unicité et d'optionalité ».               %\n%                                                                                %\n%  NB. La représentation usuelle (non prise en charge par Mocodo) insérerait     %\n%  une association entre Client et Réserver.                                     %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nDate: date\nRéserver, /1N Client, 1N Chambre, 0N Date: durée\nChambre: numéro, prix\n\nClient: id. client"
  },
  {
    "path": "doc/tutorial_lib/tuto-0026.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                             %\n%                     AGRÉGATION ET CONTRAINTES D'UNICITÉ                     %\n%                                                                             %\n%  La conversion en relationnel d'un agrégat avec une cardinalité maximale 1  %\n%  ajoute une contrainte d'unicité sur la clé étrangère.                      %\n%                                                                             %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nVoilier: num voilier, longueur\nOffrir, 0N Voilier, 0N Semaine, /11 Réservation: tarif\nSemaine: num semaine, 1_date début\n\nRéservation: num résa, arrhes, date résa"
  },
  {
    "path": "doc/tutorial_lib/tuto-0027.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                 %\n%                               AGRÉGATION MULTIPLE                               %\n%                                                                                 %\n%  Mocodo gère correctement les cas difficiles à modéliser dans la notation Look  %\n%  Here de Merise. Par exemple, deux dépendances fonctionnelles simultanées :     %\n%  - (Projet, Employé) => Site.                                                   %\n%  - (Employé, Site) => Projet.                                                   %\n%                                                                                 %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProjet: projet\nAffecter, /1N Site, /1N Projet, 0N Employé\nSite: site\n\nEmployé: employé"
  },
  {
    "path": "doc/tutorial_lib/tuto-0028.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                   CONTRAINTE D'INTÉGRITÉ FONCTIONNELLE (CIF)                   %\n%                                                                                %\n%  Les mêmes cas de figure peuvent aussi être rendus visuellement par des CIF à  %\n%  unicité complète (le seul type de CIF pris en charge par Mocodo).             %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nDate: date\nRéserver, /1N Client, 1N Chambre, 0N Date: durée\nChambre: numéro, prix\n    \nClient: id. client\n    \n(CIF) ->Client, --Chambre, --Date, ..Réserver: Date, Client"
  },
  {
    "path": "doc/tutorial_lib/tuto-0029.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                      AUTRES CONTRAINTES SUR ASSOCIATIONS                       %\n%                                                                                %\n%  Ajoutez à votre MCD diverses contraintes sous forme de lettres parenthésées   %\n%  et liées aux boîtes par des traits fléchés ou non, pleins ou pointillés, ou   %\n%  même invisibles. Ces contraintes sont purement décoratives, et ignorées lors  %\n%  du passage au relationnel.                                                    %\n%                                                                                %\n%  NB : par défaut, le centre de la contrainte coïncide avec le barycentre des   %\n%  boîtes qu'elle met en jeu.                                                    %\n%                                                                                %\n%  Source du MCD : Merise, deuxième génération (Nanci et Espinasse, 2001).       %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n:::\nDépôt: num dépôt, surface\n\n:\nLouer, 11 Commande, 0N Dépôt\n:\nStocker, 1N Dépôt, 1N Article: quantité\n\nCommande: num. commande, date\nComposer, 1N Commande, 0N Article\n:\nArticle: réf. article, prix\n\n(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande, Stocker"
  },
  {
    "path": "doc/tutorial_lib/tuto-0030.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                    EXPLICATION INTERACTIVE D'UNE CONTRAINTE                    %\n%                                                                                %\n%  Le survol d'une contrainte suivie d'un texte entre crochets affiche celui-ci  %\n%  dans un bandeau. Essayez !                                                    %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProjet: num. projet, nom projet\n:\nFournir, 1N Projet, 1N Pièce, 1N Société: quantité\nSociété: num. société, raison sociale\n\nRequérir, 1N Projet, 0N Pièce: quantité\n:\nPièce: réf. pièce, libellé pièce\n\n(I) [Toute pièce fournie doit avoir été requise.] ..Pièce, ->Requérir, --Fournir, Projet"
  },
  {
    "path": "doc/tutorial_lib/tuto-0031.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                              %\n%                   EXPLICATION INTERACTIVE DES CARDINALITÉS                   %\n%                                                                              %\n%  Même fonctionnalité pour les cardinalités. Si l'élément survolé est en bas  %\n%  du diagramme, le bandeau apparaît en haut, et vice versa.                   %\n%                                                                              %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N [Une commande inclut au moins un produit.] Commande, 0N [Un produit peut être commandé un nombre quelconque de fois.] Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N [Un client peut passer zéro (prospect) ou plusieurs commandes.] Client, 11 [Une commande est passée par un et un seul client.] Commande\nClient: réf. client, nom, adresse\nParrainer, 01 [Un client peut avoir été parrainé ou non.] Client, 0N [Un client peut parrainer d'autres clients.] Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0032.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                               %\n%                             FLÈCHE SUR UNE PATTE                              %\n%                                                                               %\n%  En suffixant de « < » ou « > » des cardinalités, vous créez une flèche dont  %\n%  la direction se lit de l'association à l'entité.                             %\n%                                                                               %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nProduit: réf. produit, libellé, prix unitaire\nInclure, 1N Commande, 0N> Produit: quantité\nCommande: num. commande, date, montant\nDF, 0N Client, 11> Commande\nClient: réf. client, nom, prénom, adresse\nParrainer, 01> Client, 0N< Client : date parrainage"
  },
  {
    "path": "doc/tutorial_lib/tuto-0033.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                         DÉVOILEMENT PROGRESSIF DU SCHÉMA                         %\n%                                                                                  %\n%  Indentez (i.e., insérez des espaces au début de) certaines clauses pour créer   %\n%  des calques. Les boîtes définies avec la même indentation sont tracées sur le   %\n%  même calque. Les calques sont ordonnés par indentation croissante. Sous Mocodo  %\n%  online, pour faciliter la mise au point, le schéma est directement dévoilé.     %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n      Parrainer, 01 Client, 0N Client : date parrainage\nProduit: réf. produit, libellé, prix unitaire\n  Inclure, 1N Commande, 0N Produit: quantité\n \n    Client: réf. client, nom, prénom, adresse\n    DF, 0N Client, 11 Commande\n  Commande: num. commande, date, montant"
  },
  {
    "path": "doc/tutorial_lib/tuto-0034.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                 %\n%                                BOÎTES HOMONYMES                                 %\n%                                                                                 %\n%  Le dernier chiffre ou tiret bas d'un nom d'entité ou d'association n'est pas   %\n%  affiché. C'est bon à savoir, p. ex. pour monnayer une entité « fictive » trop  %\n%  pattue : ici, on évite les croisements en créant deux entités Date.            %\n%                                                                                 %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nAssociation 9_, XX Entité 3_, XX Date1\nDate1: date\nAssociation 10_, XX Entité 1_, XX Date1\nAssociation 11_, XX Entité 1_, XX Entité 2_, XX Date2\n:\n\nEntité 3_:\nAssociation 8_, XX Entité 3_, XX Entité 1_, XX Date1\nEntité 1_:\nEntité 2_:\nDate2: date\n\nAssociation 5_, XX Entité 4_, XX Entité 3_\nEntité 4_:\nAssociation 6_, XX Entité 4_, XX Entité 1_\nAssociation 7_, XX Entité 1_, XX Entité 2_, XX Date2\n:"
  },
  {
    "path": "doc/tutorial_lib/tuto-0035.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                  %\n%                                 VUE EN EXTENSION                                 %\n%                                                                                  %\n%  La même fonctionnalité permet de créer une vue en extension (à droite du MCD).  %\n%  Notez qu'il n'y a pas besoin de suffixe pour créer plusieurs associations DF.   %\n%  Notez également les lignes réduites à des deux-points : ceux-ci sont traités    %\n%  comme des boîtes « fantômes », et jouent le rôle d'espaces horizontaux.         %\n%                                                                                  %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nŒUVRE1: cote, titre, date de publication\n:::\nŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\n:\n  \nDF, 1N ŒUVRE1, _11 EXEMPLAIRE1\n::\nDF, XX ŒUVRE2, XX EXEMPLAIRE2\nDF, XX ŒUVRE2, XX EXEMPLAIRE3\nDF, XX ŒUVRE2, XX EXEMPLAIRE4\n\nEXEMPLAIRE1: numéro d'exemplaire, état, date d'achat\n::\nEXEMPLAIRE2: 1, bon état, 12/6/1975\nEXEMPLAIRE3: 2, bon état, 1/8/1977\nEXEMPLAIRE4: 3, reliure rongée, 3/4/2005"
  },
  {
    "path": "doc/tutorial_lib/tuto-0036.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                  DÉCOMPOSITION DES ASSOCIATIONS TERNAIRES (1)                  %\n%                                                                                %\n%  Cochez l'option « Décomposition d'associations » et double-cliquez le bouton  %\n%  qui vient d'apparaître : l'association Fournir est remplacée par une entité   %\n%  de même nom pourvue d'un identifiant générique et assortie de trois DF.       %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ"
  },
  {
    "path": "doc/tutorial_lib/tuto-0037.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                  DÉCOMPOSITION DES ASSOCIATIONS TERNAIRES (2)                  %\n%                                                                                %\n%  Cochez maintenant l'option « Entité faible » : l'entité Fournir devient une   %\n%  entité faible sans identifiant. Vous pouvez vérifier que les schémas sont     %\n%  conceptuellement équivalents, et produisent les mêmes sorties relationnelles  %\n%  (MLD) et physiques (MPD).                                                     %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ"
  },
  {
    "path": "doc/tutorial_lib/tuto-0038.mcd",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%                                                                                %\n%                            POUR ALLER PLUS LOIN...                             %\n%                                                                                %\n%  Chacune des opérations que Mocodo online présente sous la forme de bouton ou  %\n%  de case à cocher consiste en un simple appel à la commande « mocodo » avec    %\n%  une séquence fixe d'options. En installant Mocodo, vous pourrez composer ces  %\n%  séquences librement, ce qui vous ouvrira d'autres perspectives : création de  %\n%  jeux de tests, génération d'examens avec un sujet distinct par étudiant,      %\n%  automatisation des corrections, etc. Pour l'heure, l'étape suivante semble    %\n%  être la lecture de la documentation (lien en bas de page), qui vous donnera   %\n%  un éventail complet des possibilités, et peut-être d'autres idées !           %\n%                                                                                %\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\nÀ suivre...: ou pas!"
  },
  {
    "path": "index.php",
    "content": "<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n\t<title>Mocodo online</title>\n\t<meta charset=\"utf-8\" />\n\t<meta name=\"apple-mobile-web-app-title\" content=\"Mocodo\" />\n\t<meta name=\"application-name\" content=\"Mocodo\" />\n\t<meta name=\"theme-color\" content=\"#fff\" />\n\t<link rel=\"stylesheet\" href=\"web/reset.css\" />\n\t<link rel=\"stylesheet\" href=\"web/style.css\" />\n\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\" />\n\t<link rel=\"icon\" type=\"image/png\" href=\"/favicon-32x32.png\" sizes=\"32x32\" />\n\t<link rel=\"icon\" type=\"image/png\" href=\"/favicon-16x16.png\" sizes=\"16x16\" />\n\t<link rel=\"manifest\" href=\"/manifest.json\" />\n\t<link rel=\"mask-icon\" href=\"/safari-pinned-tab.svg\" color=\"#0d42ff\" />\n\t<script src=\"web/jquery-1.7.2.min.js\"></script>\n\t<script src=\"web/js.cookie.js\"></script>\n\t<script src=\"web/mocodo.js\"></script>\n\t<script src=\"web/flashlight.js\"></script>\n\t<script src=\"web/ace-builds/ace.js\"></script>\n\t<script src=\"web/ace-builds/ext-language_tools.js\"></script>\n\t<script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n</head>\n<?php\nif (strpos($_SERVER['HTTP_REFERER'], 'localhost')) {\n    $mocodo = \"~/opt/anaconda3/bin/mocodo\";\n    $web_url = \"http://localhost:8898/mocodo/web/\";\n  } else {\n    $mocodo = \"~/.local/bin/mocodo\";\n    $web_url = \"https://www.mocodo.net/web/\";\n  }\n$version = shell_exec(\"$mocodo --version\");\n$version = !empty($version) ? trim($version) : '';\n\n$lib = $_GET['lib'];\nif ($lib) {\n\techo \"<script>$(document).ready(function() { $('#lib').val('{$lib}'); });</script>\";\n}\n?>\n<body>\n\t<div id=\"wrap\">\n\t\t<div id=\"banner\">\n\t\t\t<img\n\t\t\t\tsrc=\"web/mocodonline.svg\"\n\t\t\t\talt=\"Mocodo online\"\n\t\t\t\tstyle=\"width: 589px; height: auto;\"\n\t\t\t/>\n\t\t</div>\n\t\t<div id=\"motto\">\n\t\t\t<span>Modélisation Conceptuelle de Données. Nickel. Ni souris.</span>\n\t\t</div>\n\t\t<form method=\"post\" id=\"mainForm\" action=\"web/download.php\" autocomplete=\"off\">\n\t\t\t<input type=\"hidden\" name=\"state\" id=\"state\" value=\"dirty\" />\n\t\t\t<div id=\"inputZone\">\n\t\t\t\t<div class=\"line\"></div>\n\t\t\t\t<ul class=\"tabs\">\n\t\t\t\t\t<li><a href=\"#aboutContents\" class=\"first_tab\"><span class=\"info-symbol\" style=\"background-image: url(web/png/info.png);\"></span></a></li>\n\t\t\t\t\t<li><a href=\"#inputContents\" class=\"active\"><span>Entrée</span></a></li>\n\t\t\t\t\t<li><a href=\"#paramContents\"><span>Options</span></a></li>\n\t\t\t\t\t<li><a href=\"#geoContents\" id=\"geoTab\"><span>Retouches</span></a></li>\n\t\t\t\t</ul>\n\t\t\t\t<div class=\"pane\">\n\t\t\t\t\t<div id=\"inputButtons\" class=\"buttons\">\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"arrangeButton\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'arrange')\" style=\"background-image: url(web/png/arrange.png);\"><span class=\"tooltiptext\">Réarranger</span></span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('arrange:current')\">sur la grille actuelle</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('arrange:wide')\">en privilégiant la largeur</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('arrange:balanced=0')\">sur la plus petite grille équilibrée</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('arrange:balanced=1')\">sur la seconde plus petite grille équilibrée</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('arrange')\">sans contraintes (double clic)</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"flipButton\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'flip:hvd')\" style=\"background-image: url(web/png/flip.png);\"><span class=\"tooltiptext\">Inverser</span></span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('flip:h')\">horizontalement</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('flip:v')\">verticalement</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('flip:d')\">selon la première diagonale</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('flip:hvd')\">selon la deuxième diagonale (double clic)</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"typoButton\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'ascii:labels snake:labels lower:attrs,roles upper:boxes')\" style=\"background-image: url(web/png/typo.png);\">\n\t\t\t\t\t\t\t\t<span class=\"tooltiptext\">Éditer</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('camel:labels')\">libellés en <i>camelCase</i></span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('pascal:labels')\">libellés en <i>PascalCase</i></span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('snake:labels')\">libellés en <i>snake_case</i></span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('ascii:labels')\">libellés en ASCII</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('lower:attrs,roles')\">attributs en minuscules</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('upper:boxes')\">noms des entités et des associations en majuscules</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('snake:labels ascii:labels lower:attrs,roles upper:boxes')\">les quatre précédents à la fois (double clic)</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('fix:cards')\">correction des fautes de frappe dans les cardinalités</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"createButton\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'create:entities')\" style=\"background-image: url(web/png/create.png);\"><span class=\"tooltiptext\">Révéler</span></span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:dfs')\">mettre des DF partout où c'est possible</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:df_arrows')\">ajouter des flèches aux DF 11</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:cifs')\" id=\"createCifs\" style=\"display: none;\">ajouter les CIF correspondant aux agrégats</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:types=')\">mettre en évidence les types à remplir</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:types')\">deviner les types à partir du nom des attributs</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('delete:types')\">supprimer les types</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:entities')\">réparer l'oubli d'entités référencées dans des associations (double clic)</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"jokerButton\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'obfuscate')\" style=\"background-image: url(web/png/joker.png);\"><span class=\"tooltiptext\">Masquer</span></span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('drown')\">masquer avec des libellés génériques numérotés</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('delete')\" title=\"Crée un MCD à compléter. À accompagner de la liste des descriptifs des attributs obtenue avec l'option « Dictionnaire des données en Markdown (deux colonnes) ».\">masquer les attributs et les cardinalités</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('create:types=PLACEHOLDER randomize:types')\">remplir les types au hasard</span> <!-- Create the types as an arbitrary NONEMPTY string, then randomize them. -->\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange')\">créer un MCD d'entraînement à la conversion en relationnel</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('grow:from_scratch,arity_3=1 arrange')\">créer un MCD aléatoire avec des libellés génériques numérotés</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('obfuscate')\">masquer avec du faux texte (double clic)</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"button-with-popup\" id=\"explodeButton\" style=\"display: none;\">\n\t\t\t\t\t\t\t<span class=\"customButton tooltip explosion-call\" onmouseenter=\"closePopup()\" onclick=\"handleClick(this, 'explode:arity=3 arrange')\" style=\"background-image: url(web/png/explode.png);\">\n\t\t\t\t\t\t\t\t<span class=\"tooltiptext\">Décomposer</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<div class=\"popup-menu\" onmouseleave=\"closePopup(this)\">\n\t\t\t\t\t\t\t\t<span class=\"popup-item popup-close\" onclick=\"closePopup()\">⨉</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('drain')\">drainer les DF porteuses d'attributs</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item\" onclick=\"rewrite('split arrange')\">décomposer les DF ternaires et plus</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item explosion-call\" onclick=\"rewrite('explode:arity=3 arrange')\">décomposer les non-DF ternaires et plus (double clic)</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item explosion-call\" onclick=\"rewrite('explode:arity=2.5 arrange')\">décomposer les non-DF binaires et plus porteuses d'attributs</span>\n\t\t\t\t\t\t\t\t<span class=\"popup-item explosion-call\" onclick=\"rewrite('explode:arity=2 arrange')\">décomposer toutes les non-DF binaires et plus</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"aboutContents\" class=\"contents\">\n\t\t\t\t\t\t<p style=\"height: 2em;\"><a class=\"github-button\" href=\"https://github.com/laowantong/mocodo\" data-icon=\"octicon-star\" data-show-count=\"true\" aria-label=\"Star laowantong/mocodo on GitHub\">Star</a></p>\n\t\t\t\t\t\t<p>Mocodo est un logiciel d'aide à l'enseignement et à l'apprentissage des <a href=\"https://fr.wikipedia.org/wiki/Base_de_données_relationnelle\">bases de données relationnelles</a>.</p>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t<li>En entrée, il prend un <a href=\"https://fr.wikipedia.org/wiki/Modèle_entité-association\">MCD</a> (modèle conceptuel de données) décrit dans un langage dédié minimaliste.</li>\n\t\t\t\t\t\t\t<li>En sortie, il produit un diagramme entité-association et, à la demande, un <a href=\"https://fr.wikipedia.org/wiki/Merise_(informatique)#MLD_:_modèle_logique_des_données\">MLD</a> (schéma relationnel, sous forme graphique ou textuelle), un <a href=\"https://fr.wikipedia.org/wiki/Langage_de_définition_de_données\">DDL</a> (script SQL de création de la base), un <a href=\"https://fr.wikipedia.org/wiki/Diagramme_de_classes\">diagramme de classes UML</a>, etc.</li>\n\t\t\t\t\t\t\t<li>En bonus, il est capable de réarranger automatiquement votre MCD de façon esthétique, et de lui appliquer des opérations de réécriture qui vont du mondain (typographie) à l'académique (décomposition d'associations), en passant par le merveilleux (inférence de types, génération d'exercices et d'exemples).</li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t<p>Ce site est prévu pour une utilisation basique et occasionnelle, typiquement en salle de classe. Si vous travaillez sur des données confidentielles¹, ou souhaitez avoir accès à toutes les fonctionnalités de Mocodo, vous pouvez, soit l'importer sous <a href=\"https://www.basthon.fr\">Basthon</a>, soit l'installer sur votre ordinateur :</p>\n\t\t\t\t\t\t<br />\n\t\t\t\t\t\t<pre>&gt; pip install mocodo</pre>\n\t\t\t\t\t\t<br />\n\t\t\t\t\t\t<p>Sous cette dernière forme, Mocodo est un puissant <a href=\"https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande\">logiciel en ligne de commande</a>, multiplateforme, <a href=\"https://github.com/laowantong/mocodo\"><i>open-source</i></a>, <a href=\"https://fr.wikipedia.org/wiki/Licence_MIT\">libre</a> et gratuit. Il s'intègre particulièrement bien à l'environnement <a href=\"https://jupyter.org\">Jupyter Notebook</a>.</p>\n\t\t\t\t\t\t<br />\n\t\t\t\t\t\t<p>Pour en savoir plus, suivez nos tutoriels interactifs (onglet Entrée), puis plongez-vous dans la <a target=\"_blank\" href=\"https://laowantong.github.io/mocodo/doc/fr_refman.html\">documentation</a>.</p>\n\t\t\t\t\t\t<br />\n\t\t\t\t\t\t<p style=\"font-size: small; font-style: italic; text-align: right;\">Aristide Grange, Université de Lorraine, Metz (France)</p>\n\t\t\t\t\t\t<div class=\"footnote\">\n\t\t\t\t\t\t\t<hr>\n\t\t\t\t\t\t\t<p>¹ Ce site stocke dans votre navigateur un <a href=\"https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies/que-dit-la-loi\">cookie non soumis à obligation de consentement préalable</a> qui lui permet de retrouver vos réglages de l'onglet Options. Côté serveur, il stocke le dernier état de votre travail afin de le mettre à votre disposition sous forme d'archive téléchargeable. Ce dossier est détruit au bout de 24 heures. Pour le détruire dès la fin d'une session, effacez le texte d'entrée et pressez le bouton de rafraîchissement. Sous Basthon ou en local, rien ne quitte votre ordinateur.</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"inputContents\" class=\"contents\">\n\t\t\t\t\t\t<div id=\"inputPane\">\n\t\t\t\t\t\t\t<div><input type=\"text\" oninput=\"markAsDirty();get_from_lib()\" onfocus=\"onFocus(this)\" name=\"title\" id=\"title\" value=\"MCD\" onblur=\"onBlur(this)\" autocomplete=\"off\" /></div>\n\t\t\t\t\t\t\t<select onchange=\"changeTitleToNthTuto();get_from_lib()\" name=\"tutorial\" id=\"tutorial\" title=\"Parcourez notre galerie de MCD pour apprendre la syntaxe de Mocodo.\"></select>\n\t\t\t\t\t\t\t<textarea hidden name=\"text\"><?php\n\t\t\t\t\t\t\t\t$encoded_string = (isset($_GET['mcd'])) ? $_GET['mcd'] : '';\n\t\t\t\t\t\t\t\techo (zlib_decode(base64_decode(strtr($encoded_string, '-_', '+/'))));\n\t\t\t\t\t\t\t?></textarea>\n\t\t\t\t\t\t\t<div id=\"editor-wrapper\">\n\t\t\t\t\t\t\t\t<div id=\"editor\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"paramContents\" class=\"contents\">\n\t\t\t\t\t\t<div class=\"settings-pane\">\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"shapes\">Police et proportions</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<select onchange=\"markAsDirty();writeCookie()\" name=\"shapes\" id=\"shapes\">\n\t\t\t\t\t\t\t\t\t\t<!-- To be populated by JS -->\n\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"colors\">Palette de couleurs</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<select onchange=\"markAsDirty();writeCookie()\" name=\"colors\" id=\"colors\">\n\t\t\t\t\t\t\t\t\t\t<!-- To be populated by JS -->\n\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"flashlight\">Mode nuit</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" id=\"flashlight\" onclick=\"switchOnFlashlight(event)\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"adjust_width\">Ajustement de la largeur des libellés</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<input type=\"number\" value=\"1.00\" max=\"2.00\" min=\"0.50\" step=\"0.01\" onchange=\"writeCookie()\" name=\"adjust_width\" id=\"adjust_width\" style=\"width: 5em; border-radius: 0;\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"detect_overlaps\" title=\"Lève une erreur en cas de chevauchement de pattes horizontales ou verticales.\">Détection des chevauchements</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"detect_overlaps\" id=\"detect_overlaps\" onchange=\"markAsDirty();writeCookie()\" checked />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" title=\"Les formats cochés seront générés et inclus dans l'archive téléchargée.\">Format des images en sortie</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" disabled=\"true\" id=\"svg\" checked />\n\t\t\t\t\t\t\t\t\t\t<label for=\"svg\" title=\"Pour le web, zoom illimité. Requis.\">&nbsp;SVG&nbsp;&nbsp;</label>\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"png\" id=\"png\" onchange=\"markAsDirty();writeCookie()\" />\n\t\t\t\t\t\t\t\t\t\t<label for=\"png\" title=\"Multi-usage, zoom limité.\">&nbsp;PNG&nbsp;&nbsp;</label>\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"pdf\" id=\"pdf\" onchange=\"markAsDirty();writeCookie()\" />\n\t\t\t\t\t\t\t\t\t\t<label for=\"pdf\" title=\"Pour l'impression, zoom illimité.\">&nbsp;PDF&nbsp;&nbsp;</label>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"conversions\" title=\"Les formats cochés seront affichés sous l'onglet « Autres sorties » et inclus dans l'archive téléchargée.\">Conversions en sortie</label>\n\t\t\t\t\t\t\t\t<ul class=\"setting-controls\" name=\"conversions\" id=\"conversions\">\n\t\t\t\t\t\t\t\t\t<!-- To be populated by JS -->\n\t\t\t\t\t\t\t\t\t<details class=\"setting-details\">\n\t\t\t\t\t\t\t\t\t\t<summary>Autres options de conversions…</summary>\n\t\t\t\t\t\t\t\t\t\t<!-- To be populated by JS -->\n\t\t\t\t\t\t\t\t\t</details>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"knowledge\" title=\"Vous pouvez adapter les traitements et l'interface de Mocodo online à des besoins plus avancés.\">Utilisation avancée</label>\n\t\t\t\t\t\t\t\t<details class=\"setting-details\">\n\t\t\t\t\t\t\t\t\t<summary>Découvrir…</summary>\n\t\t\t\t\t\t\t\t\t<ul class=\"setting-controls\" name=\"knowledge\" id=\"knowledge\">\n\t\t\t\t\t\t\t\t\t\t<!-- To be populated by JS -->\n\t\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t\t</details>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"setting-row\">\n\t\t\t\t\t\t\t\t<label class=\"setting-label\" for=\"lib\" title=\"URL d'un répertoire distant. Si l'utilisateur modifie le titre du MCD, Mocodo y cherchera un fichier de même nom (extension '.mcd' facultative) et, s'il existe, remplacera le texte d'entrée par son contenu.\">Bibliothèque de MCD</label>\n\t\t\t\t\t\t\t\t<div class=\"setting-controls\">\n\t\t\t\t\t\t\t\t\t<input type=\"url\" name=\"lib\" id=\"lib\" onchange=\"markAsDirty();writeCookie()\" placeholder=\"https://your_server.com/path/to/your/mcd/directory\"\n\t\t\t\t\t\t\t\t\tpattern=\"[Hh][Tt][Tt][Pp][Ss]?:\\/\\/(?:(?:[a-zA-Z\\u00a1-\\uffff0-9]+-?)*[a-zA-Z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-zA-Z\\u00a1-\\uffff0-9]+-?)*[a-zA-Z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-zA-Z\\u00a1-\\uffff]{2,}))(?::\\d{2,5})?(?:\\/[^\\s]*)?\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style=\"display: none;\">\n\t\t\t\t\t\t\t\t<select onchange=\"markAsDirty();writeCookie()\" name=\"sql_case\" id=\"sql_case\">\n\t\t\t\t\t\t\t\t\t<option selected=\"selected\">snake_case</option>\n\t\t\t\t\t\t\t\t\t<option>camelCase</option>\n\t\t\t\t\t\t\t\t\t<option>PascalCase</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t<select onchange=\"markAsDirty();writeCookie()\" name=\"fk_format\" id=\"fk_format\">\n\t\t\t\t\t\t\t\t\t<option value=\"#{label}\" selected=\"selected\">avec # au début</option>\n\t\t\t\t\t\t\t\t\t<option value=\"{label}#\">avec # à la fin</option>\n\t\t\t\t\t\t\t\t\t<option value=\"{label}\">telles quelles</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t<select onchange=\"markAsDirty();writeCookie()\" name=\"strengthen_card\" id=\"strengthen_card\">\n\t\t\t\t\t\t\t\t\t<option>1,1</option>\n\t\t\t\t\t\t\t\t\t<option value=\"_1,1_\" selected=\"selected\">1̲,1̲</option>\n\t\t\t\t\t\t\t\t\t<option>(1,1)</option>\n\t\t\t\t\t\t\t\t\t<option>1,1(R)</option>\n\t\t\t\t\t\t\t\t\t<option>1,1🄡</option>\n\t\t\t\t\t\t\t\t\t<option>1,1®</option>\n\t\t\t\t\t\t\t\t\t<option>(R)1,1</option>\n\t\t\t\t\t\t\t\t\t<option>🄡1,1</option>\n\t\t\t\t\t\t\t\t\t<option>®1,1</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"geoContents\" class=\"contents\">\n\t\t\t\t\t\t<fieldset>\n\t\t\t\t\t\t\t<legend>Coordonnées du centre des boîtes</legend>\n\t\t\t\t\t\t\t<div id=\"coords\"></div>\n\t\t\t\t\t\t</fieldset>\n\t\t\t\t\t\t<fieldset>\n\t\t\t\t\t\t\t<legend>Décalage des cardinalités</legend>\n\t\t\t\t\t\t\t<div id=\"cards\"></div>\n\t\t\t\t\t\t</fieldset>\n\t\t\t\t\t\t<fieldset>\n\t\t\t\t\t\t\t<legend>Zone de rognage</legend>\n\t\t\t\t\t\t\t<div id=\"size\"></div>\n\t\t\t\t\t\t</fieldset>\n\t\t\t\t\t\t<fieldset>\n\t\t\t\t\t\t\t<legend>Position des flèches des associations</legend>\n\t\t\t\t\t\t\t<div id=\"arrows\"></div>\n\t\t\t\t\t\t</fieldset>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div id=\"outputZone\">\n\t\t\t\t<div class=\"line\"></div>\n\t\t\t\t<ul class=\"tabs\">\n\t\t\t\t\t<li><a href=\"#diagramAndSupplementOutput\" id=\"diagramTab\" class=\"first_tab active\"><span>Diagramme</span></a></li>\n\t\t\t\t\t<li><a href=\"#convertOutput\"><span>Autres sorties</span></a></li>\n\t\t\t\t\t<li><a href=\"#errorOutput\" id=\"errorTab\"><span>Erreurs</span></a></li>\n\t\t\t\t</ul>\n\t\t\t\t<div class=\"pane\">\n\t\t\t\t\t<div id=\"outputButtons\" class=\"buttons\">\n\t\t\t\t\t\t<span class=\"customButton tooltip\" id=\"refreshButton\" onclick=\"generate()\" style=\"background-image: url(web/png/refresh.png);\"><span class=\"tooltiptext\">Rafraîchir</span></span>\n\t\t\t\t\t\t<div id=\"rotatingButton\" style=\"display: none;\">\n\t\t\t\t\t\t\t<span class=\"customButton\" id=\"empty\" style=\"background-image: url(web/png/empty.png);\"></span>\n\t\t\t\t\t\t\t<span class=\"customButton\" id=\"refreshRotatingButton\" style=\"background-image: url(web/png/refresh_rotating.png);\"></span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<a class=\"customButton tooltip\" id=\"downloadButton\" href=\"\" download=\"\" target=\"_blank\" style=\"background-image: url(web/png/download.png);\"><span class=\"tooltiptext\">Télécharger</span></a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"diagramAndSupplementOutput\">\n\t\t\t\t\t\t<div id=\"diagramOutput\" class=\"contents active never_refreshed\"><img src=\"web/generate_tip.svg\" alt=\"Cliquez sur le bouton de génération pour rafraîchir le MCD\" /></div>\n\t\t\t\t\t\t<div id=\"diagramOutputSupplement\" class=\"contents\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div id=\"convertOutput\" class=\"contents never_refreshed\"><img src=\"web/generate_tip.svg\" alt=\"Cliquez sur le bouton de génération pour rafraîchir le MCD\" /></div>\n\t\t\t\t\t<div id=\"errorOutput\" class=\"contents\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n\t<div id=\"navigation\">\n\t\t<a title=\"Voir le code sur GitHub.\" target=\"_blank\" href=\"https://github.com/laowantong/mocodo\">Mocodo <?php echo $version; ?></a>\n\t\t&nbsp;∙&nbsp;\n\t\t<a href=\"javascript:void(0);\" \n\t\t\tonclick=\"sendToBasthon()\" \n\t\t\ttitle=\"Ouvrir ce MCD dans un notebook pour accéder à toutes les fonctionnalités du logiciel sans avoir à l'installer.\"\n\t\t\tstyle=\"cursor: pointer; display: inline-block;\">\n\t\t\t<img class=\"inlineIcon\" src=\"web/png/basthon_play.png\" alt=\"Basthon\" />\n\t\t\t&nbsp;&nbsp;Basthon\n\t\t</a>\n\t\t&nbsp;∙&nbsp;\n\t\t<a target=\"_blank\" href=\"https://laowantong.github.io/mocodo/doc/fr_refman.html\">Documentation</a>\n\t\t&nbsp;∙&nbsp;\n\t\t<a title=\"Contacter l'auteur par mail.\" onclick=\"alert('Pour envoyer vos compliments à l\\'auteur, trouvez d\\'abord son nom sous l\\'onglet d\\'information, puis adressez un mail à prénom.nom@univ-lorraine.fr. Attention, tout problème ou demande concernant le logiciel doit préférablement faire l\\'objet d\\'une issue GitHub (« Récriminations »).')\">Félicitations</a>\n\t\t&nbsp;∙&nbsp;\n\t\t<a title=\"Créer une issue GitHub.\" target=\"_blank\" href=\"https://github.com/laowantong/mocodo/issues\">Récriminations</a>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "laowantong.vscode-mocodo/.vscode/launch.json",
    "content": "// A launch configuration that launches the extension inside a new window\n// Use IntelliSense to learn about possible attributes.\n// Hover to view descriptions of existing attributes.\n// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n{\n\t\"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Extension\",\n            \"type\": \"extensionHost\",\n            \"request\": \"launch\",\n            \"args\": [\n                \"--extensionDevelopmentPath=${workspaceFolder}\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "laowantong.vscode-mocodo/.vscodeignore",
    "content": ".vscode/**\n.vscode-test/**\n.gitignore\nvsc-extension-quickstart.md\n*.vsix\n"
  },
  {
    "path": "laowantong.vscode-mocodo/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017- Aristide Grange\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "laowantong.vscode-mocodo/README.md",
    "content": "# Mocodo Syntax\n\nSyntax highlighting support for Mocodo.\n\n![Mocodo text source](doc/syntax_screenshot.png)\n\nMocodo is a tool for designing and teaching relational databases. It is based on the French-flavored Entity-Relationship model (aka Merise).\n\n![Mocodo text source](doc/readme_1.png)\n\n## Contributing\nBug reports and pull requests are welcome on GitHub at https://github.com/laowantong/mocodo/.\n\n## License\nMIT.\n\n## Release Notes\n\n### 1.0.5 -> 1.0.6\n\nUpdate for Mocodo 4.0.5.\n\n### 1.0.2\n\nAdd support for Mocodo 4.0's invisible boxes.\n\n### 1.0.1\n\nDon't regard a mix of empty and non-empty entity attributes as an error.\n\n### 1.0.0\n\nImprove color consistency between [Mocodo online](https://mocodo.net) and VS-Code's \"Light+\" or \"Light Modern\" themes.\n\n### 0.0.2 -> 0.0.5\n\nFix packaging problems.\n\n### 0.0.1\n\nInitial release.\n\n## For more information\n\n* [Mocodo online](https://mocodo.net)\n* [Github](https://github.com/laowantong/mocodo/)\n* [Documentation](https://laowantong.github.io/mocodo/doc/fr_refman.html)\n"
  },
  {
    "path": "laowantong.vscode-mocodo/highlighting_zoo.mcd",
    "content": "%%mocodo\n:\n:::\n:  :  :\n   :  :  :\n   % commented\n% commented %\n  % foo\\\\ , %  foo  /TX\\\\\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\nCONTRÔLER, 0N< [filiale] SOCIÉTÉ, 01 [mère] SOCIÉTÉ\nDF, 0N> CLIENT, 11 COMMANDE\nGRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction\nPeut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin\nEngendre, 0N< Personne, 22> Personne\nAgent 0070: bar\nDF4, 11 Agent 0070, 1N Agent1\nAgent1: bar\nDF, _11 ŒUVRE, _11 EXEMPLAIRE\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\nLIGULA, 0N LACUS, /1N EROS, 0N TELLUS, 0N CONSEQUAT: metus\nRéserver: _Durée\n+LIGULA, 01 LACUS, 1N EROS: metus\nPASSER, 0N [Un client peut passer un nombre quelconque de commandes.] CLIENT, 11 [Toute commande est passée par un en un seul client.] COMMANDE\nINCLURE, 1N [Une commande peut inclure plusieurs produits distincts, et en inclut au moins un.] COMMANDE, 0N [Certains produits ne sont jamais commandés, d'autres le sont plusieurs fois.] PRODUIT: Quantité\nCLIENT: \nCLIENT: ,          ,,\nCOMMANDE: ,               ,\nPRODUIT: ,            , \nUnit, 1N Draw, 11 Folk: Peer, Tour, \nPASSER, XX CLIENT, XX COMMANDE\nINCLURE, XX COMMANDE, XX PRODUIT: \nŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\nEXEMPLAIRE2: 1, bon état, 12/6/1975\nEXEMPLAIRE3: 2, bon état, 1/8/1977\nEXEMPLAIRE4: 3, reliure rongée, 3/4/2005\nDF, -1N ŒUVRE, -_11 EXEMPLAIRE1\n+Prof: Num. prof, Nom prof\nEnseignant: num. ens. [numéro identifiant un enseignant], nom ens. [nom enseignant], tél. ens. [téléphone enseignant]\nCOMMANDE: Num commande, Date, Montant, #Réf. client>CLIENT>Réf. client\nCOMMANDE: Num commande, Date, Montant, #Réf. client > CLIENT > Réf. client\nINCLURE: #Num commande>COMMANDE>Num commande, _#Réf. produit>PRODUIT>Réf. produit, Quantité\nINCLURE: #Num commande > COMMANDE > Num commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\nCLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse [varchar(40)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]\nPARTICIPANT: numero [], nom, adresse [type3]\nL33T, 0N> H4X0R, 0N< H4X0R\nL33T123, 0N> H4X0R12, 0N< H4X0R0\n   AYANT-DROIT: nom ayant-droit, lien\n   DIRIGER, 0N EMPLOYÉ, 01 PROJET\n   REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nDIRIGER, EMPLOYÉ, PROJET\nA, B, C\nFoo, Bar\nDIRIGER, EMPLOYÉ, PROJET: biz, buz\nA, B, C: biz, buz\nFoo, Bar: biz, buz\nAYANT-DROIT   :   nom ayant-droit   ,   lien   \nDIRIGER   ,    0N    EMPLOYÉ   ,    01    PROJET   : fizz,  buzz   \nAYANT-DROIT  :  nom ayant-droit  ,  lien  \nDIRIGER  ,  0N  EMPLOYÉ  ,  01  PROJET  : fizz, buzz  \nAYANT-DROIT\t :\t nom ayant-droit\t ,\t lien\t \nDIRIGER\t ,\t\t0N\t\tEMPLOYÉ\t ,\t\t01\t\tPROJET\t : fizz,\tbuzz\t \n() [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(III) [bla bla.]\n(IV) \n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n(III) [bla bla.]: 12.5, 30\n(IV) : 12.5, 30\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, 30\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, BAR\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, BAR\n(IV) : 12.5, 30\n(A) --Lorem, .....Ipsum, -Dolor: 30, 10\n(B) ->Dolor, <-->Sit, -->Amet: 69, 10\n(XX) ->foo, -->foo, -> foo, --> foo\n(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer\n/XT\\ Personne ==> Homme, Femme: sexe\n/XT1\\\\ Personne <= Homme, Femme: sexe\n/XT\\\\ Personne => Homme, Femme: sexe\n/T\\\\ Personne <= Homme, Femme: sexe\n/T\\\\ Personne => Homme, Femme: sexe\n/X\\\\ Personne <= Homme, Femme: sexe\n/X\\\\ Personne => Homme, Femme: sexe\n/\\\\ Personne <= Homme, Femme: sexe\n/\\\\ Personne => Homme, Femme: sexe\n/1\\\\ FOO => BAR\n/T\\\\foo==>foo11\nÉtudiant: num, 1_nom, 1_prénom, adresse, 2_mail\nÉtudiant: 0_num, 1_nom, 1_prénom, adresse, 2_mail\nPosition: 0_latitude, 0_longitude, altitude\nFoo: bar, 1_baz, 21_qux, 123_quux\n\n\n\n% Invalid\n\n\n: foobar\n : foobar\nFOO, 0N Bar, 1N Biz [bla] \nFOO, 0N Bar, 1N Biz [bla]\nFOO, 0N Bar, 1N Biz [bla], 0N Buz\n foo /TX\\\\#  ]  #/ \nBACK\\\\SLASH:\n foo_11<11_ ]<-->]foo\nFOOBAR\n  FOOBAR>\n  FOOBAR    >\n  FOOBAR+\n/T\\\\, foobar\nDIRIGER, 0 EMPLOYÉ, 01 PROJET\nDIRIGER, 0 EMPLOYÉ, 01 PROJET: biz, buz\nDIRIGER, 0NV\n/ANYTHING\\\\ Personne => Homme, Femme: sexe\n/X12\\\\ Personne => Homme, Femme: sexe\n/1N\\\\\n(I) : 1, 2, 3\nDIRIGER,\nDIRIGER,    \n(I) : \n(I) ->Foo ..Bar : \n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, \n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOOBAR, \n(A) : Ipsum, --Lorem: 30, 90\n +\n   +#   \n/T\\\\ \\\\.. ,\\\\foo\n+..==>\n /TX\\\\ foo -> .bar\nPARTICIPANT: numero [, nom, adresse\n(])\n(+)\n(/)\n(IIII)\n(    )\n(    )\n(A) --Lorem, >Ipsum: 30, 90\n(A) --Lorem, : Ipsum: 30, 90\n(A) --Lorem 30, 90\n(A) >Ipsum, --Lorem: 30, 90\n/TX\\\\ foo bar \nCOMMANDE: Num commande, Date, Montant, #Réf. client->CLIENT->Réf. client\nINCLURE: #Num commande->COMMANDE->Num commande, _#Réf. produit->PRODUIT->Réf. produit, Quantité\n(A) ->Ipsum ->Lorem: 30, 90\nFOOBAR: foo, /bar\nFOO, 1N Bar: -->Amet\nFOOBAR: foo>bar, biz\nFOO: #bar, biz\nFOO: #bar\nFOO: biz, #bar\nFOO: #bar>buzz, biz\nFOO: #bar>buzz\nFOO: biz, #bar>buzz\nFOO: #bar>buzz>, biz\nFOO: #bar>buzz>\nFOO: biz, #bar>buzz>  \nDIRIGER, 0N EMPLOYÉ > PRODUIT, Quantité\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5\n(A) ->Ipsum, ->Lorem: 30, 9N\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 3,14 3,14"
  },
  {
    "path": "laowantong.vscode-mocodo/language-configuration.json",
    "content": "{\n    \"comments\": {\n        \"lineComment\": \"%\",\n    },\n    \"autoClosingPairs\": [\n        [\"[\", \"]\"],\n        [\"(\", \")\"]\n    ],\n    \"surroundingPairs\": [\n        [\"[\", \"]\"],\n        [\"(\", \")\"]\n    ]\n}"
  },
  {
    "path": "laowantong.vscode-mocodo/package.json",
    "content": "{\n  \"name\": \"vscode-mocodo\",\n  \"version\": \"1.0.6\",\n  \"publisher\": \"laowantong\",\n  \"engines\": {\n    \"vscode\": \"^1.2.0\"\n  },\n  \"icon\": \"images/android-chrome-512x512.png\",\n  \"license\": \"MIT\",\n  \"displayName\": \"Mocodo syntax highlighter\",\n  \"description\": \"A syntax highlighter for Mocodo E/R diagrams\",\n  \"categories\": [\n    \"Programming Languages\"\n  ],\n\t\"homepage\": \"https://marketplace.visualstudio.com/items?itemName=laowantong.vscode-mocodo\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/laowantong/mocodo\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/laowantong/mocodo/issues\"\n\t},\n  \"contributes\": {\n    \"languages\": [{\n      \"id\": \"mocodo\",\n      \"aliases\": [\"Mocodo\", \"mocodo\"],\n      \"extensions\": [\".mcd\", \".mld\"],\n      \"configuration\": \"./language-configuration.json\"\n    }],\n    \"grammars\": [{\n      \"language\": \"mocodo\",\n      \"scopeName\": \"source.mocodo\",\n      \"path\": \"./syntaxes/mocodo.tmLanguage.json\"\n    }]\n  }\n}\n"
  },
  {
    "path": "laowantong.vscode-mocodo/syntaxes/mocodo.tmLanguage.json",
    "content": "{\n  \"name\": \"Mocodo\",\n  \"scopeName\": \"source.mocodo\",\n  \"uuid\": \"2AD24A5A-63C9-40B3-B6AA-E240B7B54480\",\n  \"patterns\": [\n    { \"include\": \"#indent\" },\n    { \"include\": \"#comment\" },\n    { \"include\": \"#phantoms\" },\n    { \"include\": \"#constraint_clause\" },\n    { \"include\": \"#inheritance_clause\" },\n    { \"include\": \"#association_clause\" },\n    { \"include\": \"#entity_clause\" },\n    { \"include\": \"#invalid\" }\n  ],\n  \"repository\": {\n    \"indent\": { \"match\": \"^\\\\s+\" },\n    \"comment\": {\n      \"patterns\": [\n        {\n          \"match\": \"%%mocodo\\\\b.*$\",\n          \"name\": \"markup.bold comment.line.magic.mocodo\"\n        },\n        {\n          \"match\": \"%.*$\",\n          \"name\": \"comment.line.normal.mocodo\"\n        }\n      ]\n    },\n    \"phantoms\": {\n      \"description\": \"A line containing at least one colon, ane nothing else but spaces and colons\",\n      \"match\": \":[:\\\\s]*$\",\n      \"name\": \"markup.italic punctuation.separator.phantom.mocodo\"\n    },\n    \"association_clause\": {\n      \"name\": \"association.mocodo\",\n      \"begin\": \"(\\\\+|-)?((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])(?=\\\\s*,\\\\s*)\",\n      \"end\": \"$|^\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.mocodo\" },\n        \"2\": { \"name\": \"markup.bold support.function.association.mocodo\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#association_legs\" }\n      ]\n    },\n    \"association_legs\": {\n      \"name\": \"legs.mocodo\",\n      \"begin\": \"\",\n      \"end\": \"$|^\",\n      \"patterns\": [\n        {\n          \"match\": \"\\\\s*,\\\\s*(?:(-)?([_/])?((?![-_\\\\/])(?:[\\\\w?]{2})(?=[\\\\s]*[^\\\\w,\\\\r\\\\n:])))?([<>])?\\\\s*(\\\\[.*?\\\\])?\\\\s*((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])\\\\s*\",\n          \"captures\": {\n            \"1\": { \"name\": \"keyword.control.card_hidden.mocodo\" },\n            \"2\": { \"name\": \"keyword.control.card_prefix.mocodo\" },\n            \"3\": { \"name\": \"support.function.cardinality.mocodo\" },\n            \"4\": { \"name\": \"keyword.control.arrow.mocodo\" },\n            \"5\": { \"name\": \"string.regexp.note.mocodo\" },\n            \"6\": { \"name\": \"token.info-token.entity.mocodo\" }\n          }\n        },\n        { \"include\": \"#association_attrs\" },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"association_attrs\": {\n      \"name\": \"attrs.mocodo\",\n      \"begin\": \"\\\\s*:\\\\s*\",\n      \"end\": \"$|^\",\n      \"patterns\": [\n        { \"include\": \"#typed_attr\" },\n        {\n          \"match\": \"\\\\s*,\\\\s*\",\n          \"name\": \"punctuation.separator\"\n        }\n      ]\n    },\n    \"typed_attr\": {\n      \"name\": \"typed_attribute.mocodo\",\n      \"match\": \"((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s])\\\\s*(\\\\[.*?\\\\])?\\\\s*\",\n      \"captures\": {\n        \"1\": { \"name\": \"support.type.attribute.mocodo\" },\n        \"2\": { \"name\": \"markup.italic token.warn-token.datatype.mocodo\" }\n      }\n    },\n    \"entity_clause\": {\n      \"name\": \"entity.mocodo\",\n      \"begin\": \"(\\\\+|-)?((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])\\\\s*:\\\\s*\",\n      \"end\": \"$|^\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"keyword.control.mocodo\" },\n        \"2\": { \"name\": \"markup.bold token.info-token.entity.mocodo\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#entity_first_attr\" }\n      ]\n    },\n    \"entity_first_attr\": {\n      \"begin\": \"(?:((?:\\\\d*0\\\\d*_|_))((?:(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]|#(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]))|([1-9]+_)?((?:(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]|#(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]))|)\\\\s*(\\\\[.*?\\\\])?\",\n      \"end\": \"$|^\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"string.regexp.id_symbols.mocodo\" },\n        \"2\": { \"name\": \"support.type.attribute.mocodo\" },\n        \"3\": { \"name\": \"string.regexp.alt_id_symbols.mocodo\" },\n        \"4\": { \"name\": \"markup.underline support.type.attribute.mocodo\" },\n        \"5\": { \"name\": \"markup.italic token.warn-token.datatype.mocodo\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#entity_next_attrs\" },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"entity_next_attrs\": {\n      \"patterns\": [\n        {\n          \"match\": \"\\\\s*,\\\\s*(?:((?:\\\\d*0\\\\d*_|_))((?:(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]|#(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]))|([1-9]+_)?((?:(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]|#(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\\\\s*>\\\\s*(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]))|)\\\\s*(\\\\[.*?\\\\])?\",\n          \"captures\": {\n            \"1\": { \"name\": \"string.regexp.id_symbols.mocodo\" },\n            \"2\": { \"name\": \"markup.underline support.type.attribute.mocodo\" },\n            \"3\": { \"name\": \"string.regexp.alt_id_symbols.mocodo\" },\n            \"4\": { \"name\": \"support.type.attribute.mocodo\" },\n            \"5\": { \"name\": \"markup.italic token.warn-token.datatype.mocodo\" }\n          }\n        },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"constraint_clause\": {\n      \"name\": \"constraint.mocodo\",\n      \"begin\": \"(\\\\([a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF\\\\d_\\\\s]{0,3}\\\\))\\\\s*(\\\\[.*?\\\\])?\\\\s*\",\n      \"end\": \"$|^\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"markup.bold variable.constraint_name.mocodo\" },\n        \"2\": { \"name\": \"string.regexp.note.mocodo\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#constraint_targets\" }\n      ]\n    },\n    \"constraint_targets\": {\n      \"name\": \"targets.mocodo\",\n      \"begin\": \"\",\n      \"end\": \"$|^\",\n      \"patterns\": [\n        {\n          \"match\": \"(<?(?:\\\\.+|-+)>?)?\\\\s*((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])\",\n          \"captures\": {\n            \"1\": { \"name\": \"string.regexp.constraint_leg.mocodo\" },\n            \"2\": { \"name\": \"variable.other.constant.box.mocodo\" }\n          }\n        },\n        { \"match\": \"\\\\s*,\\\\s*\" },\n        { \"include\": \"#constraint_coords\" },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"constraint_coords\": {\n      \"name\": \"coords.mocodo\",\n      \"match\": \"\\\\s*:\\\\s*((?:-?\\\\d+(?:\\\\.\\\\d+)?(?:[eE][+-]?\\\\d+)?|(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\]))\\\\s*,\\\\s*((?:-?\\\\d+(?:\\\\.\\\\d+)?(?:[eE][+-]?\\\\d+)?|(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\]))$\",\n      \"captures\": {\n        \"1\": { \"name\": \"markup.italic string.regexp.constraint_coords.mocodo\" },\n        \"2\": { \"name\": \"markup.italic string.regexp.constraint_coords.mocodo\" }\n      }\n    },\n    \"inheritance_clause\": {\n      \"name\": \"inheritance.mocodo\",\n      \"begin\": \"(/(?:XT\\\\d?|TX\\\\d?|X\\\\d?|T\\\\d?|\\\\d?)\\\\\\\\{1,2})\\\\s*((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])?\\\\s*((?:<==?|<--?|--?>|==?>))\\\\s*\",\n      \"end\": \"$|^\",\n      \"beginCaptures\": {\n        \"1\": { \"name\": \"markup.bold support.function.inheritance.mocodo markup.underline\" },\n        \"2\": { \"name\": \"token.info-token.parent.mocodo\" },\n        \"3\": { \"name\": \"keyword.control.arrow.mocodo\" }\n      },\n      \"patterns\": [\n        { \"include\": \"#inheritance_children\" }\n      ]\n    },\n    \"inheritance_children\": {\n      \"name\": \"children.mocodo\",\n      \"begin\": \"\",\n      \"end\": \"$|^\",\n      \"patterns\": [\n        {\n          \"match\": \"((?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF])[^=<>,:\\\\\\\\]*[^-\\\\[\\\\]\\\\\\\\=<>,:\\\\s\\\\\\\\])\",\n          \"name\": \"token.info-token.child.mocodo\"\n        },\n        { \"match\": \"\\\\s*,\\\\s*\" },\n        { \"include\": \"#inheritance_attrs\" },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"inheritance_attrs\": {\n      \"name\": \"attrs.mocodo\",\n      \"begin\": \"\\\\s*:\\\\s*\",\n      \"end\": \"$|^\",\n      \"patterns\": [\n        {\n          \"match\": \"(?=[a-zA-Z\\\\u00C0-\\\\u024F\\\\u1E00-\\\\u1EFF0-9])[^\\\\[\\\\]>,]*[^\\\\[\\\\]>,\\\\s]\",\n          \"name\": \"markup.italic string.regexp.inheritance_attribute.mocodo\"\n        },\n        { \"match\": \"\\\\s*,\\\\s*\" },\n        { \"include\": \"#invalid\" }\n      ]\n    },\n    \"invalid\": {\n      \"match\": \".+\",\n      \"name\": \"invalid.illegal.mocodo\"\n    }\n  }\n}"
  },
  {
    "path": "laowantong.vscode-mocodo/syntaxes/mocodo.tmLanguage.yaml",
    "content": "---\nname: Mocodo\nscopeName: source.mocodo\nuuid: 2AD24A5A-63C9-40B3-B6AA-E240B7B54480\n\n# Warning: yaml_to_json_tmlanguage.py will suppress all \" \" symbols from the regexes.\n\nvariables:\n  latin: 'a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF'\n  attr: '(?=[{{latin}}0-9]) [^\\[\\]>,]*[^\\[\\]>,\\s]'\n  box_def_prefix: '\\+|-'\n  constraint_name: '\\([{{latin}}\\d_\\s]{0,3}\\)'\n  card_hidden: '-'\n  card_prefix: '[_/]'\n  colon: '\\s*:\\s*'\n  comma: '\\s*,\\s*'\n  constraint_leg: '<?(?:\\.+|-+)>?'\n  id_symbols: '(?: \\d*0\\d*_|_)'\n  alt_id_symbols: '[1-9]+_'\n  inheritance_name: '/ (?: XT\\d?|TX\\d?|X\\d?|T\\d?|\\d? ) \\\\{1,2}'\n  inheritance_arrow: '(?: <==?|<--?|--?>|==?> )'\n  leg_arrow: '[<>]'\n  morethan: '\\s*>\\s*'\n  note: \\[.*?\\]\n  number: '-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?'\n  box_name: '(?=[{{latin}}]) [^=<>,:\\\\]* [^-\\[\\]\\\\=<>,:\\s\\\\]'\n  card: '(?![-_\\/]) (?:[\\w?]{2}) (?=[\\s]*[^\\w,\\r\\n:])'\n  constraint_coord: '(?: {{number}} | {{box_name}} )'\n  foreign_reference: '#{{attr}} {{morethan}} {{attr}} {{morethan}} {{attr}}'\n  entity_or_table_attr: '(?: {{attr}} | {{foreign_reference}} )'\n\npatterns:\n- include: \"#indent\"\n- include: \"#comment\"\n- include: \"#phantoms\"\n- include: \"#constraint_clause\"\n- include: \"#inheritance_clause\"\n- include: \"#association_clause\"\n- include: \"#entity_clause\"\n- include: \"#invalid\"\n\nrepository:\n\n  indent:\n    match: ^\\s+\n\n  comment:\n    patterns:\n    - # Jupyter cell magic command, interpreted as a comment\n      match: '%%mocodo\\b.*$'\n      name: \"markup.bold comment.line.magic.mocodo\"\n    - # Normal comment line\n      match: '%.*$'\n      name: comment.line.normal.mocodo\n\n  phantoms:\n    description: A line containing at least one colon, ane nothing else but spaces and colons\n    match: ':[:\\s]*$'\n    name: \"markup.italic punctuation.separator.phantom.mocodo\"\n\n  association_clause:\n    name: association.mocodo\n    begin: '({{box_def_prefix}})? ({{box_name}}) (?={{comma}})'\n    end: '$|^'\n    beginCaptures:\n      '1': { name: keyword.control.mocodo }\n      '2': { name: \"markup.bold support.function.association.mocodo\" }\n    patterns:\n      - include: \"#association_legs\"\n\n  association_legs:\n    name: legs.mocodo\n    begin: ''\n    end: '$|^'\n    patterns:\n      - match: >- # Multiline string without a linebreak appended at the end.\n          {{comma}}\n          (?: ({{card_hidden}})? ({{card_prefix}})? ({{card}}))? ({{leg_arrow}})? \\s*\n          ({{note}})? \\s*\n          ({{box_name}}) \\s*\n        captures:\n          '1': { name: keyword.control.card_hidden.mocodo }\n          '2': { name: keyword.control.card_prefix.mocodo }\n          '3': { name: support.function.cardinality.mocodo }\n          '4': { name: keyword.control.arrow.mocodo }\n          '5': { name: string.regexp.note.mocodo }\n          '6': { name: token.info-token.entity.mocodo }\n      - include: \"#association_attrs\"\n      - include: \"#invalid\"\n\n  association_attrs:\n    name: attrs.mocodo\n    begin: \"{{colon}}\"\n    end: '$|^'\n    patterns:\n      - include: \"#typed_attr\"\n      - match: '{{comma}}'\n        name: punctuation.separator\n  \n  typed_attr:\n    name: typed_attribute.mocodo\n    match: '({{attr}}) \\s* ({{note}})? \\s*'\n    captures:\n      '1': { name: support.type.attribute.mocodo }\n      '2': { name: \"markup.italic token.warn-token.datatype.mocodo\" }\n\n  entity_clause:\n    name: entity.mocodo\n    begin: '( {{box_def_prefix}} )? ( {{box_name}} ) {{colon}}'\n    end: '$|^'\n    beginCaptures:\n      '1': { name: keyword.control.mocodo }\n      '2': { name: \"markup.bold token.info-token.entity.mocodo\" }\n    patterns:\n      - include: \"#entity_first_attr\"\n  \n  entity_first_attr:\n    # After the entity's name, process the first attribute\n    # Underline it iff it is **not** prefixed by id_symbols.\n    begin: '(?: ({{id_symbols}}) ({{entity_or_table_attr}}) | ({{alt_id_symbols}})? ({{entity_or_table_attr}}) | ) \\s* ({{note}})?'\n    end: '$|^'\n    beginCaptures:\n      '1': { name: string.regexp.id_symbols.mocodo }\n      '2': { name: support.type.attribute.mocodo}\n      '3': { name: string.regexp.alt_id_symbols.mocodo }\n      '4': { name: \"markup.underline support.type.attribute.mocodo\" }\n      '5': { name: \"markup.italic token.warn-token.datatype.mocodo\" }\n    patterns:\n      - include: \"#entity_next_attrs\"\n      - include: \"#invalid\"\n    \n  entity_next_attrs:\n    # After the first attribute, process the remaining ones.\n    # Underline them iff they are prefixed by a \"_\" symbol.\n    patterns:\n      - match: '{{comma}} (?: ({{id_symbols}}) ({{entity_or_table_attr}}) | ({{alt_id_symbols}})? ({{entity_or_table_attr}}) | ) \\s* ({{note}})?'\n        captures:\n          '1': { name: string.regexp.id_symbols.mocodo }\n          '2': { name: \"markup.underline support.type.attribute.mocodo\" }\n          '3': { name: string.regexp.alt_id_symbols.mocodo }\n          '4': { name: support.type.attribute.mocodo}\n          '5': { name: \"markup.italic token.warn-token.datatype.mocodo\" }\n      - include: '#invalid'\n\n  constraint_clause:\n    name: constraint.mocodo\n    begin: '({{constraint_name}}) \\s* ({{note}})? \\s*'\n    end: '$|^'\n    beginCaptures:\n      '1': { name: markup.bold variable.constraint_name.mocodo }\n      '2': { name: string.regexp.note.mocodo }\n    patterns:\n      - include: \"#constraint_targets\"\n\n  constraint_targets:\n    name: targets.mocodo\n    begin: ''\n    end: '$|^'\n    patterns:\n      - match: '({{constraint_leg}})? \\s* ({{box_name}})'\n        captures:\n          '1': { name: string.regexp.constraint_leg.mocodo }\n          '2': { name: variable.other.constant.box.mocodo }\n      - match: '{{comma}}'\n      - include: \"#constraint_coords\"\n      - include: \"#invalid\"\n  \n  constraint_coords:\n    name: coords.mocodo\n    match: '{{colon}} ({{constraint_coord}}) {{comma}} ({{constraint_coord}})$'\n    captures:\n      '1': { name: \"markup.italic string.regexp.constraint_coords.mocodo\" }\n      '2': { name: \"markup.italic string.regexp.constraint_coords.mocodo\" }\n\n  inheritance_clause:\n    name: inheritance.mocodo\n    begin: '({{inheritance_name}}) \\s* ({{box_name}})? \\s* ({{inheritance_arrow}}) \\s*'\n    end: '$|^'\n    beginCaptures:\n      '1': { name: \"markup.bold support.function.inheritance.mocodo markup.underline\" }\n      '2': { name: token.info-token.parent.mocodo }\n      '3': { name: keyword.control.arrow.mocodo }\n    patterns:\n      - include: \"#inheritance_children\"\n\n  inheritance_children:\n    name: children.mocodo\n    begin: ''\n    end: '$|^'\n    patterns:\n      - match: '({{box_name}})'\n        name: token.info-token.child.mocodo\n      - match: '{{comma}}'\n      - include: \"#inheritance_attrs\"\n      - include: \"#invalid\"\n\n  inheritance_attrs:\n    name: attrs.mocodo\n    begin: '{{colon}}'\n    end: '$|^'\n    patterns:\n      - match: '{{attr}}'\n        name: \"markup.italic string.regexp.inheritance_attribute.mocodo\"\n      - match: '{{comma}}'\n      - include: \"#invalid\"\n\n  invalid:\n    match: '.+'\n    name: invalid.illegal.mocodo\n\n"
  },
  {
    "path": "laowantong.vscode-mocodo/vsc-extension-quickstart.md",
    "content": "# Welcome to your VS Code Extension\n\n## What's in the folder\n\n* This folder contains all of the files necessary for your extension.\n* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension.\n* `syntaxes/mocodo.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization.\n* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets.\n\n## Get up and running straight away\n\n* Make sure the language configuration settings in `language-configuration.json` are accurate.\n* Press `F5` to open a new window with your extension loaded.\n* Create a new file with a file name suffix matching your language.\n* Verify that syntax highlighting works and that the language configuration settings are working.\n\n## Make changes\n\n* You can relaunch the extension from the debug toolbar after making changes to the files listed above.\n* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.\n\n## Add more language features\n\n* To add features such as IntelliSense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs\n\n## Install your extension\n\n* To start using your extension with Visual Studio Code copy it into the `<user home>/.vscode/extensions` folder and restart Code.\n* To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension.\n"
  },
  {
    "path": "mocodo/__init__.py",
    "content": "from pathlib import Path\nfrom importlib import import_module\n\n__version__ = \"4.3.3\"\nSCRIPT_DIRECTORY = Path(__file__).resolve().parent\n\n\ndef load_ipython_extension(ipython):\n    # This function is called when the extension is loaded in a notebook\n    # with %load_ext mocodo or %reload_ext mocodo.\n    mocodo = import_module(\"mocodo.magic\").mocodo\n    ipython.register_magic_function(mocodo, 'line_cell', 'mocodo')\n    print(f\"Mocodo {__version__} loaded.\")\n"
  },
  {
    "path": "mocodo/__main__.py",
    "content": "import sys\n\nif sys.version_info < (3, 6):\n    print(f\"Mocodo requires Python 3.6 or later to run.\\nThis version is {sys.version}.\")\n    sys.exit()\n\nimport contextlib\nimport importlib\nimport json\nfrom pathlib import Path\n\nfrom .argument_parser import parsed_arguments\nfrom .common import Common, Printer\nfrom .convert.read_template import read_template\nfrom .convert.relations import Relations\nfrom .font_metrics import font_metrics_factory\nfrom .guess_title import may_update_params_with_guessed_title\nfrom .mcd import Mcd\nfrom .mcd_to_svg import main as dump_mcd_to_svg\nfrom .mocodo_error import MocodoError, subopt_error\nfrom .rewrite import op_tk, guess_entities\nfrom .tools.graphviz_tools import minify_graphviz\nfrom .tools.string_tools import urlsafe_encoding\nfrom .tools.various import invert_dict\n\n\nSHOW_ARGS = invert_dict({\n    \"mcd\": [\"mcd\"],\n    \"rw\": [\"rw\", \"source\", \"text\", \"code\", \"mocodo\"],\n    \"cv\": [\"cv\", \"mld\", \"ddl\", \"sql\"],\n})\n\nclass ResponseLogger:\n\n    def __init__(self, params):\n        if not params[\"is_magic\"]:\n            self.may_log = self.log_nothing\n            return\n        self.response = {\n            \"mld\": params[\"mld\"],\n            \"args_to_delete\": params[\"args_to_delete\"],\n            \"opt_to_restore\": params[\"opt_to_restore\"],\n            \"redirect_output\": params[\"redirect_output\"],\n            \"select\": params[\"select\"],\n        }\n        self.may_log = self.log_for_magic\n        self.path = Path(f\"{params['output_name']}_response_for_magic_command.json\")\n        self.dump()\n    \n    def log_nothing(self, *args, **kwargs):\n        pass\n\n    def log_for_magic(self, key, value):\n        self.response[key] = value\n        self.dump()\n    \n    def dump(self):\n        self.path.write_text(json.dumps(self.response, ensure_ascii=False), encoding=\"utf8\")\n\n\ndef flip(source, subargs):\n    for subsubopt in \"\".join(subargs.keys()):\n        mcd = Mcd(source)\n        if subsubopt == \"v\":\n            source = mcd.get_vertically_flipped_clauses()\n        elif subsubopt == \"h\":\n            source = mcd.get_horizontally_flipped_clauses()\n        elif subsubopt == \"d\":\n            source = mcd.get_diagonally_flipped_clauses()\n        else:\n            subopt_error(\"flip\", subsubopt)\n    return source\n\n\nclass Runner:\n\n    def __init__(self, args, printer):\n        self.printer = printer\n        try:\n            self.params = parsed_arguments(args)\n            self.parsing_error = None\n            self.common = Common(self.params)\n            self.get_font_metrics = font_metrics_factory(self.params)\n        except MocodoError as e:\n            # Raising a parsing error must be delayed, otherwise it will not be displayed as a MocodoError\n            self.parsing_error = e\n    \n    def __call__(self):\n        if self.parsing_error:\n            raise self.parsing_error\n        \n        source = self.common.load_input_file()\n\n        if self.params[\"restore\"]:\n            shutil = importlib.import_module(\"shutil\")\n            path = Path(self.params[\"script_directory\"], \"resources\", \"pristine_sandbox.mcd\")\n            shutil.copyfile(path, \"sandbox.mcd\")\n            Path(\"params.json\").write_text(\"{}\\n\", encoding=\"utf8\")\n            return\n        \n        if self.params[\"print_params\"]:\n            for added_key in self.params[\"keys_to_hide\"][:]:\n                self.params.pop(added_key, None)\n            with contextlib.suppress(ValueError): # raised when called as a function (from mocodo import mocodo)\n                self.params[\"output_dir\"] = str(Path(self.params[\"output_dir\"]).resolve().relative_to(Path.cwd()))\n            text = json.dumps(self.params, ensure_ascii=False, indent=2, sort_keys=True)\n            text = text.replace(\"\\n    \", \" \")\n            text = text.replace(\"\\n  ]\", \" ]\")\n            self.printer.write(text.strip())\n            return \"\\n\".join(self.printer.accumulator)\n\n        self.add_gutter_params(self.params)\n\n        if self.params[\"mld\"] or (\"transform\" in self.params and self.params[\"transform\"] == []):\n            # In case there is an option `--mld` or an option `--transform` without arguments,\n            # inject manually the equivalent --convert sub-option\n            self.params[\"mld\"] = True\n            self.params[\"convert\"].insert(0, (\"markdown\", {}))\n\n        if \"select\" in self.params: # the user wants to override the default display policy under Jupyter\n            if \"all\" in self.params[\"select\"]:\n                self.params[\"select\"] = [\"mcd\", \"rw\", \"cv\"] if self.params[\"rewrite\"] else [\"mcd\", \"cv\"]\n            normalized_user_choices = []\n            for k in self.params[\"select\"]:\n                if k.lower() not in SHOW_ARGS:\n                    raise MocodoError(28, _('Unknown argument \"{k}\" for option --select.').format(k=k)) # fmt: skip\n                normalized_user_choices.append(SHOW_ARGS[k.lower()])\n            self.params[\"select\"] = normalized_user_choices\n        else:\n            if self.params[\"rewrite\"] and self.params[\"convert\"]:\n                self.params[\"select\"] = [\"mcd\", \"cv\"]\n            elif self.params[\"rewrite\"]:\n                self.params[\"select\"] = [\"mcd\", \"rw\"]\n            elif self.params[\"convert\"] and self.params[\"mld\"]:\n                self.params[\"select\"] = [\"mcd\", \"cv\"]\n            elif self.params[\"convert\"]:\n                self.params[\"select\"] = [\"cv\"]\n            else:\n                self.params[\"select\"] = [\"mcd\"]\n\n        response = ResponseLogger(self.params)\n\n        if self.params[\"rewrite\"]:\n            for (subopt, subargs) in self.params[\"rewrite\"]:\n                if subopt == \"echo\":\n                    pass\n                elif subopt == \"flip\":\n                    source = flip(source, subargs)\n                elif subopt == \"create\" and \"entities\" in subargs:\n                    source = guess_entities.run(source, subargs[\"entities\"])\n                elif subopt == \"delete\" and \"dfs\" in subargs:\n                    module = importlib.import_module(f\".rewrite._delete_dfs\", package=\"mocodo\")\n                    source = module.run(source, self.params)\n                elif subopt in self.params[\"op_tk_rewritings\"]: # ex.: create, delete, ascii, etc.\n                    source = op_tk.run(source, op_name=subopt, subargs=subargs, params=self.params).rstrip()\n                else: # An unspecified rewrite operation, dynamically loaded\n                    try:\n                        module = importlib.import_module(f\".rewrite._{subopt}\", package=\"mocodo\")\n                    except ModuleNotFoundError:\n                        raise subopt_error(\"rewrite\", subopt)\n                    source = module.run(source, subopt=subopt, subargs=subargs, params=self.params).rstrip()\n                response.may_log(\"rewritten_source\", source)\n            if not self.params[\"is_magic\"]:\n                self.printer.write(self.common.update_source(source))\n        \n        may_update_params_with_guessed_title(source, self.params)\n\n        converted_file_paths = [] # list of files to be displayed in the notebook\n        raw_relations = None\n        sql_relations = None\n        if self.params[\"convert\"]:\n            response.may_log(\"has_explicit_conversion\", True)\n            results = []\n            for (subopt, subargs) in self.params[\"convert\"]:\n\n                # Try to interpret subopt as the stem or path of a relation template\n                template = None\n                official_template_dir = Path(self.params[\"script_directory\"], \"resources\", \"relation_templates\")\n                if subopt == \"relation\":\n                    stem_or_path = next(iter(subargs.keys()), \"\") # ignore all sub-arguments after the first one\n                    template = read_template(stem_or_path, official_template_dir)\n                elif Path(official_template_dir, f\"{subopt}.yaml\").is_file():\n                    template_suffix = next(iter(subargs.keys()), \"\") # ignore all sub-arguments after the first one\n                    if template_suffix and set(\"bce\").issuperset(template_suffix):\n                        stem = f\"{subopt}-{''.join(sorted(template_suffix))}\"\n                    else:\n                        stem = subopt\n                    template = read_template(stem, official_template_dir)\n                \n                # If the subopt was a relation template, use it to convert the source\n                if template:\n                    if template[\"extension\"] == \"sql\":\n                        if not sql_relations:\n                            sql_source = source\n                            sql_source = op_tk.run(sql_source, \"ascii\", {\"labels\": 1, \"roles\": 1}, self.params)\n                            sql_mcd = Mcd(sql_source, self.get_font_metrics, **self.params)\n                            sql_relations = Relations(sql_mcd, self.params)\n                        text = sql_relations.get_text(template)\n                    else:\n                        if not raw_relations:\n                            mcd = Mcd(source, self.get_font_metrics, **self.params)\n                            raw_relations = Relations(mcd, self.params)\n                        text = raw_relations.get_text(template)\n                    result = {\n                        \"stem_suffix\": template[\"stem_suffix\"],\n                        \"text\": text,\n                        \"extension\": template[\"extension\"],\n                        \"to_defer\": template.get(\"to_defer\", False),\n                        \"highlight\": template.get(\"highlight\", \"plain\"),\n                    }\n\n                # Fall back to a dynamically loaded conversion operation\n                else:\n                    try:\n                        module = importlib.import_module(f\".convert._{subopt}\", package=\"mocodo\")\n                    except ModuleNotFoundError:\n                        raise subopt_error(\"convert\", subopt)\n                    result = module.run(source, subargs, self.common)\n                \n                result[\"text_path\"] = Path(f\"{self.params['output_name']}{result['stem_suffix']}.{result['extension']}\")\n                result[\"text_path\"].write_text(f\"{result['text'].rstrip()}\\n\", encoding=\"utf8\")\n                self.printer.write(self.common.output_success_message(result[\"text_path\"]))\n                results.append(result)\n            for result in results:\n                converted_file_paths.extend(self.get_converted_file_paths(result))\n            response.may_log(\"converted_file_paths\", converted_file_paths)\n\n        if not raw_relations: # if the MCD has not be calculated during the conversions\n            mcd = Mcd(source, self.get_font_metrics, **self.params)\n        self.control_for_overlaps(mcd)\n        resulting_paths = dump_mcd_to_svg(mcd, self.common)  # potential side-effect: update *_geo.json\n        for path in resulting_paths:\n            self.printer.write(self.common.output_success_message(path))\n\n    def get_rendering_service(self, extension):\n        path = Path(self.params[\"script_directory\"], \"resources\", \"rendering_services.json\")\n        try:\n            rendering_services = json.loads(path.read_text(encoding=\"utf8\"))\n        except FileNotFoundError:\n            raise MocodoError(46, _('The file \"{path}\" is missing.').format(path=path))  # fmt: skip\n        except json.decoder.JSONDecodeError:\n            raise MocodoError(47, _('The file \"{path}\" is not a valid JSON file.').format(path=path))  # fmt: skip\n        except Exception as err:\n            raise MocodoError(48, _('The file \"{path}\" could not be read:\\n{err}').format(path=path, err=err))  # fmt: skip\n        try:\n            return rendering_services[extension]\n        except KeyError:\n            raise MocodoError(49, _('No third-party rendering service for extension \"{extension}\". You may want to add one in \"{path}\".').format(extension=extension, path=path))\n\n    def get_converted_file_paths(self, result):\n        if result.get(\"to_defer\") and \"defer\" in self.params:\n            # This text must be rendered by a third-party service\n            urllib = importlib.import_module(\"urllib\")\n            requests = importlib.import_module(\"requests\")\n            mimetypes = importlib.import_module(\"mimetypes\")\n            service = self.get_rendering_service(result[\"extension\"])\n            data = result[\"text\"]\n            for preprocessing in service.get(\"preprocessing\", []):\n                if preprocessing == \"minify_graphviz\":\n                    # Spare some bandwidth\n                    data = minify_graphviz(data)\n                elif preprocessing == \"urlsafe_encoding\":\n                    data = urlsafe_encoding(data)\n                elif preprocessing == \"encode_prefix\":\n                    # Sole use case (so far): \"https://mocodo.net/?mcd=\"\" becomes \"https%3A//mocodo.net/%3Fmcd%3D\"\n                    index = data.find(\"=\") + 1\n                    data = urllib.parse.quote(data[:index]) + data[index:]\n            url = service[\"url\"].format(data=data)\n            response = requests.get(url)\n            if not response.ok:\n                raise MocodoError(23, _(\"The HTTP status code {code} was returned by:\\n{url}\").format(code=response.status_code, url=url)) # fmt: skip\n            content_type = response.headers['content-type']\n            extension = mimetypes.guess_extension(content_type)\n            resp_path = result[\"text_path\"].with_suffix(extension)\n            if content_type.startswith(\"text/\"):\n                resp_path.write_text(response.text, encoding=\"utf8\")\n            else:\n                resp_path.write_bytes(response.content)\n            yield str(resp_path)\n        elif result.get(\"stem_suffix\") == \"_mld\" and result.get(\"extension\") == \"mcd\" and self.params[\"is_magic\"]: # relational diagram\n            mld = Mcd(result[\"text\"], self.get_font_metrics, **self.params)\n            backup_input = self.params[\"input\"]\n            backup_output_name = self.params[\"output_name\"]\n            self.params[\"input\"] = result[\"text_path\"]\n            self.params[\"output_name\"] = f\"{self.params['output_name']}_mld\"\n            dump_mcd_to_svg(mld, self.common)\n            self.params[\"input\"] = backup_input\n            self.params[\"output_name\"] = backup_output_name\n            yield str(result['text_path'].with_suffix(\".svg\"))\n        else:\n            # This text doesn't need further processing\n            yield str(result[\"text_path\"])\n\n    def control_for_overlaps(self, mcd):\n        if self.params[\"detect_overlaps\"]:\n            overlaps = mcd.get_overlaps()\n            if overlaps:\n                acc = []\n                for (b1, b2, b3, b4) in overlaps:\n                    if b3 == b4:\n                        acc.append(_('  - Leg \"{b1} — {b2}\" overlaps \"{b3}\".').format(b1=b1, b2=b2, b3=b3))  # fmt: skip\n                    else:\n                        acc.append(_('  - Legs \"{b1} — {b2}\" and \"{b3} — {b4}\" overlap.').format(b1=b1, b2=b2, b3=b3, b4=b4))  # fmt: skip\n                details = \"\\n\".join(sorted(acc))\n                raise MocodoError(29, _('Bad layout of boxes:\\n{details}\\nTo fix the problem, reorder and/or skip lines in the source text, either manually, or with the option -t arrange (chocolate bar under Mocodo online).').format(details=details))  # fmt: skip\n\n    def add_gutter_params(self, params):\n        gutters = dict(params.get(\"gutters\", []))\n\n        # Ensure that the --gutter sub-options are a subset of {\"ids\", \"types\"}\n        for subopt in gutters:\n            if subopt not in (\"ids\", \"types\"):\n                raise subopt_error(\"gutters\", subopt)\n        \n        # Create the sub-option \"ids\" if needed, and initialize id_gutter params\n        if \"ids\" not in gutters:\n            gutters[\"ids\"] = {} # created at the end of the (ordered) dict\n        params[\"id_gutter_visibility\"] = gutters[\"ids\"].get(\"visibility\", \"auto\")\n        params[\"id_gutter_weak_string\"] = gutters[\"ids\"].get(\"weak\", \"id\")\n        params[\"id_gutter_strong_string\"] = gutters[\"ids\"].get(\"strong\", \"ID\")\n        s = gutters[\"ids\"].get(\"alts\", \"123456789\")\n        params[\"id_gutter_alts\"] = dict(zip(\"123456789\", s + \"123456789\"[len(s):]))\n\n        # Create the sub-option \"types\" if needed, and initialize type_gutter params\n        # NB: the gutter for types is not implemented yet, but all needed params are already there\n        if \"types\" not in gutters:\n            gutters[\"types\"] = {}\n        params[\"type_gutter_visibility\"] = gutters[\"types\"].get(\"visibility\", \"auto\")\n\n        # We are sure that gutters is a dict with keys \"ids\" and \"types\" only. Order matters.\n        (params[\"left_gutter\"], params[\"right_gutter\"]) = tuple(gutters.keys())\n\n\ndef main():\n    printer = Printer(quiet=True)\n    run = Runner(sys.argv[1:], printer)\n    try:\n        run()\n    except MocodoError as err:\n        print(str(err), file=sys.stderr)\n        sys.exit(err.errno)\n\n\nif __name__ == \"__main__\": # to be run with `python -m mocodo`\n    main()\n"
  },
  {
    "path": "mocodo/api.py",
    "content": "import argparse\nimport os\nfrom pathlib import Path\nimport shlex\nfrom . import __version__, SCRIPT_DIRECTORY\nfrom .__main__ import Printer, Runner\n\n\ndef mocodo(arg_string=\"\", quiet=True):\n    \"\"\"\n    Simulate the command line `mocodo` as a function, with the same arguments provided as a string.\n    With `quiet=True`, no success messages are printed.\n    In either case, return the printed messages accumulated in a \"\\n\" separated string.\n    \"\"\"\n    parser = argparse.ArgumentParser(add_help=False)\n    parser.add_argument(\"--input\", \"-i\")\n    parser.add_argument(\"--output_dir\")\n    (args, remaining_args) = parser.parse_known_args(shlex.split(arg_string))\n\n    input_path = args.input\n    if not args.input:\n        # No path is provided for the source of the MCD. Fall back to the pristine sandbox.\n        input_path = str(Path(SCRIPT_DIRECTORY, \"resources\", \"pristine_sandbox.mcd\"))\n    \n    output_dir = args.output_dir\n    if not args.output_dir:\n        output_dir = os.getcwd()\n\n    remaining_args.extend([\n        \"--input\", input_path,\n        \"--output_dir\", output_dir,\n    ]) # may override user's provided options\n    printer = Printer(quiet=quiet)\n    try:\n        run = Runner(remaining_args, printer)\n    except SystemExit: # raised by argparse with certain arguments: --help, --version\n        if \"--version\" in remaining_args:\n            return __version__\n        return\n    run()\n    return \"\".join(printer.accumulator)\n"
  },
  {
    "path": "mocodo/argument_parser.py",
    "content": "import argparse\nimport contextlib\nimport gettext\nimport json\nimport locale\nimport os\nimport random\nimport re\nimport importlib\nimport sys\nfrom pathlib import Path\n\nfrom mocodo.tools.string_tools import strip_surrounds\nfrom mocodo.tools.various import invert_dict\n\nfrom . import __version__, SCRIPT_DIRECTORY\nfrom .mocodo_error import MocodoError\n\nclass ArgumentDefaultsRawDescriptionHelpFormatter(\n    argparse.ArgumentDefaultsHelpFormatter,\n    argparse.RawDescriptionHelpFormatter,\n):\n    pass\n\ndef init_localization(language):\n    if not language:\n        if (\n            sys.platform.lower().startswith(\"darwin\")\n            and os.system(\"defaults read -g AppleLanguages > /tmp/languages.txt\") == 0\n        ):\n            language = re.search(r\"\\W*(\\w+)\", Path(\"/tmp/languages.txt\").read_text(encoding=\"utf8\")).group(1)\n        else:\n            try:\n                language = locale.getdefaultlocale()[0][:2]\n            except:\n                language = \"en\"\n    try:\n        path = Path(SCRIPT_DIRECTORY, \"resources\", \"i18n\", f\"messages_{language}.mo\")\n        with path.open(\"rb\") as mo_contents:\n            trans = gettext.GNUTranslations(mo_contents)\n    except IOError:\n        trans = gettext.NullTranslations()\n\n    # Beware that the following line sets the global variable `_`. Using a single underscore\n    # would clash with the gettext alias, EVEN IF THE CODE IS NOT REACHED: the compiler would\n    # consider that _ is a local variable, and shadow the global one, resulting in:\n    # UnboundLocalError: local variable '_' referenced before assignment\n    # Solution : use `__` instead of `_` in any function that uses the gettext alias.\n    trans.install()\n    return language\n\nclass Transformations:\n\n    def __init__(self, language):\n        metadata_path = Path(SCRIPT_DIRECTORY, \"resources\", \"transformations.json\")\n        self.metadata = json.loads(metadata_path.read_text(encoding=\"utf8\"))\n        index_path = Path(SCRIPT_DIRECTORY, \"resources\", \"relation_templates\", \"_index.json\")\n        template_data = json.loads(index_path.read_text(encoding=\"utf8\"))\n        for (stem, d) in template_data.items():\n            if f\"help_{language}\" in d:\n                d[\"help\"] = d.pop(f\"help_{language}\")\n                continue\n            try:\n                d[\"help\"] = d[f\"help_en\"]\n            except KeyError:\n                raise MocodoError(22, _(\"The template '{stem}' doesn't have a help message in language of code '{language}' or 'en'.\").format(stem=stem, language=language)) # fmt: skip\n        self.metadata.update(template_data)\n        self.normalize = invert_dict({k: v[\"aliases\"] for (k, v) in self.metadata.items()})\n        self.normalize.update((k, k) for k in self.metadata)\n        # recreate the dictionary to have it in alphabetical order\n        self.metadata = {k: self.metadata[k] for k in sorted(self.metadata.keys(), key=str.casefold)}\n        self.operations = {\"rw\": [], \"cv\": []}\n        self.op_tk_rewritings = set(k for (k, v) in self.metadata.items() if v.get(\"op_tk\"))\n        self.args_to_delete = [\"-t\", \"-T\", \"--transform\"]\n        self.opt_to_restore = \" \"\n    \n    def extract_transformation_subargs(self, arg):\n        (subopt, __, tail) = arg.partition(\":\")\n        try:\n            subopt = self.normalize[subopt.lower()]\n        except:\n            valid = \", \".join(sorted(self.normalize.keys()))\n            raise MocodoError(45, _(\"The transformation '{subopt}' is not among the possible ones:\\n{valid}.\").format(subopt=subopt, valid=valid)) # fmt: skip\n        result = extract_subargs(f\"{subopt}:{tail}\")\n        category = self.metadata[subopt][\"category\"]\n        self.operations[category].append(result)\n        if category == \"rw\":\n            self.args_to_delete.append(arg)\n        else:\n            self.opt_to_restore = \" -t \"\n        return result\n\n\ndef extract_subargs(arg):\n    (subopt, _, tail) = arg.partition(\":\")\n    subargs = {}\n    for string in filter(None, tail.split(\",\")):\n        subsubopt, equal, subsubarg = string.partition(\"=\")\n        if equal: # subopt:subsubopt= / subopt:subsubopt=subsubarg\n            subsubarg = strip_surrounds(subsubarg, \"''\")\n            subsubarg = strip_surrounds(subsubarg, '\"\"')\n        else: # subopt:subsubopt\n            subsubarg = None\n        subargs[subsubopt] = subsubarg\n    return (subopt, subargs)\n\ndef rate(string):\n    try:\n        value = float(string)\n    except ValueError:\n        msg = f\"The rate {repr(string)} cannot be coerced to float\"\n        raise argparse.ArgumentTypeError(msg)\n    if not (0 <= value <= 1):\n        msg = f\"The rate {repr(string)} is not between 0 and 1\"\n        raise argparse.ArgumentTypeError(msg)\n    return value\n\n\ndef scale(string):\n    try:\n        value = float(string)\n    except ValueError:\n        msg = f\"The scale {repr(string)} cannot be coerced to float\"\n        raise argparse.ArgumentTypeError(msg)\n    if value <= 0:\n        msg = f\"The scale {repr(string)} is not strictly positive\"\n        raise argparse.ArgumentTypeError(msg)\n    return value\n\n\ndef non_negative_integer(string):\n    try:\n        value = int(string)\n    except ValueError:\n        msg = f\"The value {repr(string)} cannot be coerced to an integer\"\n        raise argparse.ArgumentTypeError(msg)\n    if value < 0:\n        msg = f\"The integer {repr(string)} is negative\"\n        raise argparse.ArgumentTypeError(msg)\n    return value\n\n\ndef positive_integer(string):\n    try:\n        value = int(string)\n    except ValueError:\n        msg = f\"The value {repr(string)} cannot be coerced to an integer\"\n        raise argparse.ArgumentTypeError(msg)\n    if value <= 0:\n        msg = f\"The integer {repr(string)} is negative or zero\"\n        raise argparse.ArgumentTypeError(msg)\n    return value\n\ndef parsed_arguments(args):\n    # When mocodo is called from the command line, `args` is just `sys.argv[1:]`.\n    # When it is imported, `args` is a list of strings constructed with shlex.split().\n\n    parser = argparse.ArgumentParser(\n        prog=\"mocodo\",\n        add_help=False,\n        formatter_class=ArgumentDefaultsRawDescriptionHelpFormatter,\n        allow_abbrev=False,\n    )\n\n    mocodo_group = parser.add_argument_group()\n    io_group = parser.add_argument_group()\n    aspect_group = parser.add_argument_group()\n\n    if sys.platform.lower().startswith(\"darwin\"):\n        default_params = {\n            \"encodings\": [\"utf8\", \"macroman\"],\n            \"shapes\": \"copperplate\",\n        }\n    elif sys.platform.lower().startswith(\"win\"):\n        default_params = {\n            \"encodings\": [\"utf8\", \"ISO_8859-15\"],\n            \"shapes\": \"trebuchet\",\n        }\n    else:  # linux\n        default_params = {\n            \"encodings\": [\"utf8\", \"ISO_8859-15\"],\n            \"shapes\": \"serif\",\n        }\n\n    # First, add the arguments that need some preprocessing.\n    # The help messages will be added later, after the localization.\n\n    mocodo_group.add_argument(\"--language\",\n        metavar=\"CODE\",\n        type=str,\n    )\n    language_action = mocodo_group._group_actions[-1]\n    io_group.add_argument(\"--params_path\",\n        metavar=\"PATH\",\n        default=\"params.json\",\n    )\n    params_path_action = io_group._group_actions[-1]\n    io_group.add_argument(\"--input\", \"-i\",\n        metavar=\"PATH\",\n        default=\"\"\n    )\n    input_action = io_group._group_actions[-1]\n    \n    (args, remaining_args) = parser.parse_known_args(args)\n\n    if not args.input:\n        # no input file is specified, use the pristine sandbox\n        source = Path(SCRIPT_DIRECTORY, \"resources\", \"pristine_sandbox.mcd\").read_text(encoding=\"utf8\")\n        args.input = \"sandbox.mcd\"\n        Path(args.input).write_text(source, encoding=\"utf8\")\n    elif not args.input.endswith(\".mcd\"):\n        # the input file has no extension, assume it is a stem\n        args.input += \".mcd\"\n    default_params[\"input\"] = args.input\n\n    if os.path.exists(args.params_path):\n        default_params.update(json.loads(Path(args.params_path).read_text(encoding=\"utf8\")))\n    if not default_params[\"input\"]:\n        default_params[\"input\"] = \"sandbox.mcd\"\n    default_params[\"language\"] = init_localization(default_params.get(\"language\", args.language))\n    default_params.setdefault(\"output_dir\", os.path.dirname(default_params[\"input\"]))\n\n    # Add localized messages.\n\n    mocodo_group.title = _(\"OPTIONS ON MOCODO ITSELF\")\n    io_group.title = _(\"INPUT/OUTPUT\")\n    aspect_group.title = _(\"ASPECT OF THE GRAPHICAL OUTPUT\")\n\n    language_action.help = _(\"override the automatic localization of the messages with the given language code (e.g., 'fr', 'en', ...)\")\n    params_path_action.help = _(\"the path of the parameter file. If omitted, use 'params.json' in the input directory. If non existent, use default parameters.\")\n    input_action.help = _(\"the path of the input file. By default, the output files will be generated in the same directory\")\n\n    parser.description = re.sub(r\"(?m)^(        )\", \"\", _(\"\"\"\n        NAME:\n        Mocodo - An Entity-Relation Diagram Generator.\n\n        DESCRIPTION:\n        Mocodo is an open-source tool for designing and teaching relational databases.\n        It takes as an input a textual description of both entities and associations\n        of an entity-relationship diagram (ERD). It outputs a vectorial drawing in SVG\n        and a relational schema in various formats (SQL, LaTeX, Markdown, etc.).\n\n        NOTE:\n        Each one of the following values is:\n        - explicitely specified by the user as a command line option;\n        - otherwise, retrieved from a file located at --params_path;\n        - otherwise, retrieved from a file named 'params.json' in the input directory;\n        - otherwise, calculated from a default value, possibly dependant of your system.\n    \"\"\")) # fmt: skip\n\n    parser.epilog = re.sub(r\"(?m)^(        )\", \"\", _(\"\"\"\n        SEE ALSO:\n          Online version        https://mocodo.net\n          Source code           https://github.com/laowantong/mocodo\n          Documentation         https://laowantong.github.io/mocodo/doc/fr_refman.html\n          Cheat sheet for -t    https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md\n\n        LICENSE:                MIT\n\n        CONTACT:\n          Author                Aristide Grange\n          Address               Université de Lorraine\n                                Laboratoire LCOMS - UFR MIM\n                                3 rue Augustin Fresnel\n                                57070 METZ Technopôle\n                                France\n          Mail                  <author.full.name>@univ-lorraine.fr\n    \"\"\")) # fmt: skip\n\n    transformations = Transformations(default_params[\"language\"])\n\n    mocodo_group.add_argument(\"--help\",\n        action=\"help\",\n        help=_(\"show this help message, then exit\"),\n    )\n    mocodo_group.add_argument(\"--version\",\n        action=\"version\",\n        version=__version__,\n        help=_(\"display the version number, then exit\"),\n    )\n    mocodo_group.add_argument(\"--restore\",\n        action=\"store_true\",\n        help=_(\"recreate a pristine version of the files 'sandbox.mcd' and 'params.json' in the input directory, then exit\"),\n    )\n\n    io_group.add_argument(\"--lib\",\n        metavar=\"URL\",\n        nargs=\"?\",\n        help=_(\"remote directory to use as fallback when the input file is not found locally\"),\n    )\n    io_group.add_argument(\"--output_dir\",\n        metavar=\"PATH\",\n        help=_(\"the directory of the output files\"),\n    )\n    io_group.add_argument(\"--encodings\",\n        metavar=\"STR\",\n        nargs=\"*\",\n        help=_(\"one or several encodings to be tried successively when reading the input file\"),\n    )\n    io_group.add_argument(\"--svg_to\",\n        choices=[\"png\", \"pdf\"],\n        nargs=\"+\",\n        default=[],\n        help=_(\"generate a PNG or a PDF version of the SVG output (requires CairoSVG)\"),\n    )\n    io_group.add_argument(\"--print_params\",\n        action=\"store_true\",\n        help=_(\"display the contents of the parameter file, then exit\"),\n    )\n    io_group.add_argument(\"--reuse_geo\",\n        action=\"store_true\",\n        help=_(\"reuse the geometry file of the previous execution\"),\n    )\n    io_group.add_argument(\"--uid_suffix\",\n        metavar=\"INT\",\n        type=non_negative_integer,\n        default=0,\n        help=_(\"discriminate between multiple SVG of the same interactive diagram\"),\n    )\n    io_group.add_argument(\"--select\",\n        choices=[\"all\", \"mcd\", \"rw\", \"source\", \"text\", \"code\", \"mocodo\", \"cv\", \"mld\", \"ddl\", \"sql\"],\n        nargs=\"*\",\n        default=argparse.SUPPRESS, # causes no attribute to be added if the argument was not present\n        help=_(\"under Jupyter Notebook, explicitely state the categories of results to display\"),\n    )\n    io_group.add_argument(\"--defer\",\n        metavar=\"STR\",\n        nargs=\"*\",\n        default=argparse.SUPPRESS,\n        help=_(\"use an external web-service to further convert the conversion results into the given graphical formats\"),\n    )\n    io_group.add_argument(\"--mld\",\n        action=\"store_true\",\n        help=_(\"backward compatibility alias for '-t' (with no arguments). Same as '-t markdown' but, under Jupyter Notebook, does not prevent the rendering of the conceptual diagram in the cell output\"),\n    )\n    io_group.add_argument(\"--is_magic\",\n        action=\"store_true\",\n        help=argparse.SUPPRESS, # don't show this argument in the help message\n    )\n    io_group.add_argument(\"--transform\", \"-t\",\n        metavar=\"STR\",\n        nargs=\"*\",\n        type=transformations.extract_transformation_subargs,\n        default=argparse.SUPPRESS,\n        help=_(\"make a new version of the MCD by applying sequentially the given rewriting operations, and/or convert it into the given formats or languages. Under Jupyter Notebook, '-T' respectively replaces the current cell by the textual result, or copies it into the clipboard (pip3 install pyperclip)\"),\n    )\n    io_group.add_argument(\"--Transform\", \"--TRANSFORM\", \"-T\",\n        metavar=\"STR\",\n        nargs=\"*\",\n        type=transformations.extract_transformation_subargs,\n        help=argparse.SUPPRESS, # don't show this argument in the help message\n    )\n    io_group.add_argument(\"--seed\",\n        metavar=\"FLOAT\",\n        nargs=\"?\",\n        type=float,\n        help=_(\"initial value for the random number generator\"),\n    )\n    io_group.add_argument(\"--title\",\n        metavar=\"STR\",\n        default=_(\"Untitled\"),\n        type=str,\n        help=_(\"name of the model, used at various places (file system, database, etc.)\"),\n    )\n\n    aspect_group.add_argument(\"--df\",\n        metavar=\"STR\",\n        type=str,\n        default=\"DF\",\n        help=_(\"the acronym to be circled in a functional dependency\"),\n    )\n    aspect_group.add_argument(\"--card_format\",\n        metavar=\"STR\",\n        type=str,\n        nargs=\"?\",\n        default=\"{min_card},{max_card}\",\n        help=_(\"format string for minimal and maximal cardinalities\"),\n    )\n    aspect_group.add_argument(\"--fk_format\",\n        metavar=\"STR\",\n        type=str,\n        nargs=\"?\",\n        default=\"#{label}\",\n        help=_(\"format string for foreign keys in relational diagram\"),\n    )\n    aspect_group.add_argument(\"--strengthen_card\",\n        metavar=\"STR\",\n        type=str,\n        nargs=\"?\",\n        default=\"_1,1_\",\n        help=_(\"string for relative cardinalities\"),\n    )\n    aspect_group.add_argument(\"--flex\",\n        metavar=\"FLOAT\",\n        type=float,\n        default=0.75,\n        help=_(\"flex straight legs whose cardinalities may collide\"),\n    )\n    aspect_group.add_argument(\"--colors\",\n        metavar=\"STEM_OR_PATH\",\n        default=\"bw\",\n        help=_(\"the color palette to use when generating the drawing. Name (without extension) of a file located in the directory 'colors', or path to a personal file\"),\n    )\n    aspect_group.add_argument(\"--shapes\",\n        metavar=\"STEM_OR_PATH\",\n        help=_(\"specification of the fonts, dimensions, etc. Name (without extension) of a file located in the directory 'shapes', or path to a personal file\"),\n    )\n    aspect_group.add_argument(\"--scale\",\n        metavar=\"RATE\",\n        type=scale,\n        default=1,\n        help=_(\"scale the diagram by the given factor\"),\n    )\n    aspect_group.add_argument(\"--adjust_width\",\n        metavar=\"RATE\",\n        type=scale,\n        default=1,\n        help=_(\"scale all calculated text widths by the given factor\"),\n    )\n    aspect_group.add_argument(\"--detect_overlaps\",\n        action=\"store_true\",\n        help=_(\"raise an error when horizontal or vertical legs overlap\"),\n    )\n    aspect_group.add_argument(\"--no_assoc_ids\",\n        action=\"store_true\",\n        help=_(\"forbid the use of identifiers in associations (according to the Merise standard)\"),\n    )\n    aspect_group.add_argument(\"--gutters\",\n        metavar=\"STR\",\n        nargs=\"+\",\n        type=extract_subargs,\n        default=argparse.SUPPRESS, \n        help=_(\"set the visibility and the contents of the lateral gutters\"),\n    )\n\n    parser.set_defaults(**default_params)\n    params = vars(parser.parse_args(remaining_args))\n    params[\"script_directory\"] = SCRIPT_DIRECTORY\n    params[\"output_name\"] = Path(params[\"output_dir\"]) / Path(params[\"input\"]).stem\n    params[\"rewrite\"] = transformations.operations[\"rw\"]\n    params[\"convert\"] = transformations.operations[\"cv\"]\n    params[\"args_to_delete\"] = transformations.args_to_delete\n    params[\"opt_to_restore\"] = transformations.opt_to_restore\n    params[\"op_tk_rewritings\"] = transformations.op_tk_rewritings\n    params[\"redirect_output\"] = (\"-T\" in remaining_args or \"--Transform\" in remaining_args)\n    params[\"keys_to_hide\"] = [\n        \"keys_to_hide\",\n        \"script_directory\",\n        \"output_name\",\n        \"rewrite\",\n        \"convert\",\n        \"args_to_delete\",\n        \"opt_to_restore\",\n        \"op_tk_rewritings\",\n        \"redirect_output\",\n        \"params_path\",\n        \"Transform\",\n        \"is_magic\",\n        \"print_params\",\n        \"reuse_geo\",\n        \"input\",\n    ]\n\n    lib = \"https://mocodo.net/web/lib\"\n    if params[\"lib\"]:\n        parse_url = importlib.import_module(\"urllib.parse\").urlparse\n        if parse_url(params[\"lib\"]).scheme:\n            lib = params[\"lib\"]\n    params[\"lib\"] = lib\n\n    if params[\"seed\"] is not None:\n        random.seed(params[\"seed\"])\n    \n    with contextlib.suppress(UnicodeDecodeError, AttributeError):\n        params[\"title\"] = params[\"title\"].decode(\"utf8\")\n    \n    return params\n"
  },
  {
    "path": "mocodo/association.py",
    "content": "import re\nfrom .attribute import *\nfrom .leg import *\nfrom .mocodo_error import MocodoError\nfrom .tools.string_tools import rstrip_digit_or_underline, raw_to_bid\n\nclass Association:\n\n    df_counter = 0\n\n    @classmethod\n    def reset_df_counter(cls):\n        cls.df_counter = 0\n\n    def __init__(self, clause, **params):\n        self.source = clause[\"source\"]\n        self.raw_name = clause[\"name\"]\n        self.bid = raw_to_bid(self.raw_name)\n        # A protected association results in a table, even if this association is a DF.\n        self.is_protected = (clause.get(\"box_def_prefix\") == \"+\")\n        if clause.get(\"box_def_prefix\") == \"-\":\n            self.calculate_size = self.calculate_size_when_invisible\n            self.description = lambda *ignored: []\n            self.is_invisible = True\n        else:\n            self.calculate_size = self.calculate_size_when_visible\n            self.description = self.description_when_visible\n            self.is_invisible = False\n        self.peg_count = 0\n        self.attributes = []\n        for attr in clause.get(\"attrs\", []):\n            if attr.get(\"attribute_label\", \"\") == \"\":\n                self.attributes.append(PhantomAttribute(attr))\n            elif attr.get(\"id_mark\", \"\") == \"_\":\n                if params.get(\"no_assoc_ids\"):\n                    raise MocodoError(52, _('The association \"{name}\" cannot have an identifier.').format(name=self.raw_name))\n                self.attributes.append(StrongAttribute(attr))\n            else:\n                self.attributes.append(SimpleAssociationAttribute(attr))\n        df_label = params.get(\"df\", \"DF\")\n        if re.match(fr\"^{df_label.upper()}\\d*$\", self.raw_name.upper()):\n            self.name_view = df_label # strip all digits suffixing a DF name\n            self.bid = f\"{df_label}{Association.df_counter}\"\n            Association.df_counter += 1\n            self.kind = \"df\"\n        else:\n            self.name_view = rstrip_digit_or_underline(self.raw_name)\n            legs = clause[\"legs\"]\n            # A \"peg\" is a leg that is prefixed by a \"/\" character.\n            for leg in legs:\n                if leg.get(\"card_prefix\") == \"/\":\n                    self.peg_count += 1\n            if self.peg_count > 0:\n                if len(legs) < 3:\n                    raise MocodoError(51, _('The association \"{name}\" should have at least 3 legs to become a cluster.').format(name=self.raw_name))\n                self.kind = \"cluster\"\n            else:\n                self.kind = \"association\"\n        self.set_view_strategies()\n        entity_raw_names = [leg[\"entity\"] for leg in clause[\"legs\"]]\n        self.legs = []\n        for leg_clause in clause[\"legs\"]:\n            entity_raw_name = leg_clause[\"entity\"]\n            rank = leg_clause[\"rank\"]\n            leg = Leg(self, leg_clause, **params)\n            mutiplicity = entity_raw_names.count(entity_raw_name)\n            rank = entity_raw_names[:rank].count(entity_raw_name)\n            leg.set_spin_strategy(0 if mutiplicity == 1 else 2 * rank / (mutiplicity - 1) - 1)\n            self.legs.append(leg)\n        if self.kind == \"cluster\":\n            candidate_groups = iter([0] + list(range(self.peg_count - 1, 0, -1)))\n            for leg in self.legs:\n                if leg.kind == \"cluster_peg\":\n                    group_number = str(next(candidate_groups))\n                    for other_leg in self.legs:\n                        if other_leg is leg:\n                            continue\n                        other_leg.append_candidate_group(group_number)\n        elif self.kind == \"df\":\n            for leg in self.legs:\n                if leg.card.endswith((\"1\", \"X\")):\n                    break\n            else:\n                raise MocodoError(37, _('An association named \"{df_label}\" must have at least one leg with a maximal cardinality of 1.').format(df_label=df_label)) # fmt: skip\n\n    def get_note_data(self):\n        result = {}\n        for leg in self.legs:\n            result[leg.lid] = {\n                \"subject\": leg.entity_bid,\n                \"predicate\": self.name_view,\n                \"min\": leg.card[:1],\n                \"max\": leg.card[-1:],\n                \"objects\": [other.entity_bid for other in self.legs if other is not leg],\n                \"note\": leg.note,\n            }\n        return result\n\n    def register_boxes(self, boxes):\n        self.boxes = boxes\n\n    def register_mcd_has_cif(self, mcd_has_cif):\n        self.mcd_has_cif = mcd_has_cif\n        for leg in self.legs:\n            leg.register_mcd_has_cif(mcd_has_cif)\n\n    def calculate_size_when_invisible(self, *ignored):\n        self.w = 0\n        self.h = 0\n    \n    def calculate_size_when_visible(self, style, get_font_metrics):\n        cartouche_font = get_font_metrics(style[\"association_cartouche_font\"])\n        self.get_cartouche_string_width = cartouche_font.get_pixel_width\n        self.cartouche_height = cartouche_font.get_pixel_height()\n        attribute_font = get_font_metrics(style[\"association_attribute_font\"])\n        self.attribute_height = attribute_font.get_pixel_height()\n        self.calculate_size_depending_on_kind(style, get_font_metrics)\n        self.w += self.w % 2\n        self.h += self.h % 2\n        for leg in self.legs:\n            leg.calculate_size(style, get_font_metrics)\n\n    def register_center(self, geo):\n        self.cx = geo[\"cx\"][self.bid]\n        self.cy = geo[\"cy\"][self.bid]\n        self.l = self.cx - self.w // 2\n        self.r = self.cx + self.w // 2\n        self.t = self.cy - self.h // 2\n        self.b = self.cy + self.h // 2\n\n    def set_view_strategies(self):\n\n        def calculate_size_when_df(style, get_font_metrics):\n            self.w = self.h = max(\n                style[\"round_rect_margin_width\"] * 2 + self.get_cartouche_string_width(self.name_view),\n                style[\"round_rect_margin_width\"] * 2 + self.cartouche_height\n            )\n\n        def calculate_size_when_default(style, get_font_metrics):\n            for attribute in self.attributes:\n                attribute.calculate_size(style, get_font_metrics)\n            cartouche_and_attribute_widths = [a.w for a in self.attributes] + [self.get_cartouche_string_width(self.name_view)]\n            self.w = 2 * style[\"round_rect_margin_width\"] + max(cartouche_and_attribute_widths)\n            self.h = max(1, len(self.attributes)) * (self.attribute_height + style[\"line_skip_height\"]) \\\n                - style[\"line_skip_height\"] \\\n                + 2 * style[\"rect_margin_height\"] \\\n                + 2 * style[\"round_rect_margin_height\"] \\\n                + self.cartouche_height\n            self.w += self.w % 2\n            self.h += self.h % 2\n\n        def description_when_df(style):\n            return [\n                (\n                    \"circle\",\n                    {\n                        \"stroke_depth\": style[\"box_stroke_depth\"],\n                        \"stroke_color\": style[\"association_stroke_color\"],\n                        \"color\": style[\"association_cartouche_color\"],\n                        \"cx\": self.cx,\n                        \"cy\": self.cy,\n                        \"r\": self.w // 2,\n                    },\n                ),\n                (\n                    \"text\",\n                    {\n                        \"text\": self.name_view,\n                        \"text_color\": style['association_cartouche_text_color'],\n                        \"x\": self.l + style[\"round_rect_margin_width\"],\n                        \"y\": self.t + style[\"round_rect_margin_height\"] + style[\"df_text_height_ratio\"] * self.cartouche_height,\n                        \"family\": style[\"association_cartouche_font\"][\"family\"],\n                        \"size\": style[\"association_cartouche_font\"][\"size\"],\n                    },\n                )\n            ]\n        \n        def optional_description_for_cluster(style):\n            if self.kind != \"cluster\" or self.mcd_has_cif:\n                return []\n            if len(self.legs) > 3:\n                # The calculation of a hull with more than 3 legs is not implemented yet.\n                return []\n            result = []\n            tweak = 1\n            for (i, leg) in enumerate(self.legs):\n                if leg.kind == \"cluster_peg\":\n                    other_legs = self.legs[:i] + self.legs[i+1:]\n                    e1 = other_legs[0].entity # the first entity of the other legs\n                    e2 = other_legs[-1].entity # the last one, either the same as e1 or not\n                    points = self.cluster_hull(e1, e2, style[\"card_margin\"] * tweak)\n                    if not points: # complex hulls are not implemented yet\n                        continue\n                    path = points_to_rounded_path(points, style[\"round_corner_radius\"] // 2)\n                    result.extend([\n                        (\n                            \"polygon\",\n                            {\n                                \"path\": path,\n                                \"stroke_color\": None,\n                                \"stroke_depth\": 0,\n                                \"color\": style[\"entity_color\"],\n                                \"opacity\": 0.3 / self.peg_count,\n                            },\n                        ),\n                        (\n                            \"dot_polygon\",\n                            {\n                                \"path\": path,\n                                \"stroke_color\": style['entity_stroke_color'],\n                                \"stroke_depth\": style[\"box_stroke_depth\"],\n                                \"color\": None,\n                                \"dash_gap\": style[\"dash_width\"],\n                            },\n                        )\n                    ])\n                    tweak += 1\n            return result\n\n        def description_when_default(style):\n            result = []\n            result.extend(optional_description_for_cluster(style))\n            if self.is_protected:\n                result.append(\n                    (\n                        \"round_rect\",\n                        {\n                            \"x\": self.l - style[\"card_margin\"] * 2,\n                            \"y\": self.t - style[\"card_margin\"] * 2,\n                            \"w\": self.w + style[\"card_margin\"] * 4,\n                            \"h\": self.h + style[\"card_margin\"] * 4,\n                            \"radius\": style[\"round_corner_radius\"] // 2,\n                            \"stroke_color\": style['entity_stroke_color'] + \"55\", # alpha channel\n                            \"stroke_depth\": style[\"box_stroke_depth\"],\n                            \"color\": style[\"entity_color\"] + \"55\", # alpha channel\n                        },\n                    )\n                )\n            x = self.l\n            y = self.t\n            w = self.w\n            h = self.attribute_height + style[\"round_rect_margin_height\"] + style[\"rect_margin_height\"]\n            r = style[\"round_corner_radius\"]\n            result.append(\n                (\n                    \"upper_round_rect\",\n                    {\n                        \"x0\": x + w - r,\n                        \"y0\": y,\n                        \"y1\": y + h,\n                        \"y2\": y + r,\n                        \"w\": w,\n                        \"r\": r,\n                        \"color\": style['association_cartouche_color'],\n                        \"stroke_color\": style['association_cartouche_color'],\n                        \"stroke_depth\": 0,\n                    },\n                )\n            )\n            y = self.t + self.attribute_height + style[\"round_rect_margin_height\"] + style[\"rect_margin_height\"]\n            h = self.h - self.attribute_height - style[\"round_rect_margin_height\"] - style[\"rect_margin_height\"]\n            result.append(\n                (\n                    \"lower_round_rect\",\n                    {\n                        \"x0\": x + w,\n                        \"y0\": y,\n                        \"y1\": h - r,\n                        \"x1\": x + r,\n                        \"w\": w,\n                        \"r\": r,\n                        \"color\": style['association_color'],\n                        \"stroke_color\": style['association_color'],\n                        \"stroke_depth\": 0,\n                    },\n                )\n            )\n            result.append(\n                (\n                    \"round_rect\",\n                    {\n                        \"x\": self.l,\n                        \"y\": self.t,\n                        \"w\": self.w,\n                        \"h\": self.h,\n                        \"radius\": r,\n                        \"color\": style['transparent_color'],\n                        \"stroke_color\": style['association_stroke_color'],\n                        \"stroke_depth\": style[\"box_stroke_depth\"],\n                    },\n                )\n            )\n            result.append(\n                (\n                    \"line\",\n                    {\n                        \"x0\": self.l,\n                        \"y0\": self.t + self.attribute_height + style[\"round_rect_margin_height\"] + style[\"rect_margin_height\"],\n                        \"x1\": self.r,\n                        \"y1\": self.t + self.attribute_height + style[\"round_rect_margin_height\"] + style[\"rect_margin_height\"],\n                        \"stroke_color\": style['association_stroke_color'],\n                        \"stroke_depth\": style[\"inner_stroke_depth\"],\n                    },\n                )\n            )\n            result.append(\n                (\n                    \"text\",\n                    {\n                        \"text\": self.name_view,\n                        \"text_color\": style['association_cartouche_text_color'],\n                        \"x\": self.cx - self.get_cartouche_string_width(self.name_view) // 2,\n                        \"y\": self.t + style[\"rect_margin_height\"] + style[\"cartouche_text_height_ratio\"] * self.cartouche_height,\n                        \"family\": style[\"association_cartouche_font\"][\"family\"],\n                        \"size\": style[\"association_cartouche_font\"][\"size\"],\n                    },\n                ),\n            )\n            x = self.cx - self.w // 2 + style[\"round_rect_margin_width\"]\n            dx = 0\n            dy = style[\"round_rect_margin_height\"] + self.cartouche_height + 2 * style[\"rect_margin_height\"] - self.h // 2\n            for attribute in self.attributes:\n                result.extend(attribute.description(style, x, self.cy, dx, dy))\n                dy += self.attribute_height + style[\"line_skip_height\"]\n            return result\n\n        if self.kind == \"df\":\n            self.calculate_size_depending_on_kind = calculate_size_when_df\n            self.description_depending_on_kind = description_when_df\n        else:\n            self.calculate_size_depending_on_kind = calculate_size_when_default\n            self.description_depending_on_kind = description_when_default\n\n    def description_when_visible(self, style, geo):\n        self.saved_card_description = []\n        result = []\n        result.append((\"comment\", {\"text\": f\"Association {self.bid}\"}))\n        result.append(\n            (\n                \"begin_component\",\n                {\n                    \"page\": self.page,\n                    \"visibility\": \"hidden\" if self.page else \"visible\",\n                }\n            )\n        )\n        result.extend(self.leg_descriptions(style, geo))\n        result.append((\"begin_group\", {}))\n        result.extend(self.description_depending_on_kind(style))\n        result.append((\"end\", {}))\n        result.extend(self.saved_card_description) # need to be displayed after the clusters for more readability\n        result.append((\"end\", {}))\n        return result\n\n    def leg_descriptions(self, style, geo):\n        result = []\n        for leg in self.legs:\n            result.extend(leg.description(style, geo))\n            self.saved_card_description.extend(leg.saved_card_description)\n        return result\n\n    def cluster_hull(self, e1, e2, card_margin):\n        x_min = min(box.l for box in (self, e1, e2))\n        y_min = min(box.t for box in (self, e1, e2))\n        x_max = max(box.r for box in (self, e1, e2))\n        y_max = max(box.b for box in (self, e1, e2))\n        x = x_min - card_margin // 2\n        y = y_min - card_margin // 2\n        w = x_max - x_min + card_margin\n        h = y_max - y_min + card_margin\n\n        x1_min = min(box.l for box in (self, e1))\n        y1_min = min(box.t for box in (self, e1))\n        x1_max = max(box.r for box in (self, e1))\n        y1_max = max(box.b for box in (self, e1))\n        x1 = x1_min - card_margin // 2\n        y1 = y1_min - card_margin // 2\n        w1 = x1_max - x1_min + card_margin\n        h1 = y1_max - y1_min + card_margin\n        \n        x2_min = min(box.l for box in (self, e2))\n        y2_min = min(box.t for box in (self, e2))\n        x2_max = max(box.r for box in (self, e2))\n        y2_max = max(box.b for box in (self, e2))\n        x2 = x2_min - card_margin // 2\n        y2 = y2_min - card_margin // 2\n        w2 = x2_max - x2_min + card_margin\n        h2 = y2_max - y2_min + card_margin\n\n        e1_same_row = e1.t <= self.t < self.b <= e1.b or self.t <= e1.t < e1.b <= self.b\n        e2_same_row = e2.t <= self.t < self.b <= e2.b or self.t <= e2.t < e2.b <= self.b\n        e1_same_col = e1.l <= self.l < self.r <= e1.r or self.l <= e1.l < e1.r <= self.r\n        e2_same_col = e2.l <= self.l < self.r <= e2.r or self.l <= e2.l < e2.r <= self.r\n        if e1_same_row and e2_same_row or e1_same_col and e2_same_col:\n            return [x, y, x+w, y, x+w, y+h, x, y+h]\n        elif e1_same_row and e2_same_col:\n            if e1.cx < self.cx:\n                if e2.cy < self.cy:\n                    #   2\n                    # 1 a\n                    return [x, y1, x2, y1, x2, y, x+w, y, x+w, y+h, x, y+h]\n                else:\n                    # 1 a\n                    #   2\n                    return [x, y, x+w, y, x+w, y+h, x2, y+h, x2, y1+h1, x, y1+h1]\n            else:\n                if e2.cy < self.cy:\n                    # 2\n                    # a 1\n                    return [x, y, x2+w2, y, x2+w2, y1, x+w, y1, x+w, y+h, x, y+h]\n                else:\n                    # a 1\n                    # 2\n                    return [x, y, x+w, y, x+w, y1+h1, x2+w2, y1+h1, x2+w2, y+h, x, y+h]\n        elif e2_same_row and e1_same_col:\n            if e2.cx < self.cx:\n                if e1.cy < self.cy:\n                    #   1\n                    # 2 a\n                    return [x, y2, x1, y2, x1, y, x+w, y, x+w, y+h, x, y+h]\n                else:\n                    # 2 a\n                    #   1\n                    return [x, y, x+w, y, x+w, y+h, x1, y+h, x1, y2+h2, x, y2+h2]\n            else:\n                if e1.cy < self.cy:\n                    # 1\n                    # a 2\n                    return [x, y, x1+w1, y, x1+w1, y2, x+w, y2, x+w, y+h, x, y+h]\n                else:\n                    # a 2\n                    # 1\n                    return [x, y, x+w, y, x+w, y2+h2, x1+w1, y2+h2, x1+w1, y+h, x, y+h]\n        else:\n            return []\n\ndef points_to_rounded_path(points, r):\n    result = []\n    points.extend(points[:6])\n    for i in range(0, len(points) - 6, 2):\n        (x1, y1, x2, y2, x3, y3) = points[i:i+6]\n        if x1 < x2 and y2 > y3:\n            #   3\n            # 1 2\n            (x2, c, dx, dy) = (x2 - r, 0, r, -r)\n        elif x1 < x2 and y2 < y3:\n            # 1 2\n            #   3\n            (x2, c, dx, dy) = (x2 - r, 1, r, r)\n        elif x1 > x2 and y2 < y3:\n            # 2 1\n            # 3\n            (x2, c, dx, dy) = (x2 + r, 0, -r, r)\n        elif x1 > x2 and y2 > y3:\n            # 3\n            # 2 1\n            (x2, c, dx, dy) = (x2 + r, 1, -r, -r)\n        elif y1 < y2 and x2 > x3:\n            #   1\n            # 3 2\n            (y2, c, dx, dy) = (y2 - r, 1, -r, r)\n        elif y1 < y2 and x2 < x3:\n            # 1\n            # 2 3\n            (y2, c, dx, dy) = (y2 - r, 0, r, r)\n        elif y1 > y2 and x2 < x3:\n            # 2 3\n            # 1\n            (y2, c, dx, dy) = (y2 + r, 1, r, -r)\n        elif y1 > y2 and x2 > x3:\n            # 3 2\n            #   1\n            (y2, c, dx, dy) = (y2 + r, 0, -r, -r)\n        result.append(f\"L{x2} {y2} a{r} {r} 0 0 {c} {dx} {dy}\")\n    result[0:0] = [f\"M{x2+dx} {y2+dy}\"]\n    return \" \".join(result)\n"
  },
  {
    "path": "mocodo/attribute.py",
    "content": "from .tools.string_tools import raw_to_bid\n\nclass Attribute:\n\n    # The following three static attributes will be updated by Mcd.add_attributes() method.\n    # They are here to simplify the writing of some tests.\n    id_gutter_strong_string = \"ID\"\n    id_gutter_weak_string = \"id\"\n    id_gutter_alts = dict(zip(\"123456789\", \"123456789\"))\n\n    def __init__(self, attribute):\n        self.label = attribute.get(\"attribute_label\", \"\")\n        self.label_view = self.label # may be updated in self.register_foreign_key_status()\n        self.rank = attribute[\"rank\"]\n        self.datatype = attribute.get(\"datatype\", \"\")\n        self.primary_entity_bid = raw_to_bid(attribute.get(\"that_table\", \"\"))\n        self.id_groups = set(attribute.get(\"id_groups\", \"\").replace(\"0\", \"\"))\n        self.id_text =  \" \".join(map(self.id_gutter_alts.get, sorted(self.id_groups)))\n        self.id_gutter_width = 0  # For anything but entities\n\n    def register_foreign_key_status(self, attribute, fk_format):\n        that_table = attribute.get(\"that_table\")\n        if not that_table:\n            return\n        self.primary_key_label = attribute.get(\"that_table_attribute_label\")\n        self.label_view = fk_format.format(label=self.label)\n\n    def calculate_size(self, style, get_font_metrics):\n        self.attribute_font = style[self.font_type]\n        self.font = get_font_metrics(self.attribute_font)\n        self.w = self.font.get_pixel_width(self.label_view)\n        self.h = self.font.get_pixel_height()\n        self.id_width = self.font.get_pixel_width(self.id_text)\n\n    def set_id_gutter_width(self, id_gutter_width):\n        self.id_gutter_width = id_gutter_width\n\n    def description(self, style, x, y, dx, dy):\n        result = [\n            (\n                \"text\",\n                {\n                    \"x\": x + dx,\n                    \"y\": y + round(dy + style[\"attribute_text_height_ratio\"] * self.h, 1),\n                    \"text\": self.label_view,\n                    \"text_color\": style[f\"{self.box_type}_attribute_text_color\"],\n                    \"family\": self.attribute_font[\"family\"],\n                    \"size\": self.attribute_font[\"size\"],\n                }\n            )\n        ]\n        if self.id_gutter_width:\n            result.append(\n                (\n                    \"text\",\n                    {\n                        \"x\": x + (self.id_gutter_width - self.id_width) // 2 - style[\"rect_margin_width\"],\n                        \"y\": y + round(dy + style[\"attribute_text_height_ratio\"] * self.h, 1),\n                        \"text\": self.id_text,\n                        \"text_color\": style[f\"{self.box_type}_attribute_text_color\"],\n                        \"family\": self.attribute_font[\"family\"],\n                        \"size\": self.attribute_font[\"size\"],\n                    }\n                )\n            )\n        return result\n\nclass SimpleEntityAttribute(Attribute):\n\n    def __init__(self, attribute):\n        Attribute.__init__(self, attribute)\n        self.box_type = \"entity\"\n        self.font_type = \"entity_attribute_font\"\n        self.kind = \"simple\"\n\n\nclass SimpleAssociationAttribute(Attribute):\n\n    def __init__(self, attribute):\n        Attribute.__init__(self, attribute)\n        self.box_type = \"association\"\n        self.font_type = \"association_attribute_font\"\n        self.kind = \"simple_association\"\n\n\nclass IdentifierAttribute(Attribute):\n\n    def __init__(self, attribute):\n        Attribute.__init__(self, attribute)\n        self.box_type = \"entity\"\n        self.font_type = \"entity_attribute_font\"\n        self.id_groups.add(\"0\")\n\n    def calculate_size(self, *args):\n        Attribute.calculate_size(self, *args)\n\nclass StrongAttribute(IdentifierAttribute):\n\n    def __init__(self, attribute):\n        IdentifierAttribute.__init__(self, attribute)\n        self.id_text = f\"{self.id_text} {self.id_gutter_strong_string}\".lstrip()\n        self.kind = \"strong\"\n\n    def description(self, style, x, y, dx, dy):\n        return IdentifierAttribute.description(self, style, x, y, dx, dy) + [\n            (\n                \"line\",\n                {\n                    \"x0\": x + dx,\n                    \"y0\": y + dy + self.h + style[\"underline_skip_height\"],\n                    \"x1\": x + dx + self.w,\n                    \"y1\": y + dy + self.h + style[\"underline_skip_height\"],\n                    \"stroke_depth\": style[\"underline_depth\"],\n                    \"stroke_color\": style['entity_attribute_text_color'],\n                }\n            )\n        ]\n\nclass WeakAttribute(IdentifierAttribute):\n\n    def __init__(self, attribute):\n        IdentifierAttribute.__init__(self, attribute)\n        self.id_text = f\"{self.id_text} {self.id_gutter_weak_string}\".lstrip()\n        self.kind = \"weak\"\n\n    def description(self, style, x, y, dx, dy):\n        return IdentifierAttribute.description(self, style, x, y, dx, dy) + [\n            (\n                \"dash_line\",\n                {\n                    \"x0\": x + dx,\n                    \"y0\": y + dy + self.h + style[\"underline_skip_height\"],\n                    \"x1\": x + dx + self.w,\n                    \"y1\": y + dy + self.h + style[\"underline_skip_height\"],\n                    \"dash_width\": style[\"dash_width\"],\n                    \"stroke_depth\": style[\"underline_depth\"],\n                    \"stroke_color\": style['entity_attribute_text_color'],\n                }\n            )\n        ]\n\n\nclass PhantomAttribute(Attribute):\n    \n    def __init__(self, attribute):\n        Attribute.__init__(self, attribute)\n        self.kind = \"phantom\"\n        self.font_type = \"entity_attribute_font\" # dummy\n    \n    def description(self, *_):\n        return []\n\n\nclass InheritanceAttribute(Attribute):\n\n    def __init__(self, attribute):\n        Attribute.__init__(self, attribute)\n        self.kind = \"inheritance\"\n"
  },
  {
    "path": "mocodo/common.py",
    "content": "import json\nimport numbers\nimport sys\nfrom pathlib import Path\nimport contextlib\nimport importlib\n\nfrom .mocodo_error import MocodoError\n\n\ndef contract_path(path):\n    \"\"\"\n    Contract a full path to one with ~, if it's under the user's home directory.\n    \"\"\"\n    home = str(Path.home())\n    absolute_path = str(Path(path).resolve())\n    if absolute_path.startswith(home):\n        return absolute_path.replace(home, '~', 1)\n    else:\n        return absolute_path\n\n\nclass Printer:\n\n    def __init__(self, quiet=False):\n        self.accumulator = []\n        if quiet:\n            self.write = self.accumulator.append\n        else:\n            self.write = self.safe_print_for_PHP\n\n    def safe_print_for_PHP(self, s):\n        \"\"\" It seems that when called from PHP, Python is unable to guess correctly\n            the encoding of the standard output. \"\"\"\n        try:\n            print(s, file=sys.stdout)\n        except UnicodeEncodeError:\n            print(s.encode(\"utf8\"), file=sys.stdout)\n\n\nclass Common:\n\n    def __init__(self, params):\n        self.params = params\n\n    def output_success_message(self, path):\n        return _('Output file \"{filename}\" successfully generated.').format(filename=contract_path(path))\n\n    def update_source(self, source):\n        path = Path(f\"{self.params['output_name']}.mcd\")\n        path.write_text(source, encoding=\"utf8\")\n        return _('Source file \"{filename}\" successfully updated.').format(filename=contract_path(path))\n\n    def load_input_file(self):\n        # Try to read the file locally.\n        path = Path(self.params[\"input\"])\n        if path.is_file():\n            for encoding in self.params[\"encodings\"]:\n                with contextlib.suppress(UnicodeError):\n                    self.encoding = encoding\n                    return path.read_text(encoding=encoding).replace('\"', '')\n            raise MocodoError(5, _('Unable to read \"{filename}\" with any of the following encodings: \"{encodings}\".').format(filename=self.params[\"input\"], encodings= \", \".join(self.params[\"encodings\"]))) # fmt: skip\n        # The file is not found locally, try to retrieve it from the server.\n        self.encoding = self.params[\"encodings\"][0]\n        requests = importlib.import_module(\"requests\")\n        with contextlib.suppress(requests.exceptions.ConnectionError):\n            response = requests.get(f\"{self.params['lib']}/{path.name}\")\n            if response.status_code == 200:\n                response.encoding = 'utf-8'  # Force the response encoding to UTF-8\n                source = response.text.replace('\"', '')\n                # Save the file locally.\n                path.parent.mkdir(parents=True, exist_ok=True)\n                path.write_text(source, encoding=self.encoding)\n                return source\n        # The file is not found locally nor on the server.\n        raise MocodoError(2, _('The file \"{input}\" doesn\\'t exist.').format(input=path))  # fmt: skip\n\n    def load_style(self):\n        \n        def load_by_name(name):\n            path = Path(self.params[name]).with_suffix(\".json\")\n            if path.is_file():\n                try:\n                    return json.loads(path.read_text(encoding=\"utf8\"))\n                except:\n                    raise MocodoError(3, _('Problem with \"{name}\" file \"{path}\".').format(name=name, path=path)) # fmt: skip\n            path = Path(self.params[\"script_directory\"], \"resources\", name, path)\n            try:\n                return json.loads(path.read_text(encoding=\"utf8\"))\n            except:\n                raise MocodoError(3, _('Problem with \"{name}\" file \"{path}\".').format(name=name, path=path)) # fmt: skip\n        \n        def may_apply_scaling(shapes):\n            if self.params[\"scale\"] == 1:\n                return\n            scale = self.params[\"scale\"]\n            for key in shapes:\n                if key.endswith(\"font\"):\n                    shapes[key][\"size\"] = shapes[key][\"size\"] * scale\n                elif not key.endswith(\"ratio\") and isinstance(shapes[key], numbers.Number):\n                    shapes[key] *= scale\n        \n        def ensure_margins_are_integer(shapes):\n            # Some nasty failures are known to occur otherwise.\n            for key in shapes:\n                if \"margin\" in key:\n                    shapes[key] = int(shapes[key] + 0.5)\n            \n        style = {}\n        style.update(load_by_name(\"colors\"))\n        shapes = load_by_name(\"shapes\")\n        may_apply_scaling(shapes)\n        ensure_margins_are_integer(shapes)\n        style.update(shapes)\n        style[\"transparent_color\"] = None\n        return style\n"
  },
  {
    "path": "mocodo/constraint.py",
    "content": "import re\n\nfrom .attribute import *\nfrom .leg import ConstraintLeg\nfrom .tools.string_tools import is_a_description, raw_to_bid\n\nclass Constraint:\n\n    counter = 0\n\n    @classmethod\n    def reset_counter(cls):\n        cls.counter = 0\n\n    def __init__(self, clause):\n        self.source = clause[\"source\"]\n        self.raw_name = clause.get(\"name\", \"Anonymous\")\n        self.name_view = clause.get(\"name\", \"\")\n        Constraint.counter += 1\n        self.bid = f'{raw_to_bid(self.raw_name)}_CONSTRAINT_#{Constraint.counter}'\n        self.note = clause.get(\"constraint_note\")\n        self.legs = []\n        for target in clause.get(\"constraint_targets\", []):\n            self.legs.append(ConstraintLeg(self, target.get(\"constraint_leg\", \"\"), target[\"name\"]))\n        if self.legs:\n            self.coords = clause.get(\"constraint_coords\", [])\n        else:\n            # When there is neither coord nor target, the constraint is placed at the top right corner\n            # which is obviously undesirable, forcing the user to specify at least one coord.\n            self.coords = clause.get(\"constraint_coords\", [0, 0])\n        self.kind= \"constraint\"\n\n    def register_boxes(self, boxes):\n        self.boxes = boxes\n\n    def calculate_size(self, style, get_font_metrics):\n        constraint_font = get_font_metrics(style[\"constraint_font\"])\n        self.get_constraint_string_width = constraint_font.get_pixel_width\n        self.constraint_height = constraint_font.get_pixel_height()\n        if self.name_view.strip():\n            size = max(self.get_constraint_string_width(self.name_view), self.constraint_height)\n        else:\n            size = self.get_constraint_string_width(\"W\") * len(self.name_view)\n        self.w = self.h = style[\"constraint_margin\"] * 2 + size\n\n    def register_center(self, geo):\n        self.page_width = geo[\"width\"]\n        self.page_height = geo[\"height\"]\n        if self.coords:\n            # The center of a constraint is either at a certain ratio of the width and height of the\n            # page, or aligned with the center of a box.\n            if isinstance(self.coords[0], (float, int)):\n                self.cx = self.coords[0] * self.page_width // 100\n            else:\n                self.cx = geo[\"cx\"][raw_to_bid(self.coords[0])]\n            if isinstance(self.coords[1], (float, int)):\n                self.cy = self.coords[1] * self.page_height // 100\n            else:\n                self.cy = geo[\"cy\"][raw_to_bid(self.coords[1])]\n        else:\n            # The center of a constraint is the barycenter of the centers of its boxes\n            self.cx = sum(geo[\"cx\"][leg.bid] for leg in self.legs) / len(self.legs)\n            self.cy = sum(geo[\"cy\"][leg.bid] for leg in self.legs) / len(self.legs)\n        self.l = self.cx - self.w // 2\n        self.r = self.cx + self.w // 2\n        self.t = self.cy - self.h // 2\n        self.b = self.cy + self.h // 2\n\n    def _description(self, style):\n        return [\n            (\n                \"circle_with_note\" if is_a_description(self.note) else \"circle\",\n                {\n                    \"stroke_depth\": style[\"constraint_stroke_depth\"],\n                    \"stroke_color\": style[\"constraint_stroke_color\"],\n                    \"color\": style[\"constraint_background_color\"],\n                    \"cx\": self.cx,\n                    \"cy\": self.cy,\n                    \"r\": self.w // 2,\n                    \"note\": self.note,\n                },\n            ),\n            (\n                \"text_above_note\",\n                {\n                    \"text\": self.name_view,\n                    \"text_color\": style['constraint_text_color'],\n                    \"x\": self.cx - self.get_constraint_string_width(self.name_view) / 2,\n                    \"y\": self.cy + self.constraint_height * style[\"constraint_text_height_tweak\"],\n                    \"family\": style[\"card_font\"][\"family\"],\n                    \"size\": style[\"card_font\"][\"size\"],\n                },\n            ),\n        ]\n\n    def description(self, style, geo):\n        result = []\n        result.append((\"comment\", {\"text\": f\"Constraint {self.bid}\"}))\n        result.append(\n            (\n                \"begin_component\",\n                {\n                    \"page\": self.page,\n                    \"visibility\": \"hidden\" if self.page else \"visible\",\n                }\n            )\n        )\n        result.extend(self.leg_descriptions(style, geo))\n        result.append((\"begin_group\", {}))\n        result.extend(self._description(style))\n        result.append((\"end\", {}))\n        result.append((\"end\", {}))\n        return result\n\n    def leg_descriptions(self, style, geo):\n        result = []\n        for leg in self.legs:\n            result.extend(leg.description(style, geo))\n        return result\n\n    def invert_coords_horizontal_mirror(self):\n        if self.coords and isinstance(self.coords[1], (float, int)):\n            self.coords[1] = 100 - self.coords[1]\n            self.source = re.sub(r\"(.+):.+\", fr\"\\1: {self.coords[0]}, {self.coords[1]}\", self.source)\n    \n    def invert_coords_vertical_mirror(self):\n        if self.coords and isinstance(self.coords[0], (float, int)):\n            self.coords[0] = 100 - self.coords[0]\n            self.source = re.sub(r\"(.+):.+\", fr\"\\1: {self.coords[0]}, {self.coords[1]}\", self.source)\n    \n    def invert_coords_diagonal_mirror(self):\n        if self.coords:\n            (self.coords[0], self.coords[1]) = (self.coords[1], self.coords[0])\n            self.source = re.sub(r\"(.+):.+\", fr\"\\1: {self.coords[0]}, {self.coords[1]}\", self.source)\n"
  },
  {
    "path": "mocodo/convert/__init__.py",
    "content": ""
  },
  {
    "path": "mocodo/convert/_ast.py",
    "content": "from ..tools.parser_tools import parse_source, Token\n\ndef ast_to_yaml(node, indent=\"\"):\n    indent += \"  \"\n    if isinstance(node, Token):\n        yield f\"{indent}- type: {node.type}\"\n        yield f\"{indent}  value: {repr(node.value)}\"\n    else:\n        yield f\"{indent}- type: {node.data}\"\n        yield f\"{indent}  children:\"\n        for child in node.children:\n            yield from ast_to_yaml(child, indent)\n\n\ndef run(source, subargs=None, common=None):\n    tree = parse_source(source)\n    return {\n        \"stem_suffix\": \"_ast\",\n        \"text\": \"\\n\".join(ast_to_yaml(tree)),\n        \"extension\": \"yaml\",\n        \"to_defer\": False,\n        \"highlight\": \"yaml\",\n    }\n"
  },
  {
    "path": "mocodo/convert/_chen.py",
    "content": "from collections import Counter\nimport itertools\nimport re\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source, is_identifier\nfrom ..rewrite import _split as split\nfrom ..tools.graphviz_tools import create_name_to_index\nfrom ..tools.string_tools import wrap_label, rstrip_digit_or_underline\nfrom .. import __version__\n\nclass Chen(Visitor):\n    def __init__(self, subargs, common):\n        self.no_attrs = \"attrs\" not in subargs\n        subargs.pop(\"attrs\", None)\n        self.subargs = subargs\n        self.df_counter = itertools.count()\n        self.df_label = common.params[\"df\"]\n\n        self.name_to_index = create_name_to_index()\n        # Entities and their attributes\n        self.entity_nodes = []\n        self.weak_box_indexes = set()\n        self.strengthening_leg_count = Counter()\n        self.ent_attr_nodes = []\n        self.ent_key_attr_nodes = []\n        self.ent_attr_edges = []\n        self.not_gerund_nodes = set()\n        # Associations and their attributes\n        self.rel_nodes = []\n        self.rel_attr_nodes = []\n        self.rel_attr_edges = []\n        # Legs with their participation\n        self.partial_edges = []\n        self.total_edges = []\n        # Invisible boxes\n        self.invisible_boxes = set()\n\n    def entity_or_table_attr(self, tree):\n        id_groups = str(first_child(tree, \"id_groups\"))\n        id_mark = str(first_child(tree, \"id_mark\"))\n        attr = str(first_child(tree, \"attr\"))\n        tree.children = [(id_groups, id_mark, attr)]\n    \n    def entity_clause(self, tree):\n        ent_name = str(first_child(tree, \"box_name\"))\n        ent_index = self.name_to_index(f\"ent_{ent_name}\")\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(ent_index)\n            return\n        ent_name = rstrip_digit_or_underline(ent_name)\n        self.entity_nodes.append((ent_index, ent_name))\n\n        # Entity attributes\n        if self.no_attrs:\n            return\n        for (i, node) in enumerate(tree.find_data(\"entity_or_table_attr\")):\n            (id_groups, id_mark, attr_label) = node.children[0]\n            attr_label = str(attr_label)\n            if attr_label == \"\":\n                continue # don't create a node for a spacer attribute\n            attr_index = self.name_to_index(f\"ent_attr_{ent_index}_{attr_label}\")\n            if is_identifier(i, id_groups, id_mark):\n                self.ent_key_attr_nodes.append((attr_index, attr_label, ent_index))\n            else:\n                self.ent_attr_nodes.append((attr_index, attr_label))\n            self.ent_attr_edges.append((ent_index, attr_index))\n    \n    def assoc_clause(self, tree):\n        legs = [node for node in tree.find_data(\"assoc_leg\")]\n\n        # Accumulate the association as a new relationship\n        assoc_name = str(first_child(tree, \"assoc_name_def\").children[0])\n        if assoc_name == self.df_label:\n            assoc_name = f\"{assoc_name}{next(self.df_counter)}\"\n        assoc_index = self.name_to_index(f\"assoc_{assoc_name}\")\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(assoc_index)\n            return\n        assoc_name = rstrip_digit_or_underline(assoc_name)\n        self.rel_nodes.append((assoc_index, assoc_name))\n\n        min_maxs = [node.children[0].value for node in tree.find_data(\"card\")]\n        ent_names = [str(first_child(leg, \"entity_name_ref\").children[0]) for leg in legs]\n\n        edge_accs = [self.partial_edges if c[0] == \"0\" else self.total_edges for c in min_maxs]\n        ent_indexes = [self.name_to_index(f\"ent_{ent_name}\") for ent_name in ent_names]\n\n        if len(legs) == 2:\n            weaks = [first_child(leg, \"card_prefix\") == \"_\" for leg in legs]\n            if any(weaks): # the binary association is \"weak\", in the Chen sense\n                self.weak_box_indexes.add(assoc_index)\n            # If both legs are *N, change one with *M\n            if min_maxs[0][1] == min_maxs[1][1] == \"N\":\n                min_maxs[0] = f\"{min_maxs[0][0]}M\"\n            for i in range(2):\n                # The 1-i is to get the other leg, i.e., to look across instead of to look here\n                edge_accs[i].append((ent_indexes[i], assoc_index, min_maxs[1-i][1]))\n                if weaks[i]: # the entity is distinguished by a _11\n                    self.weak_box_indexes.add(ent_indexes[i])\n                    self.strengthening_leg_count[ent_indexes[i]] += 1\n                else: # we are sure that it is not an associative entity\n                    self.not_gerund_nodes.add(ent_indexes[i])\n        else:\n            # The Chen's card is 1 if the min-max card has a \"/\" prefix, N otherwise\n            chen_cards = [\"1\" if first_child(leg, \"card_prefix\") == \"/\" else \"N\" for leg in legs]\n            for (chen_card, edge_acc, ent_index) in zip(chen_cards, edge_accs, ent_indexes):\n                edge_acc.append((ent_index, assoc_index, chen_card))\n                self.not_gerund_nodes.add(ent_index)\n        \n        # Association attributes\n        if self.no_attrs:\n            return\n        for node in tree.find_data(\"attr\"):\n            attr_label = str(node.children[0])\n            if attr_label == \"\":\n                continue # don't create a node for a spacer attribute\n            attr_index = self.name_to_index(f\"assoc_attr_{assoc_index}_{attr_label}\")\n            self.rel_attr_nodes.append((attr_index, attr_label))\n            self.rel_attr_edges.append((assoc_index, attr_index))\n    \n    def start(self, tree):\n        # Since the traversal is depth-first, this is in fact a post-treatment\n        for (ent_index, strengthening_leg_count) in self.strengthening_leg_count.items():\n            if strengthening_leg_count < 2:\n                self.not_gerund_nodes.add(ent_index)\n        self.partial_edges = [(x, y, c) for (x, y, c) in self.partial_edges if x not in self.invisible_boxes and y not in self.invisible_boxes]\n        self.total_edges = [(x, y, c) for (x, y, c) in self.total_edges if x not in self.invisible_boxes and y not in self.invisible_boxes]\n    \n    def get_graphviz(self, common):\n        style = common.load_style()\n        result = []\n        result.append(f'// Generated by Mocodo {__version__}\\n')\n        result.append(f'graph{{')\n        result.append(f'  bgcolor=\"{style[\"background_color\"]}\"')\n        if common.params[\"seed\"] is not None:\n            result.append(f'  start={common.params[\"seed\"]}')\n\n        for (subsubopt, subsubarg) in self.subargs.items():\n            result.append(f'  {subsubopt}={subsubarg}')\n\n        result.append(f'\\n  // Entities')\n        result.append(f'  node [')\n        result.append(f'    shape=box')\n        result.append(f'    style=filled')\n        result.append(f'    penwidth={style[\"box_stroke_depth\"]}')\n        result.append(f'    color=\"{style[\"entity_stroke_color\"]}\"')\n        result.append(f'    fillcolor=\"{style[\"entity_cartouche_color\"]}\"')\n        result.append(f'    fontcolor=\"{style[\"entity_cartouche_text_color\"]}\"')\n        result.append(f'  ]')\n        for (index, name) in self.entity_nodes:\n            name = \"\\\\n\".join(wrap_label(name))\n            if index in self.not_gerund_nodes:\n                if index in self.weak_box_indexes:\n                    result.append(f'  {index} [label=\"{name}\",peripheries=2]')\n                else:\n                    result.append(f'  {index} [label=\"{name}\"]')\n        \n        if len(self.entity_nodes) > len(self.not_gerund_nodes):\n            result.append(f'\\n  // Associative entities')\n            for (index, name) in self.entity_nodes:\n                name = \"\\\\n\".join(wrap_label(name))\n                if index not in self.not_gerund_nodes:\n                    result.append(f'  {index} [label=\"{name}\",shape=Mdiamond]')\n\n        if self.ent_attr_nodes or self.ent_key_attr_nodes:\n            result.append(f'\\n  // Normal entity attributes')\n            result.append(f'  node [')\n            result.append(f'    shape=oval')\n            result.append(f'    penwidth={style[\"box_stroke_depth\"]}')\n            result.append(f'    color=\"{style[\"entity_stroke_color\"]}\"')\n            result.append(f'    fillcolor=\"{style[\"entity_color\"]}\"')\n            result.append(f'    fontcolor=\"{style[\"entity_attribute_text_color\"]}\"')\n            result.append(f'  ]')\n            for (index, name) in self.ent_attr_nodes:\n                name = \"\\\\n\".join(wrap_label(name))\n                result.append(f'  {index} [label=\"{name}\"]')\n            result.append(f'\\n  // Weak and strong entity attributes')\n            for (index, name, ent_index) in self.ent_key_attr_nodes:\n                name = \"<br/>\".join(wrap_label(name))\n                if ent_index in self.weak_box_indexes:\n                    result.append(f'  {index} [label=<<u>{name}</u>> style=\"dashed,filled\"]')\n                else:\n                    result.append(f'  {index} [label=<<u>{name}</u>>]')\n        \n        if self.rel_attr_nodes:\n            result.append(f'\\n  // Relationship attributes')\n            result.append(f'  node [')\n            result.append(f'    color=\"{style[\"association_stroke_color\"]}\"')\n            result.append(f'    fillcolor=\"{style[\"association_color\"]}\"')\n            result.append(f'    fontcolor=\"{style[\"association_attribute_text_color\"]}\"')\n            result.append(f'  ]')\n            for (index, name) in self.rel_attr_nodes:\n                name = \"\\\\n\".join(wrap_label(name))\n                result.append(f'  {index} [label=\"{name}\"]')\n\n        if self.rel_nodes:\n            result.append(f'\\n  // Relationships')\n            result.append(f'  node [')\n            result.append(f'    shape=diamond')\n            result.append(f'    height=0.7')\n            result.append(f'    penwidth={style[\"box_stroke_depth\"]}')\n            result.append(f'    color=\"{style[\"association_stroke_color\"]}\"')\n            result.append(f'    fillcolor=\"{style[\"association_cartouche_color\"]}\"')\n            result.append(f'    fontcolor=\"{style[\"association_cartouche_text_color\"]}\"')\n            result.append(f'  ]')\n            for (index, name) in self.rel_nodes:\n                name = \"\\\\n\".join(wrap_label(name))\n                if index in self.weak_box_indexes:\n                    result.append(f'  {index} [label=\"{name}\",peripheries=2]')\n                else:\n                    result.append(f'  {index} [label=\"{name}\"]')\n\n        if self.ent_attr_edges or self.rel_attr_edges:\n            result.append(f'\\n  // Edges between entities and attributes')\n            result.append(f'  edge [')\n            result.append(f'    penwidth={style[\"box_stroke_depth\"]}')\n            result.append(f'    color=\"{style[\"entity_stroke_color\"]}\"')\n            result.append(f'  ]')\n            for (ent_index, attr_index) in sorted(self.ent_attr_edges):\n                result.append(f'  {ent_index} -- {attr_index}')\n            result.append(f'\\n  // Edges between relationships and attributes')\n            result.append(f'  edge [color=\"{style[\"association_stroke_color\"]}\"]')\n            useless = True\n            for (assoc_index, attr_index) in sorted(self.rel_attr_edges):\n                result.append(f'  {assoc_index} -- {attr_index}')\n                useless = False\n            if useless:\n                result.pop()\n                result.pop()\n\n        if self.partial_edges or self.total_edges:\n            seen_edges = set()\n            result.append(f'\\n  // Edges between entities and relationships')\n            result.append(f'  edge [')\n            result.append(f'    penwidth={style[\"leg_stroke_depth\"]}')\n            result.append(f'    color=\"{style[\"leg_stroke_color\"]}:{style[\"leg_stroke_color\"]}\"') # default to total participation\n            result.append(f'    fontcolor=\"{style[\"card_text_color\"]}\"')\n            result.append(f'    labeldistance=2')\n            result.append(f'    headlabel=1')\n            result.append(f'  ]')\n            for label in \"1MN\":\n                useless = label != \"1\"\n                if label != \"1\":\n                    result.append(f'  edge [headlabel={label}]')\n                suffix = \"\"\n                for edges in (self.total_edges, self.partial_edges):\n                    for (ent_index, assoc_index, edge_label) in sorted(edges):\n                        if label == edge_label:\n                            if (ent_index, assoc_index) in seen_edges:\n                                (assoc_index, ent_index) = (ent_index, assoc_index)\n                            result.append(f'  {ent_index} -- {assoc_index}{suffix}')\n                            seen_edges.add((ent_index, assoc_index))\n                            useless = False\n                    suffix = f' [color=\"{style[\"leg_stroke_color\"]}\"]' # from now on, partial participation\n                if useless:\n                    result.pop()\n        result.append(\"}\")\n\n        result = \"\\n\".join(result)\n        useless_colors = [\n            'bgcolor=\"#FFFFFF\"',\n            'color=\"#000000\"',\n            'fontcolor=\"#000000\"',\n        ]\n        for useless_color in useless_colors:\n            result = re.sub(fr'(?m)^ *{useless_color}\\n', \"\", result)\n        return result\n\n    def get_text_for_testing(self):\n        nodes = {}\n        for (i, x) in self.entity_nodes:\n            if i in self.not_gerund_nodes:\n                if i in self.weak_box_indexes:\n                    nodes[i] = f\"[[{x}]]\"\n                else:\n                    nodes[i] = f\"[{x}]\"\n            else:\n                nodes[i] = f\"[<{x}>]\"\n        for (i, x) in self.rel_nodes:\n            if i in self.weak_box_indexes:\n                nodes[i] = f\"<<{x}>>\"\n            else:\n                nodes[i] = f\"<{x}>\"\n        for (i, x, j) in self.ent_key_attr_nodes:\n            if j in self.weak_box_indexes:\n                nodes[i] = f\"(.{x}.)\"\n            else:\n                nodes[i] = f\"(_{x}_)\"\n        nodes.update((i, f\"({x})\") for (i, x) in self.ent_attr_nodes + self.rel_attr_nodes)\n        result = []\n        for (x, y, c) in self.partial_edges:\n            result.append(f\"            {nodes[x]} --{c}-- {nodes[y]}\")\n        for (x, y, c) in self.total_edges:\n            result.append(f\"            {nodes[x]} =={c}== {nodes[y]}\")\n        for (x, y) in self.ent_attr_edges + self.rel_attr_edges:\n            result.append(f\"            {nodes[x]} -- {nodes[y]}\")\n        return \"\\n\".join(sorted(result))\n\n\ndef run(source, subargs=None, common=None, testing=False):\n    subargs = subargs or {}\n    source = split.run(source)\n    tree = parse_source(source)\n    extractor = Chen(subargs, common)\n    extractor.visit(tree)\n    if testing:\n        return extractor.get_text_for_testing()\n    text = extractor.get_graphviz(common)\n    return {\n        \"stem_suffix\": \"_erd_chen\",\n        \"text\": text,\n        \"extension\": \"gv\",\n        \"to_defer\": True,\n        \"highlight\": \"graphviz\",\n    }\n"
  },
  {
    "path": "mocodo/convert/_crow.py",
    "content": "import importlib\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..mocodo_error import subsubopt_error\nfrom ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, is_identifier\nfrom ..tools.string_tools import rstrip_digit_or_underline\nfrom ..tools.graphviz_tools import create_name_to_index\n\n\nclass Crow(Visitor):\n    def __init__(self):\n        self.name_to_index = create_name_to_index()\n        self.tables = {}\n        self.links = []\n        self.has_no_datatype = True\n        self.invisible_boxes = set()\n    \n    def entity_or_table_attr(self, tree):\n        id_groups = str(first_child(tree, \"id_groups\"))\n        id_mark = str(first_child(tree, \"id_mark\"))\n        attr = str(first_child(tree, \"attr\"))\n        datatype = str(first_child(tree, \"datatype\"))\n        if datatype:\n            self.has_no_datatype = False\n        tree.children = [(id_groups, id_mark, attr, datatype)]\n    \n    def entity_clause(self, tree):\n        ent_name = first_child(tree, \"box_name\").value\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(ent_name)\n            return\n        ent_index = self.name_to_index(ent_name)\n        ent_name = rstrip_digit_or_underline(ent_name)\n        attrs = []\n        has_id = False\n        for (i, node) in enumerate(tree.find_data(\"entity_or_table_attr\")):\n            (id_groups, id_mark, attr, datatype) = node.children[0]\n            is_id = is_identifier(i, id_groups, id_mark)\n            has_id = has_id or is_id\n            attrs.append((datatype, attr, is_id))\n        self.tables[ent_index] = (ent_name, has_id, attrs)\n    \n    def assoc_clause(self, tree):\n        assoc_name = first_child(tree, \"assoc_name_def\").children[0].value\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(assoc_name)\n            return\n        cards = [node.children[0].value for node in tree.find_data(\"card\")]\n        assert len(cards) == 2\n        assoc_name = rstrip_digit_or_underline(assoc_name)\n        kind = \"..\" if any(s.children[0].value == \"_\" for s in tree.find_data(\"card_prefix\")) else \"--\"\n        entities = tree.find_data(\"entity_name_ref\")\n        ent_1 = first_child(next(entities), \"entity_name_ref\").children[0]\n        ent_2 = first_child(next(entities), \"entity_name_ref\").children[0]\n        self.links.append((ent_1, cards[1], kind, cards[0], ent_2, assoc_name))\n    \n    def start(self, tree):\n        visible_links = []\n        for (ent_1, card_1, kind, card_2, ent_2, assoc_name) in self.links:\n            if ent_1 in self.invisible_boxes or ent_2 in self.invisible_boxes:\n                continue\n            visible_links.append((ent_1, card_1, kind, card_2, ent_2, assoc_name))\n\n\ndef run(source, subargs, common=None):\n    extension = \"mmd\" if \"mmd\" in subargs or \"mermaid\" in subargs else \"gv\"\n    try:\n        module = importlib.import_module(f\".convert.crow_{extension}\", package=\"mocodo\")\n    except ModuleNotFoundError:\n        raise subsubopt_error(extension)\n    text = module.run(source, subargs, common)\n    if extension == \"mmd\":\n        return {\n            \"stem_suffix\": \"_erd_crow\",\n            \"text\": text,\n            \"extension\": \"mmd\",\n            \"to_defer\": True,\n            \"highlight\": \"mermaid\",\n        }\n    else:\n        return {\n            \"stem_suffix\": \"_erd_crow\",\n            \"text\": text,\n            \"extension\": \"gv\",\n            \"to_defer\": True,\n            \"highlight\": \"graphviz\",\n        }\n\n"
  },
  {
    "path": "mocodo/convert/_data_dict.py",
    "content": "__import__(\"sys\").path[0:0] = [\".\"]\n\nimport re\n\nfrom ..tools.string_tools import markdown_table\nfrom ..parse_mcd import Transformer\nfrom ..tools.parser_tools import parse_source, first_child\nfrom ..mocodo_error import subsubopt_error\n\nDEFAULT_COLUMN_NAMES = {\n    \"en\": {\n        \"label\": \"Label of the attribute\",\n        \"type\": \"Type\",\n        \"box\": \"Entity or relationship\",\n    },\n    \"fr\": {\n        \"label\": \"Libellé de l'attribut\",\n        \"type\": \"Type\",\n        \"box\": \"Entité ou association\",\n    },\n}\n\nclass AttributeListExtractor(Transformer): # depth-first, post-order\n    def __init__(self):\n        self.boxes = {}\n        self.typed_attribute_accumulator = []\n        self.assoc_clause = self._box_clause\n        self.entity_clause = self._box_clause\n    \n    def _box_clause(self, children):\n        # Associate the box name with the accumulated list of attributes\n        box_def_prefix = first_child(children[0], \"box_def_prefix\")\n        if box_def_prefix != \"-\":\n            if not box_def_prefix:\n                box_name = first_child(children[0], \"box_name\")\n            else:\n                box_name = first_child(children[1], \"box_name\")\n            self.boxes[box_name] = self.typed_attribute_accumulator[:]\n        self.typed_attribute_accumulator = []\n    \n    def attr(self, children):\n        # Accumulate a couple (attribute name, data type placeholder)\n        self.typed_attribute_accumulator.append((children[0].value, \"\"))\n    \n    def datatype(self, children):\n        # Replace the last data type placeholder with the actual data type\n        (name, _) = self.typed_attribute_accumulator.pop()\n        self.typed_attribute_accumulator.append((name, children[0].value))\n    \n    def finalize(self, common, subargs):\n        language = common.params[\"language\"]\n        actual_colons = {}\n        for kind in list(subargs):\n            m = re.match(r\"^([*_`]*)(.+)\\1$\", kind) \n            if m[2] in (\"label\", \"type\", \"box\"):\n                actual_colons[m[2]] = m[1]\n            subargs[m[2]] = subargs.pop(kind)\n        if not actual_colons:\n            actual_colons[\"box\"] = subargs[\"box\"] = \"\"\n            actual_colons[\"label\"] = subargs[\"label\"] = \"\"\n            actual_colons[\"type\"] = subargs[\"type\"] = \"\"\n        self.header = []\n        self.projectors = []\n        for (kind, col_name) in subargs.items():\n            if kind in (\"tsv\", \"md\", \"markdown\"):\n                continue\n            if kind not in actual_colons:\n                raise subsubopt_error(kind)\n            self.header.append(col_name or DEFAULT_COLUMN_NAMES[language][kind])\n            self.projectors.append(kind)\n        self.rows = []\n        for (box, attributes) in self.boxes.items():\n            for (attr, datatype) in attributes:\n                d = {\"box\": box, \"label\": attr, \"type\": datatype}\n                row = [d[p] for p in self.projectors]\n                self.rows.append(row)\n        self.md_tags = [actual_colons[p] for p in self.projectors]\n        self.rows.sort()\n        return len(actual_colons)\n    \n    def get_tsv(self):\n        result = []\n        if len(self.header) > 1:\n            result.append(\"\\t\".join(self.header))\n        result.extend(map(\"\\t\".join, self.rows))\n        return \"\\n\".join(result)\n    \n    def get_markdown(self):\n        if len(self.header) > 1: # output a table only if there are at least two columns\n            result = []\n            previous_leftmost = None\n            for row in [self.header] + self.rows:\n                if row[0] == previous_leftmost:\n                    row[0] = '\"'\n                else:\n                    previous_leftmost = row[0]\n                result.append(f\"{tag}{cell}{tag}\" for (tag, cell) in zip(self.md_tags, row))\n            return markdown_table(result)\n        else: # otherwise, output a list\n            return \"\\n\".join([f\"- {self.md_tags[0]}{row[0]}{self.md_tags[0]}\" for row in self.rows])\n\ndef run(source, subargs=None, common=None):\n    tree = parse_source(source)\n    extractor = AttributeListExtractor()\n    extractor.transform(tree)\n    column_count = extractor.finalize(common, subargs)\n    if \"tsv\" in subargs:\n        return {\n            \"stem_suffix\": f\"_data_dict_{column_count}\",\n            \"text\": extractor.get_tsv(),\n            \"extension\": \"tsv\",\n            \"to_defer\": False,\n            \"highlight\": \"tsv\",\n        }\n    else: # Markdown is the default\n        return {\n            \"stem_suffix\": f\"_data_dict_{column_count}\",\n            \"text\": extractor.get_markdown(),\n            \"extension\": \"md\",\n            \"to_defer\": False,\n            \"highlight\": \"markdown\",\n        }\n"
  },
  {
    "path": "mocodo/convert/_prompt.py",
    "content": "from ..parse_mcd import Visitor\nfrom ..tools.parser_tools import parse_source, reconstruct_source, first_child\nfrom pathlib import Path\n\nclass CreateLegNotePlaceholder(Visitor):\n    def assoc_leg(self, tree):\n        \"\"\" Create or replace the leg note with a placeholder. \"\"\"\n        leg_note = first_child(tree, \"leg_note\")\n        if leg_note:\n            leg_note.value = \"?\"\n        else:\n            box_name = first_child(tree, \"box_name\")\n            box_name.value = f\"[?] {box_name.value}\"\n\n    def comment(self, tree):\n        \"\"\" Suppress the comment line. \"\"\"\n        tree.children = []\n\n\nclass CreateTypePlaceholder(Visitor):\n    def typed_attr(self, tree):\n        if len(tree.children) == 1:\n            tree.children[0].children[0].value += f\" [?]\"\n\ndef CreatePlaceholder(subarg):\n    if subarg == \"cards\":\n        return CreateLegNotePlaceholder()\n    elif subarg == \"types\":\n        return CreateTypePlaceholder()\n    else:\n        raise ValueError(f\"Unknown subarg: {subarg}\")\n\n\ndef get_prompt(source, chat_dir, subarg):\n    prompt = Path(chat_dir, f\"{subarg}_fr.md\").read_text(encoding=\"utf8\")\n    examples = []\n    for path in sorted(Path(chat_dir, f\"{subarg}_examples\").glob(\"*.mcd\")):\n        (i, name) = path.stem.split(\"_\", 1)\n        example_source = path.read_text(encoding=\"utf8\")\n        if name == \"input\":\n            examples.append(f\"## Example {i}\\n\\n### Question\\n\\n{backticks(example_source)}\")\n        elif name == \"output\":\n            examples.append(f\"### Answer\\n\\n{backticks(example_source)}\")\n    examples = \"\\n\".join(examples)\n    tree = parse_source(source)\n    visitor = CreatePlaceholder(subarg)\n    visitor.visit(tree)\n    question = backticks(reconstruct_source(tree))\n    return prompt.format(examples=examples, question=question)\n\ndef backticks(text):\n    text = text.strip('\\n')\n    return f\"```mocodo\\n{text}\\n```\\n\"\n\ndef run(source, subargs, common):\n    chat_dir = Path(common.params[\"script_directory\"], \"resources\", \"prompts\", \"chat\")\n    prompt = \"\"\n    for subarg in subargs:\n        if subarg in (\"cards\", \"types\"):\n            prompt = get_prompt(source, chat_dir, subarg)\n            break\n    return {\n        \"stem_suffix\": f\"_prompt_for_{subarg}\",\n        \"text\": prompt,\n        \"extension\": \"md\",\n        \"to_defer\": False,\n        \"highlight\": \"md\",\n    }\n"
  },
  {
    "path": "mocodo/convert/_share.py",
    "content": "from ..tools.string_tools import urlsafe_encoding\n\n\ndef run(source, subargs=None, common=None):\n    return {\n        \"stem_suffix\": \"_url\",\n        \"text\": f\"https://www.mocodo.net/?mcd={urlsafe_encoding(source)}\",\n        \"extension\": \"url\",\n        \"to_defer\": True,\n        \"highlight\": \"url\",\n    }\n"
  },
  {
    "path": "mocodo/convert/_uml.py",
    "content": "import itertools\nimport gettext\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source, is_identifier\nfrom ..rewrite import (\n    _split as split,\n    _drain as drain,\n)\nfrom .. import __version__\n\nMIN_MAX_IN_UML = {\n    \"01\": \"1..*\",\n    \"0N\": \"*\",\n    \"11\": \"1\",\n    \"1N\": \"1..*\",\n}\n\ngettext.NullTranslations().install()\n\nINHERITANCE_IN_UML = {\n    \"XT\": _(\"{complete, disjoint}\"), # Partition\n    \"X\": _(\"{incomplete, disjoint}\"), # Exclusivité\n    \"T\": _(\"{complete, overlapping}\"), # Totalité\n    \"\": _(\"{incomplete, overlapping}\"),\n}\n\nclass UmlClassDiagram(Visitor):\n    def __init__(self, preamble, common):\n        self.common = common\n        self.preamble = preamble or \"\" # preamble may be None\n        self.id_counter = itertools.count()\n        self.df_label = common.params[\"df\"]\n        self.has_no_datatype = True\n        self.acc = []\n        self.invisible_boxes = set()\n\n    def entity_or_table_attr(self, tree):\n        id_groups = str(first_child(tree, \"id_groups\"))\n        id_mark = str(first_child(tree, \"id_mark\"))\n        attr = str(first_child(tree, \"attr\"))\n        datatype = str(first_child(tree, \"datatype\"))\n        if datatype:\n            self.has_no_datatype = False\n        tree.children = [(id_groups, id_mark, attr, datatype)]\n    \n    def entity_clause(self, tree):\n        ent_name = str(first_child(tree, \"box_name\"))\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(ent_name)\n            return\n        attributes = []\n        for (i, node) in enumerate(tree.find_data(\"entity_or_table_attr\")):\n            (id_groups, id_mark, attr_label, datatype) = node.children[0]\n            attr_label = str(attr_label)\n            if attr_label == \"\":\n                continue # ignore spacer attributes\n            attributes.append((is_identifier(i, id_groups, id_mark), attr_label, datatype))\n        self.acc.append({\n            \"kind\": \"table\",\n            \"name\": ent_name,\n            \"attributes\": attributes,\n        })\n        self.acc.append({\"kind\": \"spacer\"})\n    \n    def assoc_clause(self, tree):\n        legs = [node for node in tree.find_data(\"assoc_leg\")]\n        assoc_name = str(first_child(tree, \"assoc_name_def\").children[0])\n        if first_child(tree, \"box_def_prefix\") == \"-\":\n            self.invisible_boxes.add(assoc_name)\n            return\n\n        min_maxs = [node.children[0].value for node in tree.find_data(\"card\")]\n        ent_names = [str(first_child(leg, \"entity_name_ref\").children[0]) for leg in legs]\n\n        typed_attrs = []\n        for node in list(tree.find_data(\"typed_attr\")):\n            attr_label = str(first_child(node, \"attr\"))\n            if attr_label == \"\":\n                continue # don't create a node for a spacer attribute\n            datatype = str(first_child(node, \"datatype\"))\n            typed_attrs.append((attr_label, datatype))\n\n        if len(legs) == 2:\n            weaks = [first_child(leg, \"card_prefix\") == \"_\" for leg in legs]\n            self.acc.append({\n                \"kind\": \"binary_link\",\n                \"tables\": ent_names,\n                \"table_1\": ent_names[0],\n                \"card_1\": MIN_MAX_IN_UML.get(min_maxs[1], \"*\"),\n                \"composition_1\": weaks[1],\n                \"table_2\": ent_names[1],\n                \"card_2\": MIN_MAX_IN_UML.get(min_maxs[0], \"*\"),\n                \"composition_2\": weaks[0],\n                \"assoc_name\": assoc_name,\n            })\n            if typed_attrs:\n                self.acc.append({\n                    \"kind\": \"binary_link_attrs\",\n                    \"tables\": ent_names,\n                    \"table_1\": ent_names[0],\n                    \"table_2\": ent_names[1],\n                    \"assoc_name\": assoc_name,\n                })\n        else:\n            # The card is 1 (11) if the min-max card has a \"/\" prefix, 1..* or * otherwise\n            diamond = f\"N_ARY_{next(self.id_counter)}\"\n            self.acc.append({\n                \"kind\": \"n_ary_link\",\n                \"diamond\": diamond,\n                \"tables\": ent_names,\n                \"cards\": [\"1\" if first_child(leg, \"card_prefix\") == \"/\" else MIN_MAX_IN_UML.get(first_child(leg, \"card\"), \"*\") for leg in legs],\n                \"assoc_name\": assoc_name,\n            })\n            if typed_attrs:\n                self.acc.append({\n                    \"kind\": \"n_ary_link_attrs\",\n                    \"diamond\": diamond,\n                    \"tables\": ent_names,\n                    \"assoc_name\": assoc_name,\n                })\n        \n        if typed_attrs:\n            self.acc.append({\n                \"kind\": \"table\",\n                \"name\": assoc_name,\n                \"attributes\": [(False, attr_label, datatype) for (attr_label, datatype) in typed_attrs],\n                \"tables\": ent_names,\n            })\n        \n        self.acc.append({\"kind\": \"spacer\"})\n    \n    def inheritance_clause(self, tree):\n        inheritance_name = str(first_child(tree, \"inheritance_name\"))\n        box_names = [str(first_child(leg, \"box_name\")) for leg in tree.find_data(\"box_name\")]\n        box_names.reverse() # not sure why, but the boxes seem to come in reverse order\n        self.acc.append({\n            \"kind\": \"generalization\",\n            \"set\": INHERITANCE_IN_UML[inheritance_name],\n            \"parent\": box_names[0],\n            \"children\": [box_name for box_name in box_names[1:]],\n            \"id\": f\"GENERALIZATION_{next(self.id_counter)}\",\n        })\n        self.acc.append({\"kind\": \"spacer\"})\n    \n    def start(self, tree):\n        self.acc = list(filter(lambda d: not self.invisible_boxes.intersection(d.get(\"tables\", [])), self.acc))\n    \n    def get_plantuml(self):\n        style = self.common.load_style()\n        result = []\n        if not self.preamble.startswith(\"-\"):\n            result.append(f\"' Generated by Mocodo {__version__}\\n\")\n        result.append(f'@startuml \"{self.common.params[\"title\"]}\"\\n')\n        result.append(f'!define Table(x) class \"x\" << (T,{style[\"entity_color\"]}) >>')\n        result.append(\"!define pk(x) <b>x</b>\")\n        if self.preamble.startswith(\"-\"):\n            self.preamble = self.preamble[1:]\n        else:\n            result.append(\"\\n\".join([\n                \"hide methods\",\n                \"left to right direction\",\n                f'skinparam groupInheritance 2',\n                f'skinparam lineThickness {style[\"box_stroke_depth\"]}',\n                f'skinparam lineColor {style[\"association_stroke_color\"]}',\n                f'skinparam backgroundColor {style[\"background_color\"]}',\n                f'skinparam classAttributeFontColor {style[\"entity_attribute_text_color\"]}',\n                f'skinparam classAttributeFontName Monospaced',\n                f'skinparam classAttributeFontSize 14',\n                f'skinparam classBackgroundColor {style[\"entity_color\"]}',\n                f'skinparam classBorderColor {style[\"entity_stroke_color\"]}',\n                f'skinparam classBorderThickness {style[\"box_stroke_depth\"]}',\n                f'skinparam classFontColor {style[\"entity_cartouche_text_color\"]}',\n                f'skinparam classFontName Arial',\n                f'skinparam classFontSize 18',\n                f'skinparam classHeaderBackgroundColor {style[\"entity_cartouche_color\"]}',\n            ]))\n        result.append(self.preamble.replace(r\"\\n\", \"\\n\")) # the user-defined preamble comes raw\n        for element in self.acc:\n            if element[\"kind\"] == \"table\":\n                max_attr_length = max([len(attr) for (_, attr, _) in element[\"attributes\"]], default=0)\n                result.append(f'Table(\"{element[\"name\"]}\") {{')\n                for (is_id, attr, datatype) in element[\"attributes\"]:\n                    suffix = \"\"\n                    if datatype:\n                        tabs = \" \" * (max_attr_length - len(attr) + 1)\n                        suffix = f\"{tabs}{datatype}\"\n                    if is_id:\n                        attr = f\"pk({attr})\"\n                    result.append(f\"    {{field}} + {attr}{suffix}\")\n                result.append(f\"}}\")\n            elif element[\"kind\"] == \"binary_link\":\n                head = \"*\" if element[\"composition_1\"] else \"-\"\n                tail = \"*\" if element[\"composition_2\"] else \"-\"\n                element[\"link\"] = f\"{head}-{tail}\"\n                if element[\"assoc_name\"].upper() == self.df_label.upper():\n                    result.append('\"{table_1}\" \"{card_1}\" {link} \"{card_2}\" \"{table_2}\"'.format(**element))\n                else:\n                    result.append('\"{table_1}\" \"{card_1}\" {link} \"{card_2}\" \"{table_2}\": \"{assoc_name}\"'.format(**element))\n            elif element[\"kind\"] == \"n_ary_link\":\n                result.append(f\"diamond {element['diamond']}\")\n                for (table_name, card) in zip(element[\"tables\"], element[\"cards\"]):\n                    result.append(f'{element[\"diamond\"]} -- \"{card}\" \"{table_name}\"')\n            elif element[\"kind\"] == \"binary_link_attrs\":\n                result.append('(\"{table_1}\", \"{table_2}\") .. \"{assoc_name}\"'.format(**element))\n            elif element[\"kind\"] == \"n_ary_link_attrs\":\n                result.append('{diamond} \"{assoc_name}\" .. \"{assoc_name}\"'.format(**element))\n            elif element[\"kind\"] == \"generalization\":\n                if element[\"set\"]:\n                    result.append(f'note \"{element[\"set\"]}\" as {element[\"id\"]}')\n                    result.extend(f'{element[\"id\"]} -[dotted]- {child}' for child in element[\"children\"])\n                result.extend(f'{element[\"parent\"]} <|-- {child}' for child in element[\"children\"])\n            else: # spacer\n                result.append(\"\")\n        result.append(f\"@enduml\\n\")\n        return \"\\n\".join(result)\n\n\ndef run(source, subargs=None, common=None):\n    (language, preamble) = next(iter(subargs.items()), (\"plantuml\", \"\"))\n    source = split.run(source)\n    source = drain.run(source)\n    tree = parse_source(source)\n    extractor = UmlClassDiagram(preamble, common)\n    extractor.visit(tree)\n    if True: # language == \"plantuml\":\n        text = extractor.get_plantuml()\n        extension = \"puml\"\n        highlight = \"puml\"\n    else:\n        text = extractor.get_mermaid()\n        extension = \"mmd\"\n        highlight = \"mermaid\"\n    return {\n        \"stem_suffix\": \"_uml\",\n        \"text\": text,\n        \"extension\": extension,\n        \"to_defer\": True,\n        \"highlight\": highlight,\n    }\n"
  },
  {
    "path": "mocodo/convert/crow_gv.py",
    "content": "__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ._crow import Crow\nfrom ..tools.parser_tools import parse_source\nfrom ..rewrite import (\n    _drain as drain,\n    _explode as explode,\n    _split as split,\n)\nfrom ..tools.string_tools import rstrip_digit_or_underline\nfrom ..tools.graphviz_tools import NODE_OPTIONS_TEMPLATE, table_as_label\nfrom .. import __version__\n\nSUFFIX = \"_crows_foot_erd.gv\"\n\nGV_CARD = {\n    \"01\": \"teeodot\",\n    \"0N\": \"crowodot\",\n    \"11\": \"teetee\",\n    \"1N\": \"crowtee\",\n}\n\nclass CrowGv(Crow):\n  \n    def get_text(self, common):\n        style = common.load_style()\n        ent_table_style = {\n            \"stroke_color\": style[\"entity_stroke_color\"],\n            \"cell_bg_color\": style[\"entity_color\"],\n            \"header_bg_color\": style[\"entity_cartouche_color\"],\n            \"header_font_color\": style[\"entity_cartouche_text_color\"],\n            \"header_font_size\": style[\"entity_cartouche_font\"][\"size\"],\n            \"cell_font_color\": style[\"entity_attribute_text_color\"],\n            \"cell_font_size\": style[\"entity_attribute_font\"][\"size\"],\n        }\n        assoc_table_style = {\n            \"stroke_color\": style[\"association_stroke_color\"],\n            \"cell_bg_color\": style[\"association_color\"],\n            \"header_bg_color\": style[\"association_cartouche_color\"],\n            \"header_font_color\": style[\"association_cartouche_text_color\"],\n            \"header_font_size\": style[\"association_cartouche_font\"][\"size\"],\n            \"cell_font_color\": style[\"association_attribute_text_color\"],\n            \"cell_font_size\": style[\"association_attribute_font\"][\"size\"],\n        }\n        acc = []\n        acc.append(f'// Generated by Mocodo {__version__}\\n')\n        acc.append(f'digraph{{')\n        acc.append(f'  layout=dot')\n        acc.append(f'  bgcolor=\"{style[\"background_color\"]}\"')\n        acc.append(f'  nodesep=0.5') # increase spacing between multiedges\n\n        acc.append(f'\\n  // Nodes')\n        for (i, table_style) in enumerate([assoc_table_style, ent_table_style]):\n            node_options = NODE_OPTIONS_TEMPLATE.format(**ent_table_style)\n            acc.append(f'  node [{node_options}]')\n            for (ent_index, (ent_name, has_id, attrs)) in self.tables.items():\n                if i != has_id:\n                    continue\n                attrs = [((\"PK\" if is_id else \" \"), a, (t or \" \")) for (t, a, is_id) in attrs]\n                row_format = \"|c|lR|\"\n                if self.has_no_datatype:\n                    attrs = [attr[:-1] for attr in attrs]\n                    row_format = row_format.replace(\"R|\", \"|\")\n                label = table_as_label(ent_name, attrs, row_format, table_style)\n                acc.append(f'  {ent_index} [label=<{label}>]')\n        \n        acc.append(f'\\n  // Edges')\n        acc.append(f'  edge [')\n        acc.append(f'    penwidth={style[\"leg_stroke_depth\"]}')\n        acc.append(f'    color=\"{style[\"leg_stroke_color\"]}\"')\n        acc.append(f'    fontcolor=\"{style[\"card_text_color\"]}\"')\n        acc.append(f'    fontname=\"{style[\"card_font\"][\"family\"]}\"')\n        acc.append(f'    fontsize={style[\"card_font\"][\"size\"]}')\n        acc.append(f'    dir=both') # bidirectional arrows, otherwise the tail doesn't appear\n        acc.append(f'  ]')\n        for (ent_1, card_1, kind, card_2, ent_2, assoc_name) in self.links:\n            ent_index_1 = self.name_to_index(ent_1)\n            ent_index_2 = self.name_to_index(ent_2)\n            tail = GV_CARD.get(card_1, \"crowodot\")\n            head = GV_CARD.get(card_2, \"crowodot\")\n            kind = \" style=dotted\" if kind == \"..\" else \"\"\n            label = \"\"\n            if self.tables[ent_index_1][1] and self.tables[ent_index_2][1]:\n                label = f' label=\"{rstrip_digit_or_underline(assoc_name)}\"'\n            acc.append(f'  {ent_index_1} -> {ent_index_2} [arrowhead=\"{head}\" arrowtail=\"{tail}\"{label}{kind}]')\n        acc.append('}')\n\n        return \"\\n\".join(acc)\n\ndef run(source, subargs, common=None):\n    source = drain.run(source)\n    source = split.run(source)\n    source = explode.run(source, {\"arity\": \"2.5\", \"weak\": True}, common.params)\n    tree = parse_source(source)\n    extractor = CrowGv()\n    extractor.visit(tree)\n    result = extractor.get_text(common)\n    return result\n"
  },
  {
    "path": "mocodo/convert/crow_mmd.py",
    "content": "import re\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ._crow import Crow\nfrom ..tools.parser_tools import parse_source\nfrom ..rewrite import (\n    op_tk,\n    _drain as drain,\n    _explode as explode,\n    _split as split,\n)\nfrom ..tools.string_tools import rstrip_digit_or_underline\nfrom .. import __version__\n\nSUFFIX = \"_crows_foot_erd.mmd\"\n\nLEFT_CARD = {\n    \"01\": \"|o\",\n    \"0N\": \"}o\",\n    \"11\": \"||\",\n    \"1N\": \"}|\",\n}\nRIGHT_CARD = {\n    \"01\": \"o|\",\n    \"0N\": \"o{\",\n    \"11\": \"||\",\n    \"1N\": \"|{\",\n}\n\n\ndef sanitize_type(s):\n    # In Mermaid syntax, the type values must begin with an alphabetic character\n    # and may contain digits, hyphens, underscores, parentheses and square brackets.\n    # This seems a too specific operation to be offered by op_tk.\n    s = s.replace(\n        \",\", \"-\"\n    )  # as long as https://github.com/mermaid-js/mermaid/issues/1546 is not fixed\n    s = re.sub(r\"[^-_0-9A-Za-z()[\\]]\", \"_\", s)\n    s = re.sub(r\"__+\", \"_\", s)\n    s = s.strip(\"_\")\n    return s\n\n\nclass CrowMmd(Crow):\n    def get_text(self):\n        result = []\n        result.append(\"erDiagram\")\n        result.append(f\"  %% Generated by Mocodo {__version__}\")\n        for (name, has_id, attrs) in self.tables.values():\n            result.append(f\"  {name} {{\")\n            for (datatype, attr, is_id) in attrs:\n                datatype = sanitize_type(datatype) if datatype else \"TYPE\"\n                pk = \" PK\" if is_id else \"\"\n                result.append(f\"    {datatype} {attr}{pk}\")\n            result.append(f\"  }}\")\n        for (ent_1, card_1, kind, card_2, ent_2, assoc_name) in self.links:\n            ent_1 = rstrip_digit_or_underline(ent_1)\n            ent_2 = rstrip_digit_or_underline(ent_2)\n            card_1 = LEFT_CARD.get(card_1, \"}|\")\n            card_2 = RIGHT_CARD.get(card_2, \"|{\")\n            result.append(f\"  {ent_1} {card_1}{kind}{card_2} {ent_2}: {assoc_name}\")\n        return \"\\n\".join(result)\n\n\ndef run(source, subargs, common=None):\n    source = op_tk.run(source, \"ascii\", {\"labels\": 1}, common.params)\n    source = op_tk.run(source, \"snake\", {\"labels\": 1}, common.params)\n    source = drain.run(source)\n    source = split.run(source)\n    source = explode.run(source, {\"arity\": \"2.5\", \"weak\": True}, common.params)\n    tree = parse_source(source)\n    extractor = CrowMmd()\n    extractor.visit(tree)\n    result = extractor.get_text()\n    return result\n"
  },
  {
    "path": "mocodo/convert/read_template.py",
    "content": "from bisect import bisect_left\nfrom pathlib import Path\n\nfrom ..tools import load_mini_yaml\nfrom ..mocodo_error import MocodoError\n\ndef read_template(stem_or_path, official_template_dir):\n\n    def traverse_templates(stem_or_path, template_stack, already_seen):\n        if stem_or_path.endswith(\".yaml\"):\n            path = Path(stem_or_path).absolute()\n        else:\n            path = official_template_dir / f\"{stem_or_path}.yaml\"\n        (folder, name) = (path.parent, path.stem)\n        if stem_or_path in already_seen:\n            raise MocodoError(30, _('Circular inheritance in template \"{name}.yaml\" of \"{folder}.').format(name=name, folder=folder))  # fmt: skip\n        already_seen.add(stem_or_path)\n        if not path.is_file():\n            raise MocodoError(31, _('Template \"{name}.yaml\" not found in \"{folder}\".').format(name=name, folder=folder))  # fmt: skip\n        try:\n            template = load_mini_yaml.run(path)\n        except:\n            raise MocodoError(32, _('Unable to decode template \"{name}.yaml\" of \"{folder}\".').format(name=name, folder=folder))  # fmt: skip\n        for (key, array) in template.items():\n            if isinstance(array, dict):\n                raise MocodoError(34, _('Template \"{name}.yaml\" of \"{folder}\" contains a YAML object as value of key \"{key}\".').format(name=name, folder=folder, key=key))  # fmt: skip\n            if not isinstance(array, list):\n                continue\n            previous_order = None\n            for d in array:\n                if not isinstance(d, dict):\n                    raise MocodoError(35, _('Template \"{name}.yaml\" of \"{folder}\" contains a YAML array as value of key \"{key}\" which does not contain only YAML objects.').format(name=name, folder=official_template_dir, key=key))  # fmt: skip\n                if \"order\" not in d:\n                    raise MocodoError(36, _('Template \"{name}.yaml\" of \"{folder}\" contains a YAML array as value of key \"{key}\" which does not contain only objects having an \"order\" key.').format(name=name, folder=official_template_dir, key=key))  # fmt: skip\n                order = d[\"order\"]\n                if not isinstance(order, (int, float)):\n                    raise MocodoError(38, _('Template \"{name}.yaml\" of \"{folder}\" contains a YAML array as value of key \"{key}\" where the \"order\" key is not associated to a number.').format(name=name, folder=official_template_dir, key=key))\n                if previous_order is not None and order <= previous_order:\n                    raise MocodoError(39, _('Template \"{name}.yaml\" of \"{folder}\" contains a YAML array as value of key \"{key}\" where the \"order\" keys are not sorted in ascending order.').format(name=name, folder=official_template_dir, key=key))\n                previous_order = order\n        template_stack.append(template)\n        if \"parent\" in template:\n            return traverse_templates(template[\"parent\"], template_stack, already_seen)\n        else:\n            return reversed(template_stack)\n    \n    result = {}\n    for template in traverse_templates(stem_or_path, [], set()):\n        for key in template:\n            if not isinstance(result.get(key), list):\n                # create or update a scalar value\n                result[key] = template[key]\n            else:\n                if template[key] == []:\n                    result[key] = []                    \n                # update a non-empty list of dictionaries having an \"order\" key\n                for new_dictionary in template[key]:\n                    order = new_dictionary[\"order\"]\n                    orders = [d[\"order\"] for d in result[key]] # Prior to Python 3.10, bisect_left has no `key` argument\n                    i = bisect_left(orders, order)\n                    if i < len(result[key]) and result[key][i][\"order\"] == order:\n                        # a dictionary with the same order already exists\n                        if set(new_dictionary.keys()).issubset({\"order\", \"comment\"}):\n                            # the new dictionary defines nothing: remove the existing dictionary\n                            del result[key][i]\n                        else:\n                            # update the existing dictionary in place\n                            result[key][i].update(new_dictionary)\n                    else:\n                        # insert the new dictionary at the right place\n                        result[key].insert(i, new_dictionary)\n    result.pop(\"parent\", None)\n    return result\n"
  },
  {
    "path": "mocodo/convert/relations.py",
    "content": "import collections\nfrom pathlib import Path\nimport re\n\nfrom mocodo.tools.various import first_missing_positive\n\nfrom ..mocodo_error import MocodoError\nfrom .. import __version__\n\n\ndef set_defaults(template):\n    result = {\n        \"transform_attribute\": [],\n        \"transform_label\": [],\n        \"transform_title\": [],\n        \"transform_datatype\": [],\n        \"transform_optionality\": [],\n        \"label_role_separator\": \" \",\n        \"compose_primary_key\": \"_{label}_\",\n        \"compose_normal_attribute\": \"{label}\",\n        \"compose_foreign_key\": \"#{label}\",\n        \"compose_primary_foreign_key\": \"_#{label}_\",\n        \"add_unicity_constraints\": [],\n        \"add_optionality_constraints\": [],\n        \"transform_relation_name\": [],\n        \"column_separator\": \", \",\n        \"compose_relation\": \"{this_relation_name} ({columns})\",\n        \"deleted_relation_separator\": \"\",\n        \"compose_deleted_relation\": \"\",\n        \"compose_deleted_relations\": \"\",\n        \"transform_forced_relation\": [],\n        \"transform_relation\": [],\n        \"relation_separator\": \"\\n\",\n        \"compose_relational_schema\": \"{relations}\",\n        \"transform_relational_schema\": [],\n    }\n    result.update(template)\n    result.setdefault(\"compose_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_primary_ex_foreign_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_association_attribute\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_association_primary_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_deleted_child_attribute\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_discriminator_\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_discriminator_T\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_discriminator_X\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_discriminator_XT\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_entity_name\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_child_foreign_key\", result[\"compose_foreign_key\"])\n    result.setdefault(\"compose_deleted_parent_discriminator_\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_discriminator_T\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_discriminator_X\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_discriminator_XT\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_attribute\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_foreign_key\", result[\"compose_foreign_key\"])\n    result.setdefault(\"compose_deleted_parent_primary_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_stopped_foreign_key\", result[\"compose_foreign_key\"])\n    result.setdefault(\"compose_outer_attribute\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_outer_primary_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_parent_primary_key\", result[\"compose_primary_foreign_key\"])\n    result.setdefault(\"compose_strengthening_primary_foreign_key\", result[\"compose_primary_foreign_key\"])\n    result.setdefault(\"compose_strengthening_primary_ex_foreign_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_unsourced_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_unsourced_primary_foreign_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_primary_ex_foreign_key\", result[\"compose_primary_key\"])\n    result.setdefault(\"compose_deleted_child_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_deleted_parent_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_stopped_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_unsourced_ex_foreign_key\", result[\"compose_normal_attribute\"])\n    result.setdefault(\"compose_unsourced_primary_ex_foreign_key\", result[\"compose_primary_key\"])\n    return result\n\n\nclass Relations:\n\n    def __init__(self, mcd, params):\n        \n        self.mcd = mcd\n        self.output_stem = Path(params[\"output_name\"]).stem\n        self.ensure_no_reciprocical_relative_entities()\n        self.freeze_strengthening_foreign_key_migration = set()\n        self.relations = {}\n        self.relations_from_entities()\n        self.inheritance_parent_or_children_to_delete = self.find_inheritance_parent_or_children_to_delete()\n        self.strengthen_children()\n        self.strengthen_parents()\n        self.strengthen_weak_identifiers()\n        self.process_associations()\n        self.process_inheritances()\n        self.delete_inheritance_parent_or_children_to_delete()\n        self.delete_deletable_relations()\n        self.make_primary_keys_first()\n        self.relations = dict(sorted(self.relations.items()))\n\n    \n    def get_text(self, template):\n        \n        def transform(string, transformation):\n            for d in template[transformation]:\n                while True:\n                    try:\n                        (string, n) = re.subn(d[\"search\"], d[\"replace\"], str(string))\n                    except:\n                        raise MocodoError(27, _('Cannot compile the regular expression \"{regex}\" or the remplacement string \"{replace}\" in a relation template producing \"*{stem_suffix}.{extension}\" files.').format(regex=d[\"search\"], replace=d[\"replace\"], stem_suffix=template[\"stem_suffix\"], extension=template[\"extension\"])) # fmt: skip\n                    if n == 0 or not d.get(\"iterated\"):\n                        break\n            return string\n        \n        template = set_defaults(template)\n        \n        def make_non_disambiguated_labels_from_attributes():\n            for relation in self.relations.values():\n                for column in relation[\"columns\"]:\n                    column[\"non_disambiguated_label\"] = transform(column[\"attribute\"], \"transform_attribute\")\n        make_non_disambiguated_labels_from_attributes()\n\n        def make_labels_from_non_disambiguated_labels():\n            for relation in self.relations.values():\n                for column in relation[\"columns\"]:\n                    if not column[\"leg_note\"]:\n                        column[\"label\"] = column[\"non_disambiguated_label\"]\n                    elif column[\"leg_note\"].startswith(\"-\"):\n                        column[\"label\"] = column[\"leg_note\"][1:]\n                    elif column[\"leg_note\"].startswith(\"+\"):\n                        column[\"label\"] = column[\"non_disambiguated_label\"] + column[\"leg_note\"][1:]\n                    elif \" \" in column[\"leg_note\"]:\n                        column[\"label\"] = column[\"non_disambiguated_label\"]\n                    else:\n                        column[\"label\"] = column[\"non_disambiguated_label\"] + template[\"label_role_separator\"] + column[\"leg_note\"]\n            # After labels have been disambiguated by roles, ensure all of them are distinct.\n            for relation in self.relations.values():\n                occurrences = collections.Counter(column[\"label\"] for column in relation[\"columns\"])\n                occurrences = dict(c for c in occurrences.items() if c[1] > 1)\n                for column in reversed(relation[\"columns\"]):\n                    if column[\"label\"] in occurrences and column[\"nature\"] != \"primary_key\":\n                        occurrences[column[\"label\"]] -= 1\n                        column[\"label\"] = column[\"label\"] + template[\"label_role_separator\"] + str(occurrences[column[\"label\"]] + 1)\n        make_labels_from_non_disambiguated_labels()\n\n        def transform_labels(): # after labels have been disambiguated by roles\n            for relation in self.relations.values():\n                for column in relation[\"columns\"]:\n                    column[\"label\"] = transform(column[\"label\"], \"transform_label\")\n        transform_labels()\n    \n        def add_fillers():\n            for relation in self.relations.values():\n                label_max_length = max(len(column[\"label\"]) for column in relation[\"columns\"])\n                for column in relation[\"columns\"]:\n                    column[\"filler\"] = \" \" * (label_max_length - len(column[\"label\"]) + 1)\n        add_fillers()\n\n        data = {}\n        data[\"stem\"] = self.output_stem\n        data[\"title\"] = transform(self.mcd.title, \"transform_title\")\n        data[\"version\"] = __version__\n        lines = []\n        for (__, relation) in sorted(self.relations.items()): # For the double underscore, see __main__.py\n            data[\"this_relation_name\"] = transform(relation[\"this_relation_name\"], \"transform_relation_name\")\n            data[\"is_forced\"] = relation[\"is_forced\"]\n            fields = []\n            for column in relation[\"columns\"]:\n                column[\"datatype\"] = transform(column[\"datatype\"], \"transform_datatype\")\n                column[\"optionality\"] = transform(column[\"optionality\"], \"transform_optionality\")\n                data.update(column)\n                field = template[\"compose_%s\" % column[\"nature\"]].format(**data)\n                if column[\"unicities\"]:\n                    field = transform(field, \"add_unicity_constraints\").format(**data)\n                if column[\"optionality\"]:\n                    field = transform(field, \"add_optionality_constraints\").format(**data)\n                fields.append(field)\n            data[\"columns\"] = template[\"column_separator\"].join(fields)\n            line = template[\"compose_relation\"].format(**data)\n            if relation[\"is_forced\"]:\n                line = transform(line, \"transform_forced_relation\")\n            line = transform(line, \"transform_relation\")\n            lines.append(line)\n        if template.get(\"stem_suffix\") == \"_mld\" and template.get(\"extension\") == \"mcd\": # relational diagram\n            lines = self.map_mcd_layout_onto_mld(lines)\n        data[\"relations\"] = template[\"relation_separator\"].join(lines)\n\n        if self.deleted_relations:\n            lines = []\n            for deleted_relation in self.deleted_relations:\n                lines.append(template[\"compose_deleted_relation\"].format(this_relation_name=deleted_relation))\n            deleted_relation_lines = template[\"deleted_relation_separator\"].join(lines)\n            data[\"deleted_relations\"] = template[\"compose_deleted_relations\"].format(deleted_relation_lines=deleted_relation_lines)\n        else:\n            data[\"deleted_relations\"] = \"\"\n\n        data[\"relations\"] = template[\"compose_relational_schema\"].format(**data)\n        result = transform(data[\"relations\"], \"transform_relational_schema\")\n        return result\n\n\n    # private\n\n    def map_mcd_layout_onto_mld(self, lines):\n        rows = [[]]\n        all_commas = [True] * self.mcd.col_count\n        for row in self.mcd.rows:\n            for (i, box) in enumerate(row):\n                for line in lines:\n                    if line.startswith(box.name_view + \":\"):\n                        rows[-1].append(line)\n                        all_commas[i] = False\n                        break\n                else:\n                    rows[-1].append(\":\")\n            rows.append([])\n        rows.pop()\n        for row in rows:\n            row[:] = [x for (x, all_comma) in zip(row, all_commas) if not all_comma]\n        lines = []\n        for row in rows:\n            lines.append(\":\")\n            for x in row:\n                lines.append(x)\n                lines.append(\":\")\n            lines.append(\"\\n\")\n        lines.pop()\n        return lines\n\n    def may_retrieve_distant_leg_note(self, leg, attribute):\n        if leg.entity_bid in self.inheritance_parent_or_children_to_delete:\n            for d in self.relations[leg.entity.bid][\"columns\"]:\n                if all(d[k] == attribute[k] for k in (\"attribute\", \"adjacent_source\", \"association_name\")):\n                    return d[\"leg_note\"]\n        return leg.note\n\n    def may_retrieve_distant_outer_source(self, leg, attribute):\n        if leg.entity_bid in self.inheritance_parent_or_children_to_delete:\n            for d in self.relations[leg.entity_bid][\"columns\"]:\n                if d[\"attribute\"] == attribute[\"attribute\"] and d[\"adjacent_source\"] == attribute[\"adjacent_source\"]:\n                    return d[\"outer_source\"]\n        return leg.entity.name_view\n\n    def ensure_no_reciprocical_relative_entities(self):\n        for association in self.mcd.associations.values():\n            if association.is_invisible:\n                continue\n            weak_count = 0\n            for leg in association.legs:\n                if leg.kind == \"strengthening\":\n                    weak_count += 1\n                    if weak_count == 2:\n                        raise MocodoError(11, _('Reciprocal relative identification around {association}.').format(association=association.bid)) # fmt: skip\n\n    @staticmethod\n    def pop_optionality_from_datatype(attribute, is_primary = False):\n        (datatype, n) = re.subn(r\"(?i) *\\bnot +null\\b *\", \" \", attribute.datatype)\n        attribute.datatype = datatype.strip() # suppress the NOT NULL, if any\n        if n: # A NOT NULL has been suppressed\n            return \"!\" # the attribute is mandatory (as explicitely stated)\n        (datatype, n) = re.subn(r\"(?i) *\\bnull\\b *\", \" \", attribute.datatype)\n        attribute.datatype = datatype.strip() # suppress the NULL, if any\n        if is_primary:\n            return \"!\" # the attribute is mandatory (even if not explicitely stated)\n        if n: # A NULL has been suppressed\n            return \"?\" # the attribute is optional (as explicitely stated)\n        return \"\" # the attribute is neither optional nor mandatory\n\n    def relations_from_entities(self):\n        for (name, entity) in self.mcd.entities.items():\n            if entity.is_invisible:\n                continue\n            self.relations[name] = {\n                \"this_relation_name\": entity.name_view,\n                \"is_forced\": False, # an entity naturally results in a relation. No need to force it.\n                \"is_protected\": entity.is_protected,\n                \"columns\": [],\n                \"existing_unicity_numbers\": set(),\n            }\n            for attribute in entity.attributes:\n                if attribute.label.strip() == \"\":\n                    continue # ignore empty attributes\n                nature = \"primary_key\" if attribute.kind in (\"strong\", \"weak\") else \"normal_attribute\"\n                unicities = \"\".join(c for c in sorted(attribute.id_groups) if c != \"0\")\n                is_primary = (nature == \"primary_key\")\n                optionality = self.pop_optionality_from_datatype(attribute, is_primary)\n                self.relations[name][\"columns\"].append({\n                    \"attribute\": attribute.label,\n                    \"optionality\": optionality,\n                    \"datatype\": attribute.datatype,\n                    \"adjacent_source\": None,\n                    \"outer_source\": None,\n                    \"association_name\": None,\n                    \"leg_note\": None,\n                    \"is_primary\": is_primary,\n                    \"nature\": nature,\n                    \"unicities\": unicities,\n                })\n                self.relations[name][\"existing_unicity_numbers\"].update(map(int, unicities))\n\n    def strengthen_weak_identifiers(self):\n        for entity in self.mcd.entities.values():\n            entity.is_strong_or_strengthened = not entity.strengthening_legs\n        remaining_entities = [entity for entity in self.mcd.entities.values() if not entity.is_strong_or_strengthened and not entity.is_invisible]\n        while remaining_entities:\n            for entity in remaining_entities:\n                strengthening_entities_via_associations = []\n                for strengthening_leg in entity.strengthening_legs:\n                    association = strengthening_leg.association\n                    for other_leg in association.legs:\n                        other_entity = other_leg.entity\n                        if other_entity == entity:\n                            continue\n                        if not other_entity.is_strong_or_strengthened:\n                            break # weak entity linked to a weak entity\n                        strengthening_entities_via_associations.append((other_entity, association))\n                    else:\n                        continue\n                    break\n                if strengthening_entities_via_associations:\n                    for (strengthening_entity, association) in strengthening_entities_via_associations:\n                        # find the potential note on the strengthening leg\n                        for leg in association.legs:\n                            if leg.entity_bid == strengthening_entity.bid:\n                                leg_note = leg.note\n                                break\n                        else:\n                            leg_note = None\n                        \n                        # Patch for #118: if a child disappears but strengthens a weak entity, the outer source\n                        # of this entity must be the outer source of this child. Otherwise, the relational diagram\n                        # will contains the reference: #parent_id > CHILD > parent_id where CHILD no more exists.\n                        # This doesn't fix #119: in the case of cascading inheritance, the outer source should be\n                        # searched in the parent of the parent, etc.\n                        outer_source = strengthening_entity.name_view\n                        if strengthening_entity.bid in self.inheritance_parent_or_children_to_delete:\n                            for attribute in self.relations[leg.entity_bid][\"columns\"]:\n                                if attribute[\"is_primary\"]:\n                                    outer_source = attribute[\"outer_source\"]\n                                    break\n\n                        # migrate the whole primary key of the strengthening entity into the weak one\n                        self.relations[entity.bid][\"columns\"][0:0] = [{\n                                \"attribute\": attribute[\"attribute\"],\n                                \"optionality\": \"!\",\n                                \"datatype\": attribute[\"datatype\"],\n                                \"adjacent_source\": strengthening_entity.name_view,\n                                \"outer_source\": outer_source,\n                                \"association_name\": association.name_view,\n                                \"leg_note\": leg_note,\n                                \"is_primary\": True,\n                                \"nature\": \"strengthening_primary_foreign_key\",\n                                \"unicities\": \"\",\n                            } for attribute in self.relations[strengthening_entity.bid][\"columns\"] if attribute[\"is_primary\"]]\n                        self.freeze_strengthening_foreign_key_migration.add((entity.bid, association.bid, strengthening_entity.bid))\n                    remaining_entities.remove(entity)\n                    entity.is_strong_or_strengthened = True\n                    break\n            else:\n                if len(remaining_entities) == 1:\n                    raise MocodoError(16, _('A weak entity (here, {entity}) cannot be strengthened by itself.').format(entity=remaining_entities[0].bid)) # fmt: skip\n                else:\n                    remaining_entity_names = \", \".join('\"%s\"' % entity.raw_name for entity in remaining_entities)\n                    raise MocodoError(17, _('Cycle of weak entities in {entities}.').format(entities=remaining_entity_names)) # fmt: skip\n\n    def find_inheritance_parent_or_children_to_delete(self):\n        result = set()\n        for inheritance in self.mcd.inheritances:\n            parent_leg = inheritance.legs[0]\n            if inheritance.kind in (\"<-\", \"<=\"):\n                for child_leg in inheritance.legs[1:]:\n                    result.add(child_leg.entity_bid)\n            elif inheritance.kind == \"=>\":\n                if \"T\" not in inheritance.name_view:\n                    raise MocodoError(25, _('Totality (/T\\\\ or /XT\\\\) is mandatory for \"=>\" inheritance of parent \"{name}\".').format(name=parent_leg.entity_raw_name)) # fmt: skip\n                result.add(parent_leg.entity_bid)\n        return result\n\n    def strengthen_children(self):\n        \"\"\"\n        Migrate the parent's identifier in the children. This is obviously necessary if the parent\n        must disappear (`=>` + totality) or its attributes copied in its children. Otherwise, the\n        children must disappear. But in the case they are connected to other entities, they need\n        an identifier to make possible to apply the remaining rules.\n        \"\"\"\n        for inheritance in self.mcd.inheritances:\n            parent_leg = inheritance.legs[0]\n            to_be_deleted = parent_leg.entity_bid in self.inheritance_parent_or_children_to_delete\n            for child_leg in inheritance.legs[1:]: \n                self.relations[child_leg.entity_bid][\"columns\"][0:0] = [{\n                    \"attribute\": attribute[\"attribute\"],\n                    \"optionality\": \"!\",\n                    \"datatype\": attribute[\"datatype\"],\n                    \"adjacent_source\": parent_leg.entity.name_view,\n                    \"outer_source\": parent_leg.entity.name_view,\n                    \"association_name\": inheritance.name_view,\n                    \"leg_note\": None,\n                    \"is_primary\": True,\n                    \"nature\": \"deleted_parent_primary_key\" if to_be_deleted else \"parent_primary_key\",\n                    \"unicities\": \"\",\n                } for attribute in self.relations[parent_leg.entity_bid][\"columns\"] if attribute[\"is_primary\"]]\n\n    def strengthen_parents(self):\n        \"\"\"\n        Migrate the optional children's discriminators in their parent when it disappears (totality + =>).\n        In this case, this discriminator should further migrate with the identifier of the parent.\n        \"\"\"\n        for inheritance in self.mcd.inheritances:\n            if inheritance.kind == \"=>\":\n                parent_leg = inheritance.legs[0]\n                self.relations[parent_leg.entity_bid][\"columns\"].extend({ \n                    \"attribute\": attribute.label,\n                    \"optionality\": \"!\" if 'T' in inheritance.name_view else \"?\",\n                    \"datatype\": attribute.datatype or \"UNSIGNED_INT_PLACEHOLDER\",\n                    \"adjacent_source\": None,\n                    \"outer_source\": None,\n                    \"association_name\": inheritance.name_view,\n                    \"leg_note\": None,\n                    \"is_primary\": False,\n                    \"nature\": f\"deleted_parent_discriminator_{inheritance.name_view}\",\n                    \"unicities\": \"\",\n                } for attribute in inheritance.attributes)\n\n    def process_associations(self):\n        for association in self.mcd.associations.values():\n            if association.is_invisible:\n                continue\n            is_cluster = (association.kind == \"cluster\")\n            df_leg = None\n            for leg in association.legs:\n                if leg.entity.is_invisible:\n                    continue\n                if leg.card[1] == \"1\":\n                    df_leg = leg\n                    if leg.card[0] == \"1\":\n                        break # elect the first leg with cardinality 11\n            \n            if df_leg is None or association.is_protected:\n                # make a relation of this association\n                self.relations[association.bid] = {\n                    \"this_relation_name\": association.name_view,\n                    \"is_forced\": bool(df_leg), # if this association has a 11 leg, being here means it is protected: it must be forced into a relation\n                    \"columns\": [],\n                    \"existing_unicity_numbers\": set(),\n                }\n                for leg in association.legs:\n                    if leg.entity.is_invisible:\n                        continue\n                    for attribute in self.relations[leg.entity_bid][\"columns\"]:\n                        if attribute[\"is_primary\"]:\n                            outer_source = self.may_retrieve_distant_outer_source(leg, attribute)\n                            if is_cluster:\n                                self.relations[association.bid][\"columns\"].append({ # gather all migrant attributes\n                                    \"attribute\": attribute[\"attribute\"],\n                                    \"optionality\": \"!\",\n                                    \"datatype\": attribute[\"datatype\"],\n                                    \"adjacent_source\": leg.entity.name_view,\n                                    \"outer_source\": outer_source,\n                                    \"association_name\": association.name_view,\n                                    \"leg_note\": leg.note,\n                                    \"is_primary\": leg.is_in_elected_group,\n                                    \"nature\": \"primary_foreign_key\" if leg.is_in_elected_group else \"stopped_foreign_key\",\n                                    \"unicities\": leg.unicities,\n                                })\n                                self.relations[association.bid][\"existing_unicity_numbers\"].update(map(int, leg.unicities))\n                            elif association.is_protected and df_leg is not None and leg is not df_leg:\n                                self.relations[association.bid][\"columns\"].append({ # gather all migrant attributes\n                                    \"attribute\": attribute[\"attribute\"],\n                                    \"optionality\": \"!\",\n                                    \"datatype\": attribute[\"datatype\"],\n                                    \"adjacent_source\": leg.entity.name_view,\n                                    \"outer_source\": outer_source,\n                                    \"association_name\": association.name_view,\n                                    \"leg_note\": leg.note,\n                                    \"is_primary\": False,\n                                    \"nature\": \"stopped_foreign_key\",\n                                    \"unicities\": \"\",\n                                })\n                            else:\n                                self.relations[association.bid][\"columns\"].append({ # gather all migrant attributes\n                                    \"attribute\": attribute[\"attribute\"],\n                                    \"optionality\": \"!\",\n                                    \"datatype\": attribute[\"datatype\"],\n                                    \"adjacent_source\": leg.entity.name_view,\n                                    \"outer_source\": outer_source,\n                                    \"association_name\": association.name_view,\n                                    \"leg_note\": leg.note,\n                                    \"is_primary\": True,\n                                    \"nature\": \"unsourced_primary_foreign_key\" if outer_source is None else \"primary_foreign_key\",\n                                    \"unicities\": \"\",\n                                })\n                        elif attribute[\"nature\"].startswith(\"deleted_parent_discriminator\"):\n                            self.relations[association.bid][\"columns\"].append({\n                                \"attribute\": attribute[\"attribute\"],\n                                \"optionality\": \"!\",\n                                \"datatype\": attribute[\"datatype\"],\n                                \"adjacent_source\": leg.entity.name_view,\n                                \"outer_source\": None,\n                                \"association_name\": association.name_view,\n                                \"leg_note\": leg.note,\n                                \"is_primary\": False,\n                                \"nature\": attribute[\"nature\"],\n                                \"unicities\": \"\",\n                            })\n                self.relations[association.bid][\"columns\"].extend({ # and the attributes already existing in the association\n                        \"attribute\": attribute.label,\n                        \"optionality\": \"!\" if attribute.kind == \"strong\" else self.pop_optionality_from_datatype(attribute),\n                        \"datatype\": attribute.datatype,\n                        \"adjacent_source\": None,\n                        \"outer_source\": None,\n                        \"association_name\": association.name_view,\n                        \"leg_note\": None,\n                        \"is_primary\": attribute.kind == \"strong\",\n                        \"nature\": \"association_primary_key\" if attribute.kind == \"strong\" else \"association_attribute\",\n                        \"unicities\": \"\",\n                    } for attribute in association.attributes if attribute.label.strip() != \"\"\n                )\n                continue\n\n            # No relation will be created from this association.\n\n            # Check the number of /?1 legs (pegs)\n            df_pegs = []\n            for leg in association.legs:\n                if leg.entity.is_invisible:\n                    continue\n                if leg.card[1] == \"1\" and leg.kind == \"cluster_peg\":\n                    df_pegs.append(leg)\n            \n            if df_pegs: # A cluster with at least one /?1 leg (peg)\n                for df_peg in df_pegs:\n                    # All migrating attribute must belong to the same new unicity group\n                    unicities = str(first_missing_positive(self.relations[df_peg.entity_bid][\"existing_unicity_numbers\"]))\n                    self.relations[df_leg.entity_bid][\"existing_unicity_numbers\"].update(map(int, unicities))\n                    for leg in association.legs:\n                        if leg is df_peg:\n                            continue\n                        for attribute in list(self.relations[leg.entity_bid][\"columns\"]): # traverse a copy...\n                            # ... to prevent an infinite migration of the child discriminator\n                            if attribute[\"is_primary\"]:\n                                # Their primary keys must migrate in `entity_name`.\n                                outer_source = self.may_retrieve_distant_outer_source(leg, attribute)\n                                self.relations[df_peg.entity_bid][\"columns\"].append({\n                                    \"attribute\": attribute[\"attribute\"],\n                                    \"optionality\": \"!\",\n                                    \"datatype\": attribute[\"datatype\"],\n                                    \"adjacent_source\": leg.entity.name_view,\n                                    \"outer_source\": outer_source,\n                                    \"association_name\": association.name_view,\n                                    \"leg_note\": leg.note,\n                                    \"is_primary\": False,\n                                    \"nature\": \"unsourced_foreign_key\" if outer_source is None else \"foreign_key\",\n                                    \"unicities\": unicities,\n                                    # NB: technically, an unsourced foreign key is not foreign anymore\n                                })\n                # The association attributes must migrate only once, df_leg is elected.\n                # Delay the addition of the association attributes after the else part.\n\n            else:\n                # A normal DF association. Traverse the other legs to find the attributes to migrate.\n                for leg in association.legs:\n                    if leg.entity.is_invisible:\n                        continue\n                    if leg is not df_leg:\n                        if (df_leg.entity_bid, association.bid, leg.entity_bid) not in self.freeze_strengthening_foreign_key_migration:\n                            unicities = \"\"\n                            if leg.card[1] == \"1\": # *1 --(DF)-- 11 => the migrating attribute must be made unique, find a new unicity group\n                                unicities = str(first_missing_positive(self.relations[df_leg.entity_bid][\"existing_unicity_numbers\"]))\n                            for attribute in list(self.relations[leg.entity_bid][\"columns\"]): # traverse a copy...\n                                # ... to prevent an infinite migration of the child discriminator\n                                optionality = \"!\" if df_leg.card[0] == \"1\" else \"?\"\n                                if attribute[\"is_primary\"]:\n                                    # Their primary keys must migrate in df_leg.entity_bid.\n                                    outer_source = self.may_retrieve_distant_outer_source(leg, attribute)\n                                    self.relations[df_leg.entity_bid][\"columns\"].append({\n                                        \"attribute\": attribute[\"attribute\"],\n                                        \"optionality\": optionality,\n                                        \"datatype\": attribute[\"datatype\"],\n                                        \"adjacent_source\": leg.entity.name_view,\n                                        \"outer_source\": outer_source,\n                                        \"association_name\": association.name_view,\n                                        \"leg_note\": leg.note,\n                                        \"is_primary\": False,\n                                        \"nature\": \"unsourced_foreign_key\" if outer_source is None else \"foreign_key\",\n                                        \"unicities\": unicities,\n                                        # NB: technically, an unsourced foreign key is not foreign anymore\n                                    })\n                                    self.relations[df_leg.entity_bid][\"existing_unicity_numbers\"].update(map(int, unicities))\n                                elif attribute[\"nature\"].startswith(\"deleted_parent_discriminator\"):\n                                    self.relations[df_leg.entity_bid][\"columns\"].append({\n                                        \"attribute\": attribute[\"attribute\"],\n                                        \"optionality\": optionality,\n                                        \"datatype\": attribute[\"datatype\"],\n                                        \"adjacent_source\": leg.entity.name_view,\n                                        \"outer_source\": None,\n                                        \"association_name\": association.name_view,\n                                        \"leg_note\": leg.note,\n                                        \"is_primary\": False,\n                                        \"nature\": attribute[\"nature\"],\n                                        \"unicities\": \"\",\n                                    })\n                \n            # Add the attributes already existing in the association\n            self.relations[df_leg.entity_bid][\"columns\"].extend([{\n                    \"attribute\": attribute.label,\n                    \"optionality\": \"!\" if attribute.kind == \"strong\" else self.pop_optionality_from_datatype(attribute),\n                    \"datatype\": attribute.datatype,\n                    \"association_name\": association.name_view,\n                    \"adjacent_source\": None,\n                    \"outer_source\": None,\n                    \"leg_note\": None,\n                    \"is_primary\": attribute.kind == \"strong\",\n                    \"nature\": \"outer_primary_key\" if attribute.kind == \"strong\" else \"outer_attribute\",\n                    \"unicities\": \"\",\n                } for attribute in association.attributes if attribute.label.strip() != \"\"])\n\n\n    def process_inheritances(self):\n        for inheritance in self.mcd.inheritances:\n            parent_leg = inheritance.legs[0]\n            if inheritance.kind == \"=>\": # total migration: parent > children\n                for child_leg in inheritance.legs[1:]: \n                    # migrate the parent's attributes, except those of nature \"deleted_parent_discriminator\"\n                    self.relations[child_leg.entity_bid][\"columns\"][0:0] = [{\n                        \"attribute\": attribute[\"attribute\"],\n                        \"optionality\": attribute[\"optionality\"],\n                        \"datatype\": attribute[\"datatype\"],\n                        \"adjacent_source\": parent_leg.entity.name_view,\n                        \"outer_source\": self.may_retrieve_distant_outer_source(parent_leg, attribute),\n                        \"association_name\": inheritance.name_view,\n                        \"leg_note\": self.may_retrieve_distant_leg_note(parent_leg, attribute),\n                        \"is_primary\": False,\n                        \"nature\": \"deleted_parent_foreign_key\" if attribute[\"nature\"] == \"foreign_key\" else \"deleted_parent_attribute\",\n                        \"unicities\": \"\",\n                    } for attribute in self.relations[parent_leg.entity_bid][\"columns\"] if not attribute[\"is_primary\"] and not attribute[\"nature\"].startswith(\"deleted_parent_discriminator\")]\n            else: # migration: triangle attributes > parent\n                self.relations[parent_leg.entity_bid][\"columns\"].extend({ \n                    \"attribute\": attribute.label,\n                    \"optionality\": \"!\" if 'T' in inheritance.name_view else \"?\",\n                    \"datatype\": attribute.datatype or \"UNSIGNED_INT_PLACEHOLDER\",\n                    \"adjacent_source\": None,\n                    \"outer_source\": None,\n                    \"association_name\": inheritance.name_view,\n                    \"leg_note\": None,\n                    \"is_primary\": False,\n                    \"nature\": f\"deleted_child_discriminator_{inheritance.name_view}\", # \"\", \"X\", \"T\" or \"XT\"\n                    \"unicities\": \"\",\n                } for attribute in inheritance.attributes)\n                if inheritance.kind in (\"<-\", \"<=\"): # migration: children > parent, and suppress children\n                    for child_leg in inheritance.legs[1:]:\n                        if inheritance.kind == \"<=\":\n                            # make the child's name a boolean attribute of the parent\n                            self.relations[parent_leg.entity_bid][\"columns\"].append({\n                                \"attribute\": _('is {name}').format(name=child_leg.entity_bid.lower()),\n                                \"optionality\": \"!\",\n                                \"datatype\": \"BOOLEAN_PLACEHOLDER\",\n                                \"adjacent_source\": child_leg.entity.name_view,\n                                \"outer_source\": child_leg.entity.name_view,\n                                \"association_name\": inheritance.name_view,\n                                \"leg_note\": None,\n                                \"is_primary\": False,\n                                \"nature\": \"deleted_child_entity_name\",\n                                \"unicities\": \"\",\n                            })\n                        # migrate all child's attributes\n                        for attribute in self.relations[child_leg.entity_bid][\"columns\"]:\n                            if attribute[\"nature\"].endswith(\"parent_primary_key\"):\n                                continue # except the \"strengthening\" parent identifier\n                            self.relations[parent_leg.entity_bid][\"columns\"].append({\n                                \"attribute\": attribute[\"attribute\"],\n                                \"optionality\": \"?\",\n                                \"datatype\": attribute[\"datatype\"],\n                                \"adjacent_source\": child_leg.entity.name_view,\n                                \"outer_source\": self.may_retrieve_distant_outer_source(child_leg, attribute),\n                                \"association_name\": inheritance.name_view,\n                                \"leg_note\": self.may_retrieve_distant_leg_note(child_leg, attribute),\n                                \"is_primary\": False,\n                                \"nature\": \"deleted_child_foreign_key\" if attribute[\"nature\"] == \"foreign_key\" else \"deleted_child_attribute\",\n                                \"unicities\": \"\",\n                            })\n    \n    def delete_inheritance_parent_or_children_to_delete(self):\n        for entity_to_delete in self.inheritance_parent_or_children_to_delete:\n            del self.relations[entity_to_delete]\n\n    def delete_deletable_relations(self):\n        deleted_outer_sources = set()\n        for (bid, relation) in list(self.relations.items()):\n            if not relation.get(\"is_protected\") and all(column[\"nature\"] == \"primary_key\" for column in relation[\"columns\"]):\n                del self.relations[bid]\n                deleted_outer_sources.add(relation[\"this_relation_name\"])\n        for relation in self.relations.values():\n            for column in relation[\"columns\"]:\n                if column[\"outer_source\"] in deleted_outer_sources:\n                    column[\"nature\"] = column[\"nature\"].replace(\"foreign\", \"ex_foreign\")\n        self.deleted_relations = sorted(deleted_outer_sources)\n\n    def make_primary_keys_first(self):\n        for relation in self.relations.values():\n            relation[\"columns\"].sort(key=lambda column: not column[\"is_primary\"])\n"
  },
  {
    "path": "mocodo/dev/json_to_yaml_templates.py",
    "content": "from pathlib import Path\nfrom json import loads\n\ndef repr_single(s):\n    \"\"\"repr() but with single quotes\"\"\"\n    return \"'\" + repr('\"' + s)[2:]\n\ndef convert(source_path, target_path):\n    for path in sorted(source_path.glob(\"*.json\"), reverse=True):\n        print(path)\n        data = loads(path.read_text(encoding=\"utf8\"))\n        result = []\n        for (key, stuff) in data.items():\n            if isinstance(stuff, str):\n                stuff = repr_single(stuff).replace(r\"\\\\\", \"\\\\\").replace(\"\\\\'\", \"''\")\n                result.append(f\"{key}: {stuff}\")\n            elif isinstance(stuff, list):\n                result.append(f\"{key}:\")\n                for d in stuff:\n                    sub_result = []\n                    for (k, v) in d.items():\n                        if isinstance(v, str):\n                            v = repr_single(v).replace(r\"\\\\\", \"\\\\\").replace(\"\\\\'\", \"''\")\n                        else:\n                            v = str(v)\n                        sub_result.append(f\"{k}: {v}\")\n                    result.append(\"  - \" + \"\\n    \".join(sub_result))\n            elif isinstance(stuff, bool):\n                result.append(f\"{key}: {str(stuff).lower()}\")\n            elif stuff is None:\n                result.append(f\"{key}: null\")\n            else:\n                result.append(f\"{key}: {stuff}\")\n        result.append(\"\")\n        dest = Path(target_path, path.stem + \".yaml\")\n        dest.write_text(\"\\n\".join(result), encoding=\"utf8\")\n\nif __name__ == \"__main__\":\n    convert(Path(\"test/test_data/templates\"), Path(\"test/test_data/new_templates\"))\n"
  },
  {
    "path": "mocodo/dev/update_sql_reserved_words.py",
    "content": "from pathlib import Path\nimport re\nimport requests\n\nurl = \"https://modern-sql.com/reserved-words-empirical-list.html\"\ntext = requests.get(url).text\n\nwords = {}\nfor (y, word) in re.findall(r'y=\"(\\d+)\"><tspan class=\"code.*?\">(.+?)</tspan>', text):\n    words[str(int(y) - 14)] = word\n\nwords_by_dialect = {}\ndialect = None\nfor chunk in text.split('<g class=\"hoverable\">'):\n    if m := re.search(r'rotate\\(-45\\)\">(.+?)</text>', chunk):\n        dialect = m[1]\n        words_by_dialect[dialect] = []\n        for (href, y) in re.findall(r'<use href=\"#(.+?)\" transform=\"translate\\(\\d+,(\\d+)\\)\"/>', chunk):\n            if href != \"none\":\n                words_by_dialect[dialect].append(words[y])\n\ndialects = {\n    \"Apache Derby\": \"\",\n    \"BigQuery\": \"\",\n    \"Db2 (LUW)\": \"\",\n    \"H2\": \"\",\n    \"MariaDB\": \"\",\n    \"MySQL\": \"mysql.yaml\",\n    \"Oracle DB\": \"oracle.yaml\",\n    \"PostgreSQL\": \"postgresql.yaml\",\n    \"SQL Server\": \"mssql.yaml\",\n    \"SQLite\": \"sqlite.yaml\",\n}\n\nfor (dialect, filename) in dialects.items():\n    if not filename:\n        continue\n    alternative = \"|\".join(words_by_dialect[dialect])\n    path = Path(\"mocodo\", \"resources\", \"relation_templates\", filename)\n    text = path.read_text(encoding=\"utf8\")\n    text = re.sub(r\"('Protect reserved keywords'\\n    search: ).+\", fr\"\\1'(?i)^({alternative})$'\", text)\n    path.write_text(text, encoding=\"utf8\")\n    print(f\"{filename} updated.\")\n"
  },
  {
    "path": "mocodo/dev/update_transfo_metadata.py",
    "content": "from pathlib import Path\nfrom collections import defaultdict\nimport json\nimport os\n\nfrom mocodo.argument_parser import init_localization, Transformations\nfrom mocodo.tools import load_mini_yaml\n\n# Build the index of templates\n\nfolder = Path(f\"mocodo/resources/relation_templates\")\naliases = defaultdict(list)\nmetadata = defaultdict(dict)\nfor path in sorted(folder.glob(\"*.yaml\")):\n    if \"-\" in path.name:\n        continue\n    data = load_mini_yaml.run(path)\n    if \"help_en\" in data:\n        metadata[path.stem] = {\n            \"category\": \"cv\",\n            \"help_en\": data[\"help_en\"],\n            \"help_fr\": data[\"help_fr\"],\n            \"help_zh\": data[\"help_zh\"],\n            \"aliases\": [],\n        }\n        if \"fr_examples\" in data:\n            fr_examples = {}\n            for d in data[\"fr_examples\"]:\n                fr_examples[d[\"example\"]] = d[\"explanation\"]\n            metadata[path.stem][\"fr_examples\"] = fr_examples\n    elif \"parent\" in data:\n        aliases[data[\"parent\"]].append(path.stem)\n    for (parent, children) in aliases.items():\n        metadata[parent][\"aliases\"] = children\nresult = json.dumps(metadata, indent=2, ensure_ascii=False)\nresult = result.replace(\"[\\n      \", \"[\")\nresult = result.replace(\"\\n    ]\", \"]\")\nresult = result.replace(\",\\n      \", \", \")\nPath(folder, \"_index.json\").write_text(result + \"\\n\", encoding=\"utf8\")\nprint(f\"File written: {folder}/_index.json\")\n\n# Build the graph of templates\n\nedges = []\nfor path in sorted(folder.glob(\"*.yaml\")):\n    data = load_mini_yaml.run(path)\n    data.pop(\"help_fr\", None)\n    data.pop(\"help_en\", None)\n    data.pop(\"fr_examples\", None)\n    color = min(9, len(data))\n    font_color = \"white\" if color > 5 else \"black\"\n    if \"parent\" in data:\n        edges.append(f'\"{data[\"parent\"]}\" -> \"{path.stem}\"')\n    edges.append(f'\"{path.stem}\" [fillcolor={color} fontcolor={font_color}]')\nedges = \"\\n  \".join(edges)\nresult = f'digraph G {{\\n  rankdir=LR\\n  edge [dir=\"back\"]\\n  node [shape=box style=\"rounded,filled\" colorscheme=reds9 fontname=\"Arial\" penwidth=0]\\n  {edges}\\n}}\\n'\npath = Path(folder, \"_graph.gv\")\npath.write_text(result, encoding=\"utf8\")\nos.system(f\"dot -Tsvg {folder}/_graph.gv > {folder}/_graph.svg\")\npath.unlink()\nprint(f\"File written: {folder}/_graph.svg\")\n\n# Build the cheat sheet\n\ninit_localization(\"fr\")\nmetadata = Transformations(\"fr\").metadata\ntables = {}\nfor category in [\"rw\", \"cv\"]:\n    rows = []\n    rows.append((\"Sous-option\", \"Description\", \"Exemples\", \"Explications\"))\n    rows.append((\":--\", \":--\", \":--\", \":--\"))\n    for (option, data) in sorted(metadata.items()):\n        if data[\"category\"] != category:\n            continue\n        title = f\" title=\\\"Alias : {', '.join(data['aliases'])}.\\\"\" if data.get(\"aliases\") else \"\"\n        option = f'<span{title} style=\"font-family:monospace; font-weight:600\">{option}</span>'\n        row = [option, data['help']]\n        if not data.get(f\"fr_examples\"):\n            rows.append(row + [\"\", \"\"])\n            continue\n        for (example, description) in data[f\"fr_examples\"].items():\n            example = example.replace(\"\\n\", \"\\\\n\")\n            example = f\"`` {example} ``\"\n            row.extend([example, description])\n            rows.append(row)\n            row = [\"\", \"\"]  # empty cells for the first two columns\n    tables[category] = \"\\n\".join(\"| \" + \" | \".join(row) + \" |\" for row in rows)\ntext = f\"\"\"\n### Opérations de conversion\n\n{tables['cv']}\n\n### Opérations de réécriture\n\n{tables['rw']}\n\"\"\".strip()\noutput_path = Path(\"doc/fr_cheat_sheet.md\")\noutput_path.write_text(text, encoding=\"utf8\")\nprint(f\"File written: {output_path}\")\n"
  },
  {
    "path": "mocodo/diagram_link.py",
    "content": "from .mocodo_error import MocodoError\n\n\nclass DiagramLink:\n    def __init__(self, entities, foreign_entity, foreign_key):\n        self.foreign_entity = foreign_entity\n        self.foreign_key = foreign_key\n        try:\n            self.primary_entity = entities[foreign_key.primary_entity_bid]\n        except KeyError:\n            raise MocodoError(14, _('Attribute \"{attribute}\" in entity \"{entity_1}\" references an unknown entity \"{entity_2}\".').format(attribute=foreign_key.label, entity_1=foreign_entity.bid, entity_2=foreign_key.primary_entity_bid)) # fmt: skip\n        for candidate in self.primary_entity.attributes:\n            if candidate.label.lstrip(\"#\") == foreign_key.primary_key_label.lstrip(\"#\"):\n                self.primary_key = candidate\n                break\n        else:\n            raise MocodoError(15, _('Attribute \"{attribute_1}\" in entity \"{entity_1}\" references an unknown attribute \"{attribute_2}\" in entity \"{entity_2}\".').format(attribute_1=foreign_key.label, entity_1=foreign_entity.bid, attribute_2=foreign_key.primary_key_label, entity_2=foreign_key.primary_entity_bid)) # fmt: skip\n\n    def calculate_size(self, style, *ignored):\n        self.fdx = self.foreign_entity.w // 2\n        self.pdx = self.primary_entity.w // 2\n        self.fdy = (\n            -self.foreign_entity.h // 2\n            + 3 * style[\"rect_margin_height\"]\n            + self.foreign_entity.cartouche_height\n            + (self.foreign_key.rank + 0.5)\n            * (self.foreign_entity.attribute_height + style[\"line_skip_height\"])\n        )\n        self.pdy = (\n            -self.primary_entity.h // 2\n            + 3 * style[\"rect_margin_height\"]\n            + self.primary_entity.cartouche_height\n            + (self.primary_key.rank + 0.5)\n            * (self.primary_entity.attribute_height + style[\"line_skip_height\"])\n        )\n        self.offset = 2 * (style[\"card_margin\"] + style[\"card_max_width\"])\n\n    def description(self, style, geo):\n        result = [(\"comment\", {\"text\": f'Link from \"{self.foreign_key.primary_key_label}\" ({self.foreign_entity.bid}) to \"{self.primary_key.label}\" ({self.primary_entity.bid})'})]\n        spins = (\n            [(-1, -1), (1, -1), (-1, 1), (1, 1)]\n            if self.foreign_key.rank % 2\n            else [(1, 1), (-1, 1), (1, -1), (-1, -1)]\n        )\n        (fs, ps) = min(\n            spins,\n            key=lambda fs_ps: abs(\n                geo[\"cx\"][self.foreign_entity.bid]\n                + self.fdx * fs_ps[0]\n                - geo[\"cx\"][self.primary_entity.bid]\n                - self.pdx * fs_ps[1]\n            ),\n        )\n        xf = geo[\"cx\"][self.foreign_entity.bid] + self.fdx * fs\n        yf = geo[\"cy\"][self.foreign_entity.bid] + self.fdy\n        xp = geo[\"cx\"][self.primary_entity.bid] + self.pdx * ps\n        yp = geo[\"cy\"][self.primary_entity.bid] + self.pdy\n        result.append(\n            (\n                \"curve\",\n                {\n                    \"x0\": xf,\n                    \"y0\": yf,\n                    \"x1\": xf + (xp - xf) / 2 if fs != ps else xf + self.offset * fs,\n                    \"y1\": yf + (yp - yf) / 2,\n                    \"x2\": xf + (xp - xf) / 3 if fs != ps else xp + self.offset * ps,\n                    \"y2\": yp,\n                    \"x3\": xp,\n                    \"y3\": yp,\n                    \"stroke_color\": style[\"leg_stroke_color\"],\n                    \"stroke_depth\": style[\"leg_stroke_depth\"],\n                }\n            )\n        )\n        result.append(\n            (\n                \"arrow\",\n                {\n                    \"x0\": xp,\n                    \"y0\": yp,\n                    \"x1\": xp + ps * style[\"arrow_width\"],\n                    \"y1\": yp - ps * style[\"arrow_half_height\"],\n                    \"x2\": xp + ps * style[\"arrow_axis\"],\n                    \"y2\": yp,\n                    \"x3\": xp + ps * style[\"arrow_width\"],\n                    \"y3\": yp + ps * style[\"arrow_half_height\"],\n                    \"stroke_color\": style[\"leg_stroke_color\"],\n                },\n            ),\n        )\n        result.append(\n            (\n                \"circle\",\n                {\n                    \"cx\": xf,\n                    \"cy\": yf,\n                    \"r\": style[\"box_stroke_depth\"],\n                    \"stroke_depth\": style[\"box_stroke_depth\"],\n                    \"stroke_color\": style[\"leg_stroke_color\"],\n                    \"color\": style[\"leg_stroke_color\"],\n                }\n            )\n        )\n        return result\n"
  },
  {
    "path": "mocodo/entity.py",
    "content": "from collections import defaultdict\nfrom .attribute import *\nfrom .tools.string_tools import rstrip_digit_or_underline, raw_to_bid\n\nclass Entity:\n    def __init__(self, clause):\n        self.source = clause[\"source\"]\n        self.raw_name = clause[\"name\"]\n        # A protected entity results in a table, even if all its columns are part of its primary key.\n        self.is_protected = (clause.get(\"box_def_prefix\") == \"+\")\n        self.bid = raw_to_bid(self.raw_name)\n        self.name_view = rstrip_digit_or_underline(self.raw_name)\n        self.attributes = clause.get(\"attrs\", [])\n        self.legs = []  # iterating over box's legs does nothing if it is not an association\n        self.kind = \"entity\"\n        if clause.get(\"box_def_prefix\") == \"-\":\n            self.calculate_size = self.calculate_size_when_invisible\n            self.description = lambda *ignored: []\n            self.is_invisible = True\n        else:\n            self.calculate_size = self.calculate_size_when_visible\n            self.description = self.description_when_visible\n            self.is_invisible = False\n        self.has_alt_identifier = False\n\n    def add_attributes(self, legs_to_strengthen, is_child, fk_format):\n        weak_entity = bool(legs_to_strengthen)\n        self.strengthening_legs = legs_to_strengthen\n        for (i, a) in enumerate(self.attributes):\n            id_mark = a.get(\"id_mark\",\"\")\n            explicit_underscore = \"0\" in a.get(\"id_groups\", \"\") or a.get(\"id_groups\", \"\") == \"\"\n            if a.get(\"attribute_label\", \"\") == \"\":\n                attribute = PhantomAttribute(a)\n            elif is_child:\n                attribute = SimpleEntityAttribute(a)\n            elif i == 0 and id_mark != \"_\":\n                attribute = WeakAttribute(a) if  weak_entity else StrongAttribute(a)\n            elif i == 0 and id_mark == \"_\" and not explicit_underscore:\n                attribute = WeakAttribute(a) if  weak_entity else StrongAttribute(a)\n            elif i != 0 and id_mark == \"_\" and explicit_underscore:\n                attribute = WeakAttribute(a) if  weak_entity else StrongAttribute(a)\n            else:\n                attribute = SimpleEntityAttribute(a)\n            attribute.register_foreign_key_status(a, fk_format)\n            self.attributes[i] = attribute\n        self.candidates = defaultdict(set)\n        for a in self.attributes:\n            for id_group in a.id_groups:\n                self.candidates[id_group].add(a.label)\n        self.candidates = dict(self.candidates)\n        if len(self.candidates) > 1:\n            self.has_alt_identifier = True\n        \n    def register_boxes(self, boxes):\n        self.boxes = boxes\n    \n    def set_id_gutter_visibility(self, is_visible):\n        self.show_id_gutter = is_visible\n    \n    def calculate_size_when_invisible(self, *ignored):\n        self.w = 0\n        self.h = 0\n    \n    def calculate_size_when_visible(self, style, get_font_metrics):\n        cartouche_font = get_font_metrics(style[\"entity_cartouche_font\"])\n        self.get_cartouche_string_width = cartouche_font.get_pixel_width\n        self.cartouche_height = cartouche_font.get_pixel_height()\n        attribute_font = get_font_metrics(style[\"entity_attribute_font\"])\n        self.attribute_height = attribute_font.get_pixel_height()\n        for attribute in self.attributes:\n            attribute.calculate_size(style, get_font_metrics)\n        cartouche_and_attribute_widths = []\n        cartouche_and_attribute_widths.append(self.get_cartouche_string_width(self.name_view))\n        cartouche_and_attribute_widths.extend(a.w for a in self.attributes)\n        self.id_gutter_width = 0\n        if self.show_id_gutter:\n            self.id_gutter_width = 2 * style[\"rect_margin_width\"]\n            if self.attributes:\n                self.id_gutter_width += max(attribute.id_width for attribute in self.attributes)\n        self.w = 2 * style[\"rect_margin_width\"] + self.id_gutter_width + max(cartouche_and_attribute_widths)\n        self.h = (\n            len(self.attributes) * (self.attribute_height + style[\"line_skip_height\"])\n            - style[\"line_skip_height\"]\n            + 4 * style[\"rect_margin_height\"]\n            + self.cartouche_height\n        )\n        self.w += self.w % 2\n        self.h += self.h % 2\n        for attribute in self.attributes:\n            attribute.set_id_gutter_width(self.id_gutter_width)\n\n    def register_center(self, geo):\n        self.cx = geo[\"cx\"][self.bid]\n        self.cy = geo[\"cy\"][self.bid]\n        self.l = self.cx - self.w // 2\n        self.r = self.cx + self.w // 2\n        self.t = self.cy - self.h // 2\n        self.b = self.cy + self.h // 2\n\n    def description_when_visible(self, style, geo):\n        result = []\n        result.append((\"comment\", {\"text\": f\"Entity {self.bid}\"}))\n        result.append(\n            (\n                \"begin_component\",\n                {\n                    \"page\": self.page,\n                    \"visibility\": \"hidden\" if self.page else \"visible\",\n                }\n            )\n        )\n        result.append((\"begin_group\", {}))\n        result.append(\n            (\n                \"rect\",\n                { # upper part background\n                    \"x\": self.l,\n                    \"y\": self.t,\n                    \"w\": self.w,\n                    \"h\": self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                    \"color\": style[\"entity_cartouche_color\"],\n                    \"stroke_color\": \"none\",\n                    \"stroke_depth\": 0,\n                    \"opacity\": 1,\n                },\n            )\n        )\n        result.append(\n            ( # lower part background (with or without a margin for the left gutter)\n                \"rect\",\n                { \n                    \"x\": self.l + self.id_gutter_width,\n                    \"y\": self.t + self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                    \"w\": self.w - self.id_gutter_width,\n                    \"h\": self.h - self.cartouche_height - 2 * style[\"rect_margin_height\"],\n                    \"color\": style[\"entity_color\"],\n                    \"stroke_color\": \"none\",\n                    \"stroke_depth\": 0,\n                    \"opacity\": 1,\n                },\n            )\n        )\n        if self.show_id_gutter:\n            result.append(\n                ( # id_gutter background\n                    \"rect\",\n                    {\n                        \"x\": self.l,\n                        \"y\": self.t + self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                        \"w\": self.id_gutter_width,\n                        \"h\": self.h - self.cartouche_height - 2 * style[\"rect_margin_height\"],\n                        \"color\": style[\"id_gutter_color\"],\n                        \"stroke_color\": \"none\",\n                        \"stroke_depth\": 0,\n                        \"opacity\": 1,\n                    },\n                )\n            )\n            result.append(\n                ( # line at the right of the left gutter\n                    \"line\",\n                    {\n                        \"x0\": self.l + self.id_gutter_width,\n                        \"y0\": self.t + self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                        \"x1\": self.l + self.id_gutter_width,\n                        \"y1\": self.b,\n                        \"stroke_color\": style[\"entity_stroke_color\"],\n                        \"stroke_depth\": style[\"inner_stroke_depth\"] / 4,\n                    },\n                )\n            )\n        result.append(\n            ( # outer frame\n                \"rect\",\n                {\n                    \"x\": self.l,\n                    \"y\": self.t,\n                    \"w\": self.w,\n                    \"h\": self.h,\n                    \"color\": style[\"transparent_color\"],\n                    \"stroke_color\": style[\"entity_stroke_color\"],\n                    \"stroke_depth\": style[\"box_stroke_depth\"],\n                    \"opacity\": 1,\n                },\n            )\n        )\n        result.append(\n            ( # line between upper and lower part\n                \"line\",\n                {\n                    \"x0\": self.l,\n                    \"y0\": self.t + self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                    \"x1\": self.r,\n                    \"y1\": self.t + self.cartouche_height + 2 * style[\"rect_margin_height\"],\n                    \"stroke_color\": style[\"entity_stroke_color\"],\n                    \"stroke_depth\": style[\"inner_stroke_depth\"],\n                },\n            )\n        )\n        result.append((\"end\", {}))\n        result.append(\n            ( # cartouche text\n                \"text\",\n                {\n                    \"x\": self.cx - self.get_cartouche_string_width(self.name_view) // 2,\n                    \"y\": self.t + style[\"rect_margin_height\"] + style[\"cartouche_text_height_ratio\"] * self.cartouche_height,\n                    \"text_color\": style[\"entity_cartouche_text_color\"],\n                    \"family\": style[\"entity_cartouche_font\"][\"family\"],\n                    \"size\": style[\"entity_cartouche_font\"][\"size\"],\n                    \"text\": self.name_view,\n                },\n            )\n        )\n        x = self.cx - self.w // 2 + style[\"rect_margin_width\"]\n        dx = self.id_gutter_width\n        dy = self.cartouche_height + 3 * style[\"rect_margin_height\"] - self.h // 2\n        for attribute in self.attributes:\n            result.extend(attribute.description(style, x, self.cy, dx, dy))\n            dy += self.attribute_height + style[\"line_skip_height\"]\n        result.append((\"end\", {}))\n        return result\n"
  },
  {
    "path": "mocodo/font_metrics.py",
    "content": "import json\nfrom pathlib import Path\n\n\ndef font_metrics_factory(params):\n    class FontMetrics:\n\n        data = json.loads(Path(params[\"script_directory\"]).joinpath(\"resources\").joinpath(\"font_metrics.json\").read_text(encoding=\"utf8\"))\n\n        def __init__(self, font):\n            if font[\"family\"] not in self.data[\"fonts\"]:\n                font[\"family\"] = \"Courier New\"\n            metrics = self.data[\"fonts\"][font[\"family\"]]\n            self.font_height = int(round(metrics[\"height\"] * font[\"size\"] / self.data[\"size\"]))\n            alphabet = self.data[\"alphabet\"]\n            self.width = {c: ord(x) for (c, x) in zip(alphabet, metrics.get(\"widths\", []))}\n            self.default_width = metrics[\"default\"]\n            self.ratio = font[\"size\"] * metrics.get(\"correction\", 1) / self.data[\"size\"]\n            self.ratio *= params[\"adjust_width\"]\n\n        def get_pixel_height(self):\n            return self.font_height\n\n        def get_pixel_width(self, s):\n            width = sum(self.width.get(c, self.default_width) for c in s)\n            return int(round(self.ratio * width)) + 1\n\n    return FontMetrics\n"
  },
  {
    "path": "mocodo/grid.py",
    "content": "import itertools\nimport math\n\n\nclass Grid(list):\n    \n    def __init__(self, max_number_of_nodes=100, min_balance=0.5):\n        \"\"\"Create a list of couples of dimensions.\n        \n        The nth couple is the tightest balanced rectangle having at least n cells.\n        A balanced rectangle satisfies: length / width > min_balance.\n        [None, (1, 1), (2, 2), (2, 2), (2, 2), (3, 2), (3, 2), (3, 3), ...]\n        \"\"\"\n        list.__init__(self)\n        max_square_side = int(math.ceil(math.sqrt(max_number_of_nodes)))\n        for n in range(max_square_side * max_square_side, 0, -1):\n            for i in range(n, int(math.ceil(math.sqrt(n))) - 1, -1):\n                if n % i == 0 and n / i / i > min_balance:\n                    self.insert(0, (i, n // i))\n                    break\n            else:\n                self.insert(0, self[0])\n        self.insert(0, None)\n        self[2:4] = [(2, 1), (3, 1)] # tweak the 2- and 3-box grids\n    \n    def get_nth_next(self, index, nth):\n        \"\"\"Return the nth next distinct rectangle after the index-th one.\"\"\"\n        acc = set()\n        for i in itertools.count(index):\n            acc.add(self[i])\n            if len(acc) > nth:\n                return self[i]\n    \n    def get_markdown(self):\n        \"\"\"Return the grid as a nicely formatted table. For the docs only.\"\"\"\n        (w, h) = map(max, zip(*self[1:]))\n        result = \\\n            [\n                [\"\"] + \n                list(map(lambda i: \"**%s**\" % i, range(1, w + 1)))\n            ] + \\\n            [[\"---\"] * (w + 1)] + \\\n            [\n                [\"**%s**\" % row] + \n                [\"\"] * w for row in range(1, h + 1)\n            ]\n        for (n, (col, row)) in enumerate(self[1:], 1):\n            result[row + 1][col] += (\", %s\" % n if result[row + 1][col] else str(n))\n        return \"\\n\".join([\"| %s |\" % \" | \".join(row) for row in result])\n\n\nif __name__ == \"__main__\":\n    grid = Grid()\n    print(grid.get_markdown())\n"
  },
  {
    "path": "mocodo/guess_title.py",
    "content": "\n\nfrom collections import Counter\nimport contextlib\nfrom importlib import import_module\nimport re\nfrom pathlib import Path\n\nfrom .tools.parser_tools import parse_source\nfrom .tools.string_tools import rstrip_digit_or_underline\n\nBLACKLIST = {\n    \"fr\": [\"date\", \"calendrier\", \"période\"],\n    \"en\": [\"date\", \"calendar\", \"period\"]\n}\n\ndef guess_title(source, language):\n    \"\"\"\n    Find the name of the most referenced entity in the MCD\n    and pluralize it.\n    \"\"\"\n    blacklist = BLACKLIST.get(language, [])\n    tree = parse_source(source)\n    names = []\n    for node in tree.find_data(\"entity_name_ref\"):\n        name = rstrip_digit_or_underline(node.children[0].children[0])\n        if name.lower() not in blacklist:\n            names.append(name)\n    counter = Counter(names)\n    if not counter:\n        return \"\"\n    title = counter.most_common(1)[0][0]\n    title = re.sub(r\"[^\\w '\\._-]\", \"-\", title)\n    with contextlib.suppress(ModuleNotFoundError):\n        pluralize = import_module(f\"tools.pluralize_{language}\").pluralize\n        title = \" \".join(map(pluralize, title.split()))\n    return title.capitalize()\n\n\ndef may_update_params_with_guessed_title(source, params):\n    if not params.get(\"guess_title\"):\n        return\n    language = params[\"language\"][:2]\n    title = guess_title(source, language)\n    if not title:\n        return\n    Path(f\"{params['output_name']}_new_title.txt\").write_text(title, encoding=\"utf8\")\n    params[\"title\"] = title\n    params[\"output_name\"] = str(Path(params[\"output_dir\"], title))\n"
  },
  {
    "path": "mocodo/inheritance.py",
    "content": "from math import sqrt\n\nfrom .attribute import *\nfrom .leg import *\nfrom .tools.string_tools import rstrip_digit_or_underline, raw_to_bid\n\nTRIANGLE_ALTITUDE = sqrt(3) / 2\nINCIRCLE_RADIUS = 1 / sqrt(12)\n\n\nclass Inheritance:\n\n    counter = 0\n\n    @classmethod\n    def reset_counter(cls):\n        cls.counter = 0\n\n    def __init__(self, clause, **params):\n        self.source = clause[\"source\"]\n        self.raw_name = clause[\"name\"] if clause[\"name\"] != \"TX\" else \"XT\"\n        Inheritance.counter += 1\n        parent_bid = raw_to_bid(clause[\"legs\"][0][\"entity\"])\n        self.bid = f'{parent_bid}_PARENT_#{Inheritance.counter}'\n        self.name_view = rstrip_digit_or_underline(clause[\"name\"])\n        self.attributes = [InheritanceAttribute(attr) for attr in clause.get(\"attrs\", [])]\n        for leg_clause in clause[\"legs\"]:\n            leg_clause[\"kind\"] = \"-\"\n            leg_clause[\"arrow\"] = False\n        inheritance_arrow = clause[\"inheritance_arrow\"]\n        if inheritance_arrow == \"<-\":\n            clause[\"legs\"][0][\"arrow\"] = True\n        elif inheritance_arrow == \"->\":\n            for leg_clause in clause[\"legs\"][1:]:\n                leg_clause[\"arrow\"] = True\n        elif inheritance_arrow == \"<=\":\n            clause[\"legs\"][0][\"arrow\"] = True\n            for leg_clause in clause[\"legs\"][1:]:\n                leg_clause[\"kind\"] = \"=\"\n        elif inheritance_arrow == \"=>\":\n            clause[\"legs\"][0][\"kind\"] = \"=\"\n            for leg_clause in clause[\"legs\"][1:]:\n                leg_clause[\"arrow\"] = True\n        else:\n            clause[\"legs\"][0][\"arrow\"] = True\n        self.legs = [InheritanceLeg(self, leg, **params) for leg in clause[\"legs\"]]\n        self.kind = inheritance_arrow.replace(\"--\", \"-\").replace(\"==\", \"=\")\n\n    def register_boxes(self, boxes):\n        self.boxes = boxes\n\n    def calculate_size(self, style, get_font_metrics):\n        cartouche_font = get_font_metrics(style[\"association_cartouche_font\"])\n        self.get_cartouche_string_width = cartouche_font.get_pixel_width\n        self.cartouche_height = cartouche_font.get_pixel_height()\n        attribute_font = get_font_metrics(style[\"association_attribute_font\"])\n        self.attribute_height = attribute_font.get_pixel_height()\n        self.w = self.h = 2 * (style[\"round_rect_margin_width\"] + self.cartouche_height)\n        self.w += self.w % 2\n        self.h += self.h % 2\n        for leg in self.legs:\n            leg.calculate_size(style, get_font_metrics)\n\n    def register_center(self, geo):\n        self.cx = geo[\"cx\"][self.bid]\n        self.cy = geo[\"cy\"][self.bid]\n        self.l = self.cx - self.w // 2\n        self.r = self.cx + self.w // 2\n        self.t = self.cy - self.h // 2\n        self.b = self.cy + self.h // 2\n\n    def description(self, style, geo):\n        result = []\n        result.append((\"comment\", {\"text\": f\"Inheritance {self.bid}\"}))\n        result.append(\n            (\n                \"begin_component\",\n                {\n                    \"page\": self.page,\n                    \"visibility\": \"hidden\" if self.page else \"visible\",\n                }\n            )\n        )\n        result.extend(self.leg_descriptions(style, geo))\n        result.append((\"begin_group\", {}))\n        result.extend(\n            [\n                (\n                    \"triangle\",\n                    {\n                        \"stroke_depth\": style[\"box_stroke_depth\"],\n                        \"stroke_color\": style['association_stroke_color'],\n                        \"color\": style['association_cartouche_color'],\n                        \"x1\": self.cx,\n                        \"x2\": self.l,\n                        \"x3\": self.r,\n                        \"y1\": self.cy - (TRIANGLE_ALTITUDE - INCIRCLE_RADIUS) * self.w,\n                        \"y2\": self.cy + INCIRCLE_RADIUS * self.w,\n                        \"y3\": self.cy + INCIRCLE_RADIUS * self.w,\n                    },\n                ),\n                (\n                    \"text\",\n                    {\n                        \"text\": self.name_view,\n                        \"text_color\": style['association_cartouche_text_color'],\n                        \"x\": self.cx - self.get_cartouche_string_width(self.name_view) // 2,\n                        \"y\": self.cy + self.cartouche_height // 3,\n                        \"family\": style[\"association_cartouche_font\"][\"family\"],\n                        \"size\": style[\"association_cartouche_font\"][\"size\"],\n                    },\n                ),\n            ]\n        )\n        result.append((\"end\", {}))\n        result.append((\"end\", {}))\n        return result\n\n    def leg_descriptions(self, style, geo):\n        result = []\n        for leg in self.legs:\n            result.extend(leg.description(style, geo))\n        return result\n"
  },
  {
    "path": "mocodo/leg.py",
    "content": "import operator\nfrom math import hypot, sqrt\n\nfrom .mocodo_error import MocodoError\nfrom .tools.string_tools import surrounds, raw_to_bid\n\n\nclass Leg:\n    def __init__(self, association, leg_clause, **params):\n        params[\"card_format\"] = params.get(\"card_format\", \"{min_card},{max_card}\")\n\n        self.card = leg_clause.get(\"card\", \"XX\")\n        if self.card == \"XX\" or leg_clause.get(\"card_hidden\") == \"-\":\n            self.card_view = \"     \"\n        elif \"X\" in self.card:\n            self.card_view = self.card.replace(\"X\", \"\")\n        else:\n            self.card_view = params[\"card_format\"].format(min_card=self.card[0], max_card=self.card[1])\n        \n        self.has_underlined_card = False\n        if leg_clause.get(\"card_prefix\") == \"_\":\n            if self.card != \"11\": # silently ignore the prefix\n                self.kind = \"leg\"\n                del leg_clause[\"card_prefix\"]\n            else:\n                self.kind = \"strengthening\"\n                self.card_view = params.get(\"strengthen_card\", \"_1,1_\")\n                if surrounds(self.card_view, \"_\"):\n                    self.has_underlined_card = True\n                    self.card_view = self.card_view[1:-1]\n        elif association.kind == \"cluster\":\n            self.kind = \"cluster_peg\" if leg_clause.get(\"card_prefix\") == \"/\" else \"cluster_leg\"\n        else:\n            self.kind = \"leg\"\n        \n        self.arrow = leg_clause.get(\"leg_arrow\", \"\")\n        self.peg = (\"o\" if self.kind == \"cluster_peg\" and not self.arrow else \"\")\n        self.note = leg_clause.get(\"leg_note\")\n        self.association = association\n        self.entity_raw_name = leg_clause[\"entity\"]\n        self.entity_bid = raw_to_bid(self.entity_raw_name)\n        self.twist = False\n        self.lid = None\n        self.unicities = \"\"\n        self.is_in_elected_group = False\n\n    def register_entity(self, entity):\n        self.entity = entity\n    \n    def register_mcd_has_cif(self, mcd_has_cif):\n        self.mcd_has_cif = mcd_has_cif\n        if self.mcd_has_cif:\n            self.peg = \"\"\n\n    def append_candidate_group(self, candidate_number: str):\n        if candidate_number == \"0\":\n            self.is_in_elected_group = True\n        else:\n            # concatenate the candidate number to the beginning of the string to ensure sorting\n            self.unicities = candidate_number + self.unicities\n\n    def calculate_size(self, style, get_font_metrics):\n        font = get_font_metrics(style[\"card_font\"])\n        self.h = font.get_pixel_height()\n        self.w = font.get_pixel_width(self.card_view)\n\n    def set_spin_strategy(self, spin):\n        self.spin = spin\n        self.description = self._curved_description if spin else self._straight_description\n        if self.lid is None:\n            spin_str = str(round(spin, 2)).replace(\".\", \"_\")  # avoid dot for the web version\n            self.lid = f\"{self.association.bid},{self.entity_bid},{spin_str}\"\n\n    def _straight_description(self, style, geo):\n        result = []\n        ex = self.entity.cx\n        ey = self.entity.cy\n        ew = self.entity.w // 2\n        eh = self.entity.h // 2\n        ax = self.association.cx\n        ay = self.association.cy\n        aw = self.association.w // 2\n        ah = self.association.h // 2\n        card_margin = style[\"card_margin\"]\n        cw = self.w + 2 * card_margin\n        ch = self.h + 2 * card_margin\n        leg = straight_leg_factory(ex, ey, ew, eh, ax, ay, aw, ah, cw, ch, card_margin)\n        if self.peg:\n            (x, y, a, b) = leg.arrow_pos(self.arrow, 1)\n            c = hypot(a, b)\n            (cos, sin) = (a / c, b / c)\n            result.append(\n                (\n                    \"circle\",\n                    {\n                        \"cx\": x + cos * style[\"arrow_width\"] / 2,\n                        \"cy\": y - sin * style[\"arrow_width\"] / 2,\n                        \"r\": style[\"arrow_width\"] / 2,\n                        \"stroke_color\": style[\"entity_stroke_color\"],\n                        \"stroke_depth\": style[\"leg_stroke_depth\"],\n                        \"color\": style[\"entity_color\"]+ \"55\", # alpha channel\n                    },\n                ),\n            )\n        result.append(\n            (\n                \"line\",\n                {\n                    \"x0\": ex,\n                    \"y0\": ey,\n                    \"x1\": ax,\n                    \"y1\": ay,\n                    \"stroke_color\": style[\"leg_stroke_color\"],\n                    \"stroke_depth\": style[\"leg_stroke_depth\"],\n                },\n            )\n        )\n        (x, y) = leg.card_pos(self.twist, geo[\"shift\"][self.lid])\n        tx = x + card_margin\n        ty = y - card_margin - style[\"card_baseline\"]\n        self.saved_card_description = []\n        if self.note:\n            self.saved_card_description.append(\n                (\n                    \"text_with_note\",\n                    {\n                        \"x\": tx,\n                        \"y\": ty,\n                        \"text_color\": style[\"card_text_color\"],\n                        \"family\": style[\"card_font\"][\"family\"],\n                        \"size\": style[\"card_font\"][\"size\"],\n                        \"text\": self.card_view,\n                        \"note\": self.note.lstrip(\"+\").lstrip(\"-\")\n                    },\n                )\n            )\n        else:\n            self.saved_card_description.append(\n                (\n                    \"text\",\n                    {\n                        \"x\": tx,\n                        \"y\": ty,\n                        \"text_color\": style[\"card_text_color\"],\n                        \"family\": style[\"card_font\"][\"family\"],\n                        \"size\": style[\"card_font\"][\"size\"],\n                        \"text\": self.card_view,\n                    },\n                )\n            )\n        if self.has_underlined_card:\n            self.saved_card_description.append(\n                (\n                    \"line\",\n                    {\n                        \"x0\": tx,\n                        \"y0\": ty - style[\"card_underline_skip_height\"],\n                        \"x1\": tx + self.w,\n                        \"y1\": ty - style[\"card_underline_skip_height\"],\n                        \"stroke_color\": style[\"card_text_color\"],\n                        \"stroke_depth\": style[\"card_underline_depth\"],\n                    },\n                )\n            )\n        if self.arrow:\n            (x, y, a, b) = leg.arrow_pos(self.arrow, geo[\"ratio\"][self.lid])\n            c = hypot(a, b)\n            (cos, sin) = (a / c, b / c)\n            result.append(\n                (\n                    \"arrow\",\n                    {\n                        \"x0\": x,\n                        \"y0\": y,\n                        \"x1\": x + style[\"arrow_width\"] * cos - style[\"arrow_half_height\"] * sin,\n                        \"y1\": y - style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"x2\": x + style[\"arrow_axis\"] * cos,\n                        \"y2\": y - style[\"arrow_axis\"] * sin,\n                        \"x3\": x + style[\"arrow_width\"] * cos + style[\"arrow_half_height\"] * sin,\n                        \"y3\": y + style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"stroke_color\": style[\"leg_stroke_color\"],\n                    },\n                ),\n            )\n        return result\n\n    def _curved_description(self, style, geo):\n        result = []\n        ex = self.entity.cx\n        ey = self.entity.cy\n        ew = self.entity.w // 2\n        eh = self.entity.h // 2\n        ax = self.association.cx\n        ay = self.association.cy\n        aw = self.association.w // 2\n        ah = self.association.h // 2\n        card_margin = style[\"card_margin\"]\n        cw = self.w + 2 * card_margin\n        ch = self.h + 2 * card_margin\n        spin = self.spin\n        leg = curved_leg_factory(ex, ey, ew, eh, ax, ay, aw, ah, cw, ch, card_margin, spin)\n        (x0, y0, x1, y1, x2, y2, x3, y3) = leg.points\n        if self.peg:\n            (x, y, a, b) = leg.arrow_pos(self.arrow, 1)\n            c = hypot(a, b)\n            (cos, sin) = (a / c, b / c)\n            result.append(\n                (\n                    \"circle\",\n                    {\n                        \"cx\": x + cos * style[\"arrow_width\"] / 2,\n                        \"cy\": y - sin * style[\"arrow_width\"] / 2,\n                        \"r\": style[\"arrow_width\"] / 2,\n                        \"stroke_color\": style[\"entity_stroke_color\"],\n                        \"stroke_depth\": style[\"leg_stroke_depth\"],\n                        \"color\": style[\"entity_color\"]+ \"55\", # alpha channel\n                    },\n                ),\n            )\n        result.append(\n            (\n                \"curve\",\n                {\n                    \"x0\": x0,\n                    \"y0\": y0,\n                    \"x1\": x1,\n                    \"y1\": y1,\n                    \"x2\": x2,\n                    \"y2\": y2,\n                    \"x3\": x3,\n                    \"y3\": y3,\n                    \"stroke_color\": style[\"leg_stroke_color\"],\n                    \"stroke_depth\": style[\"leg_stroke_depth\"],\n                },\n            )\n        )\n        (x, y) = leg.card_pos(geo[\"shift\"][self.lid])\n        tx = x + card_margin\n        ty = y - card_margin - style[\"card_baseline\"]\n        self.saved_card_description = []\n        if self.note:\n            self.saved_card_description.append(\n                (\n                    \"text_with_note\",\n                    {\n                        \"x\": tx,\n                        \"y\": ty,\n                        \"text_color\": style[\"card_text_color\"],\n                        \"family\": style[\"card_font\"][\"family\"],\n                        \"size\": style[\"card_font\"][\"size\"],\n                        \"text\": self.card_view,\n                        \"note\": self.note.lstrip(\"+\").lstrip(\"-\"),\n                    },\n                )\n            )\n        else:\n            self.saved_card_description.append(\n                (\n                    \"text\",\n                    {\n                        \"x\": tx,\n                        \"y\": ty,\n                        \"text_color\": style[\"card_text_color\"],\n                        \"family\": style[\"card_font\"][\"family\"],\n                        \"size\": style[\"card_font\"][\"size\"],\n                        \"text\": self.card_view,\n                    },\n                )\n            )\n        if self.has_underlined_card:\n            self.saved_card_description.append(\n                (\n                    \"line\",\n                    {\n                        \"x0\": tx,\n                        \"y0\": ty - style[\"card_underline_skip_height\"],\n                        \"x1\": tx + self.w,\n                        \"y1\": ty - style[\"card_underline_skip_height\"],\n                        \"stroke_color\": style[\"card_text_color\"],\n                        \"stroke_depth\": style[\"card_underline_depth\"],\n                    },\n                )\n            )\n        if self.arrow:\n            (x, y, a, b) = leg.arrow_pos(self.arrow, geo[\"ratio\"][self.lid])\n            c = hypot(a, b)\n            (cos, sin) = (a / c, b / c)\n            result.append(\n                (\n                    \"arrow\",\n                    {\n                        \"x0\": x,\n                        \"y0\": y,\n                        \"x1\": x + style[\"arrow_width\"] * cos - style[\"arrow_half_height\"] * sin,\n                        \"y1\": y - style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"x2\": x + style[\"arrow_axis\"] * cos,\n                        \"y2\": y - style[\"arrow_axis\"] * sin,\n                        \"x3\": x + style[\"arrow_width\"] * cos + style[\"arrow_half_height\"] * sin,\n                        \"y3\": y + style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"stroke_color\": style[\"leg_stroke_color\"],\n                    },\n                ),\n            )\n        return result\n\nclass InheritanceLeg:\n    def __init__(self, inheritance, leg, **params):\n        self.kind = leg[\"kind\"] # \"-\" or \"=\"\n        self.arrow = leg[\"arrow\"]\n        self.inheritance = inheritance\n        self.entity_bid = raw_to_bid(leg[\"entity\"])\n        self.entity_raw_name = leg[\"entity\"]\n        self.lid = f\"{self.inheritance.bid} / {self.entity_bid}\"\n\n    def register_entity(self, entity):\n        self.entity = entity\n    \n    def calculate_size(self, style, get_font_metrics):\n        font = get_font_metrics(style[\"card_font\"])\n        self.h = font.get_pixel_height()\n        self.w = font.get_pixel_width(\"--\")\n\n    def description(self, style, geo):\n        result = []\n        ex = self.entity.cx\n        ey = self.entity.cy\n        ew = self.entity.w // 2\n        eh = self.entity.h // 2\n        ax = self.inheritance.cx\n        ay = self.inheritance.cy\n        aw = self.inheritance.w // 2\n        ah = self.inheritance.h // 2\n        card_margin = style[\"card_margin\"]\n        cw = self.w + 2 * card_margin\n        ch = self.h + 2 * card_margin\n        leg = straight_leg_factory(ex, ey, ew, eh, ax, ay, aw, ah, cw, ch, card_margin)\n        if self.kind == \"=\":\n            for d in (style[\"leg_stroke_depth\"], -style[\"leg_stroke_depth\"]):\n                (x0, y0, x1, y1) = orthogonal_translation(ex, ey, ax, ay, d)\n                result.append(\n                    (\n                        \"line\",\n                        {\n                            \"x0\": x0,\n                            \"y0\": y0,\n                            \"x1\": x1,\n                            \"y1\": y1,\n                            \"stroke_color\": style[\"leg_stroke_color\"],\n                            \"stroke_depth\": style[\"leg_stroke_depth\"],\n                        },\n                    )\n                )\n        else:\n            result.append(\n                (\n                    \"line\",\n                    {\n                        \"x0\": ex,\n                        \"y0\": ey,\n                        \"x1\": ax,\n                        \"y1\": ay,\n                        \"stroke_color\": style[\"leg_stroke_color\"],\n                        \"stroke_depth\": style[\"leg_stroke_depth\"],\n                    },\n                )\n            )\n        if self.arrow:\n            (x, y, a, b) = leg.arrow_pos(self.arrow, geo[\"ratio\"][self.lid])\n            c = hypot(a, b)\n            (cos, sin) = (a / c, b / c)\n            result.append(\n                (\n                    \"arrow\",\n                    {\n                        \"x0\": x,\n                        \"y0\": y,\n                        \"x1\": x + style[\"arrow_width\"] * cos - style[\"arrow_half_height\"] * sin,\n                        \"y1\": y - style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"x2\": x + style[\"arrow_axis\"] * cos,\n                        \"y2\": y - style[\"arrow_axis\"] * sin,\n                        \"x3\": x + style[\"arrow_width\"] * cos + style[\"arrow_half_height\"] * sin,\n                        \"y3\": y + style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                        \"stroke_color\": style[\"leg_stroke_color\"],\n                    },\n                ),\n            )\n        return result\n\n\nclass ConstraintLeg:\n\n    def __init__(self, constraint, kind, box_raw_name):\n        self.constraint = constraint\n        self.kind = kind\n        self.bid = raw_to_bid(box_raw_name)\n        self.entity_raw_name = box_raw_name\n        self.lid = None\n    \n    def register_box(self, box):\n        self.box = box\n    \n    def description(self, style, geo):\n        if self.kind == \"\": # a phantom leg, useful to tweak the barycenter\n            return []\n        result = []\n        bx = self.box.cx\n        by = self.box.cy\n        bw = self.box.w // 2\n        bh = self.box.h // 2\n        cx = self.constraint.cx\n        cy = self.constraint.cy\n        cw = self.constraint.w // 2\n        ch = self.constraint.h // 2\n        leg = straight_leg_factory(bx, by, bw, bh, cx, cy, cw, ch)\n        kind = self.kind\n        for direction in \"<>\":\n            if direction in self.kind:\n                (x, y, a, b) = leg.arrow_pos(direction, 1)\n                c = hypot(a, b) or 1\n                (cos, sin) = (a / c, b / c)\n                result.append(\n                    (\n                        \"arrow\",\n                        {\n                            \"x0\": x,\n                            \"y0\": y,\n                            \"x1\": x + style[\"arrow_width\"] * cos - style[\"arrow_half_height\"] * sin,\n                            \"y1\": y - style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                            \"x2\": x + style[\"arrow_axis\"] * cos,\n                            \"y2\": y - style[\"arrow_axis\"] * sin,\n                            \"x3\": x + style[\"arrow_width\"] * cos + style[\"arrow_half_height\"] * sin,\n                            \"y3\": y + style[\"arrow_half_height\"] * cos - style[\"arrow_width\"] * sin,\n                            \"stroke_color\": style[\"constraint_stroke_color\"],\n                        },\n                    ),\n                )\n                kind = kind.replace(direction, \"\")\n        if kind[:1] == \"-\":\n            result.append(\n                (\n                    \"line\",\n                    {\n                        \"x0\": bx,\n                        \"y0\": by,\n                        \"x1\": cx,\n                        \"y1\": cy,\n                        \"stroke_color\": style[\"constraint_stroke_color\"],\n                        \"stroke_depth\": style[\"constraint_stroke_depth\"],\n                    }\n                )\n            )\n        elif kind[:1] == \".\":\n            result.append(\n                (\n                    \"dot_line\",\n                    {\n                        \"x0\": bx,\n                        \"y0\": by,\n                        \"x1\": cx,\n                        \"y1\": cy,\n                        \"stroke_color\": style[\"constraint_stroke_color\"],\n                        \"stroke_depth\": style[\"constraint_dot_stroke_depth\"],\n                        \"dash_gap\": style[\"constraint_dot_gap_width\"],\n                    }\n                )\n            )\n        else:\n            raise NotImplementedError\n        return result\n\n\ndef line_intersection(ex, ey, w, h, ax, ay, cmp=lambda x, y: (x > y) - (x < y)):\n    if ax == ex:\n        return (ax, ey + cmp(ay, ey) * h)\n    if ay == ey:\n        return (ex + cmp(ax, ex) * w, ay)\n    x = ex + cmp(ax, ex) * w\n    y = ey + (ay - ey) * (x - ex) / (ax - ex)\n    if abs(y - ey) > h:\n        y = ey + cmp(ay, ey) * h\n        x = ex + (ax - ex) * (y - ey) / (ay - ey)\n    return (x, y)\n\n\ndef straight_leg_factory(ex, ey, ew, eh, ax, ay, aw, ah, cw=0, ch=0, card_margin=0):\n    def card_pos(twist, shift):\n        compare = operator.lt if twist else operator.le\n        correction = 1 - abs(abs(ax - ex) - abs(ay - ey)) / hypot(ax - ex, ay - ey)\n        correction = card_margin * 1.4142 * correction - shift\n        (xg, yg) = line_intersection(ex, ey, ew, eh + ch, ax, ay)\n        (xb, yb) = line_intersection(ex, ey, ew + cw, eh, ax, ay)\n        if compare(xg, xb):\n            if compare(xg, ex):\n                if compare(yb, ey):\n                    return (xb - correction, yb)\n                else:\n                    return (xb - correction, yb + ch)\n            else:\n                if compare(yb, ey):\n                    return (xg, yg + ch - correction)\n                else:\n                    return (xg, yg + correction)\n        else:\n            if compare(xb, ex):\n                if compare(yb, ey):\n                    return (xg - cw, yg + ch - correction)\n                else:\n                    return (xg - cw, yg + correction)\n            else:\n                if compare(yb, ey):\n                    return (xb - cw + correction, yb)\n                else:\n                    return (xb - cw + correction, yb + ch)\n\n    def arrow_pos(direction, ratio):\n        (x0, y0) = line_intersection(ex, ey, ew, eh, ax, ay)\n        (x1, y1) = line_intersection(ax, ay, aw, ah, ex, ey)\n        if direction == \"<\":\n            (x0, y0, x1, y1) = (x1, y1, x0, y0)\n        (x, y) = (ratio * x0 + (1 - ratio) * x1, ratio * y0 + (1 - ratio) * y1)\n        return (x, y, x1 - x0, y0 - y1)\n\n    straight_leg_factory.card_pos = card_pos\n    straight_leg_factory.arrow_pos = arrow_pos\n    return straight_leg_factory\n\n\ndef curved_leg_factory(ex, ey, ew, eh, ax, ay, aw, ah, cw, ch, card_margin, spin):\n    def bisection(predicate):\n        (a, b) = (0, 1)\n        while abs(b - a) > 0.0001:\n            m = (a + b) / 2\n            if predicate(bezier(m)):\n                a = m\n            else:\n                b = m\n        return m\n\n    def intersection(left, top, right, bottom):\n        (x, y) = bezier(bisection(lambda p: left <= p[0] <= right and top <= p[1] <= bottom))\n        return (int(round(x)), int(round(y)))  # avoid comparing floats\n\n    def card_pos(shift):\n        diagonal = hypot(ax - ex, ay - ey)\n        correction = card_margin * 1.4142 * (1 - abs(abs(ax - ex) - abs(ay - ey)) / diagonal)\n        (top, bot) = (ey - eh, ey + eh)\n        (TOP, BOT) = (top - ch, bot + ch)\n        (lef, rig) = (ex - ew, ex + ew)\n        (LEF, RIG) = (lef - cw, rig + cw)\n        (xr, yr) = intersection(LEF, TOP, RIG, BOT)\n        (xg, yg) = intersection(lef, TOP, rig, BOT)\n        (xb, yb) = intersection(LEF, top, RIG, bot)\n        if spin > 0:\n            if (yr == BOT and xr <= rig) or (xr == LEF and yr >= bot):\n                return (\n                    max(x for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if y >= bot)\n                    - correction\n                    + shift,\n                    bot + ch,\n                )\n            if (xr == RIG and yr >= top) or yr == BOT:\n                return (\n                    rig,\n                    min(y for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if x >= rig)\n                    + correction\n                    + shift,\n                )\n            if (yr == TOP and xr >= lef) or xr == RIG:\n                return (\n                    min(x for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if y <= top)\n                    + correction\n                    + shift\n                    - cw,\n                    TOP + ch,\n                )\n            return (\n                LEF,\n                max(y for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if x <= lef)\n                - correction\n                + shift\n                + ch,\n            )\n        if (yr == BOT and xr >= lef) or (xr == RIG and yr >= bot):\n            return (\n                min(x for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if y >= bot)\n                + correction\n                + shift\n                - cw,\n                bot + ch,\n            )\n        if xr == RIG or (yr == TOP and xr >= rig):\n            return (\n                rig,\n                max(y for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if x >= rig)\n                - correction\n                + shift\n                + ch,\n            )\n        if yr == TOP or (xr == LEF and yr <= top):\n            return (\n                max(x for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if y <= top)\n                - correction\n                + shift,\n                TOP + ch,\n            )\n        return (\n            LEF,\n            min(y for (x, y) in ((xr, yr), (xg, yg), (xb, yb)) if x <= lef) + correction + shift,\n        )\n\n    def arrow_pos(direction, ratio):\n        t0 = bisection(lambda p: abs(p[0] - ax) > aw or abs(p[1] - ay) > ah)\n        t3 = bisection(lambda p: abs(p[0] - ex) < ew and abs(p[1] - ey) < eh)\n        if direction == \"<\":\n            (t0, t3) = (t3, t0)\n        tc = t0 + (t3 - t0) * ratio\n        (xc, yc) = bezier(tc)\n        (x, y) = derivate(tc)\n        if direction == \"<\":\n            (x, y) = (-x, -y)\n        return (xc, yc, x, -y)\n\n    diagonal = hypot(ax - ex, ay - ey)\n    (x, y) = line_intersection(ex, ey, ew + cw / 2, eh + ch / 2, ax, ay)\n    k = cw * abs((ay - ey) / diagonal) + ch * abs((ax - ex) / diagonal)\n    (x, y) = (x - spin * k * (ay - ey) / diagonal, y + spin * k * (ax - ex) / diagonal)\n    (hx, hy) = (2 * x - (ex + ax) / 2, 2 * y - (ey + ay) / 2)\n    (x1, y1) = (ex + (hx - ex) * 2 / 3, ey + (hy - ey) * 2 / 3)\n    (x2, y2) = (ax + (hx - ax) * 2 / 3, ay + (hy - ay) * 2 / 3)\n    (kax, kay) = (ex - 2 * hx + ax, ey - 2 * hy + ay)\n    (kbx, kby) = (2 * hx - 2 * ex, 2 * hy - 2 * ey)\n    bezier = lambda t: (kax * t * t + kbx * t + ex, kay * t * t + kby * t + ey)\n    derivate = lambda t: (2 * kax * t + kbx, 2 * kay * t + kby)\n\n    curved_leg_factory.points = (ex, ey, x1, y1, x2, y2, ax, ay)\n    curved_leg_factory.card_pos = card_pos\n    curved_leg_factory.arrow_pos = arrow_pos\n    return curved_leg_factory\n\ndef orthogonal_translation(x1, y1, x2, y2, d):\n    if x1 == x2:\n        return (x1+d, y1, x1+d, y2)\n    slope = (y2 - y1) / (x2 - x1)\n    dy = sqrt(d * d / (slope * slope + 1))\n    dx = -slope * dy\n    if d > 0:\n        return (x1+dx, y1+dy, x2+dx, y2+dy)\n    else:\n        return (x1-dx, y1-dy, x2-dx, y2-dy)\n"
  },
  {
    "path": "mocodo/magic.py",
    "content": "import argparse\nimport contextlib\nimport importlib\nimport json\nimport re\nimport shlex\nimport warnings\nfrom base64 import b64encode\nfrom itertools import takewhile\nfrom pathlib import Path\n\nfrom IPython import get_ipython\nfrom IPython.display import HTML, SVG, Code, Image, Markdown, display\n\nfrom .__main__ import Printer, Runner\nfrom .mocodo_error import MocodoError\n\n# ANSI color codes\nOK = \"\\033[92m\"\nWARNING = \"\\033[1m\\033[38;5;166m\"\nFAIL = \"\\033[1m\\033[91m\"\nRESET = \"\\033[0m\"\n\nIPYTHON = get_ipython()\n\ndef update_cell(content):\n    IPYTHON.set_next_input(content, replace=True)\n\nPARAM_TEMPLATE = '''\\\n# You may edit and run the following lines\nimport json, pathlib\nparams = \"\"\"\\\\\n{stdoutdata}\"\"\"\ntry:\n    json.loads(params)\nexcept:\n    raise RuntimeError(\"Invalid JSON. Check your syntax on https://jsonlint.com.\")\npathlib.Path(\"{output_dir}/params.json\").write_text(params, encoding=\"utf8\");'''\n\nOUTPUT_PART_HEADER = re.sub(\"  +\", \"\", \"\"\"\n<div style=\"position: relative; height: 3ex; background-color: transparent\">\n  <hr style=\"margin: 1ex 0 0 0; border-top: 1px solid #BBB\">\n  <span style=\"position: absolute; right: 0; color: #BBB\">\n    <tt>\n        {label}\n    </tt>\n  </span>\n</div>\n\"\"\")\n\ndef read_and_cleanup_text(path):\n    text = path.read_text(encoding=\"utf8\")\n    text = re.sub(r\"(?m).+Generated by Mocodo.+\\n+\", \"\", text)\n    return text\n\ndef display_converted_file(path, hide_header):\n    if not (hide_header and path.name.endswith(\"_mld.md\")):\n        display(Markdown(OUTPUT_PART_HEADER.format(label=path.relative_to(Path.cwd()))))\n    extension=path.suffix[1:]\n    if extension == \"svg\":\n        # Fix a maximum width for SVG images:\n        # https://stackoverflow.com/questions/51452569/how-to-resize-rescale-a-svg-graphic-in-an-ipython-jupyter-notebook\n        svg = b64encode(path.read_bytes()).decode(\"utf8\")\n        # Use Markdown instead of HTML to avoid a grey background.\n        display(Markdown(f'<img max-width=\"100%\" src=\"data:image/svg+xml;base64,{svg}\">'))\n    elif extension == \"md\":\n        display(Markdown(read_and_cleanup_text(path)))\n    elif extension == \"png\":\n        display(Image(filename=path, unconfined=False))\n    elif extension == \"html\":\n        text = path.read_text(encoding=\"utf8\")\n        text = re.sub('<!-- TO_BE_DELETED_BY_MOCODO_MAGIC -->.+\\n', \"\", text)\n        display(HTML(text))\n    elif extension == \"tex\":\n        display(Code(filename=path, language=\"latex\"))\n    elif extension == \"url\":\n        print(path.read_text(encoding=\"utf8\")) # make the link clickable\n    elif extension == \"tsv\":\n        try:\n            df = importlib.import_module(\"pandas\").read_csv(path, sep=\"\\t\", header=0, index_col=False)\n            df = df.style.set_properties(**{'text-align': 'left'}).set_table_styles([ dict(selector='th', props=[('text-align', 'left')] ) ])\n            display(df)\n        except ImportError:\n            display(Markdown(f'```\\n{path.read_text(encoding=\"utf8\")}\\n```'))\n    else:\n        display(Markdown(f\"```{extension}\\n{read_and_cleanup_text(path)}\\n```\"))\n\ndef mocodo(line=\"\", source=\"\"):\n    \"\"\"\n    Mocodo IPython magic extension\n\n    Magic methods:\n        %mocodo [command line options]\n        %%mocodo [command line options]\n        < MCD ... >\n\n    Usage:\n        %load_ext mocodo\n    \"\"\"\n\n    if source == \"\":\n        # When this function is NOT invoked as a magic command, the first (and normally unique)\n        # argument can consist of several lines, separated by \"\\n\". The first line is the magic\n        # command, the other ones (if any) are the source of the MCD. Redistribute the lines to\n        # conform to the magic command's expected format.\n        line = re.sub(r\"^\\s*%%?mocodo\\b *\", \"\", line)\n        lines = line.split(\"\\n\")\n        if len(lines) > 1:\n            source = \"\\n\".join(lines[1:])\n            line = lines[0]\n\n    parser = argparse.ArgumentParser(add_help=False)\n    parser.add_argument(\"--input\", \"-i\")\n    parser.add_argument(\"--output_dir\")\n    (args, remaining_args) = parser.parse_known_args(shlex.split(line))\n    remaining_args = list(takewhile(lambda x: not x.startswith(\"#\"), remaining_args))\n    new_args = remaining_args[:]\n\n    mocodo_notebook_dir = Path.cwd()\n    if mocodo_notebook_dir.name != \"mocodo_notebook\":\n        mocodo_notebook_dir = mocodo_notebook_dir / \"mocodo_notebook\"\n        mocodo_notebook_dir.mkdir(parents=True, exist_ok=True)\n    if not args.input:\n        input_path = mocodo_notebook_dir / \"sandbox.mcd\"\n        input_path.write_text(source, encoding=\"utf8\")\n    else:\n        input_path = Path(args.input)\n        if not input_path.suffix:\n            input_path = input_path.with_suffix(\".mcd\")\n\n    if not args.output_dir:\n        output_dir = mocodo_notebook_dir\n    else:\n        output_dir = Path(args.output_dir)\n        output_dir.mkdir(parents=True, exist_ok=True)\n    output_path_radical = output_dir / input_path.stem\n\n    remaining_args.extend([\n        \"--input\", str(input_path),\n        \"--output_dir\", str(output_dir),\n        \"--is_magic\",\n    ]) # may override user's provided options\n\n    stdoutdata = \"\"\n    stderrdata = \"\"\n    printer = Printer(quiet=True)\n    try:\n        run = Runner(remaining_args, printer)\n    except SystemExit: # raised by argparse with certain arguments: --help, --version\n        return\n    try:\n        stdoutdata = run()\n    except MocodoError as err:\n        stderrdata = str(err)\n    \n    if \"--print_params\" in remaining_args:\n        update_cell(PARAM_TEMPLATE.format(stdoutdata=stdoutdata, output_dir=output_dir.relative_to(Path.cwd())))\n        return\n    \n    response_path = Path(f\"{output_path_radical}_response_for_magic_command.json\")\n    try: \n        response = json.loads(response_path.read_text(encoding=\"utf8\"))\n    except (json.decoder.JSONDecodeError, FileNotFoundError):\n        response = {}\n    finally:\n        with contextlib.suppress(FileNotFoundError): # From Python 3.8, use the missing_ok argument\n            response_path.unlink()\n    \n    rewritten_source = response.get(\"rewritten_source\", \"\")\n    redirect_output = response.get(\"redirect_output\", False)\n    converted_file_paths = response.get(\"converted_file_paths\", [])\n\n    if stderrdata:\n        message = stderrdata\n        if rewritten_source:\n            message = f\"{rewritten_source}\\n\\n{message}\"\n        warnings.formatwarning = lambda x, *args, **kargs : str(x)\n        warnings.warn(message)\n        return\n    \n    if rewritten_source and not rewritten_source.startswith(\"%%mocodo\"):\n        new_args = \" \".join(filter(lambda x: x not in response[\"args_to_delete\"], new_args))\n        new_args = response[\"opt_to_restore\"] + new_args\n        rewritten_source = f\"%%mocodo{new_args}\\n{rewritten_source}\"\n    \n    for select in response.get(\"select\", []):\n        if select == \"mcd\":\n            svg_path = output_path_radical.with_suffix(\".svg\")\n            if svg_path.is_file() and input_path.stat().st_mtime <= svg_path.stat().st_mtime:\n                display(SVG(filename=svg_path))\n        elif select == \"rw\":\n            path = output_path_radical.with_suffix(\".mcd\")\n            display(Markdown(OUTPUT_PART_HEADER.format(label=path.relative_to(output_dir))))\n            print(rewritten_source or source)\n        elif select == \"cv\":\n            for converted_file_path in converted_file_paths:\n                display_converted_file(Path(converted_file_path), hide_header=response.get(\"mld\"))\n\n    if redirect_output:\n        if rewritten_source:\n            update_cell(rewritten_source)\n        if converted_file_paths:\n            # Copy the last converted file source to the clipboard\n            with contextlib.suppress(ImportError):\n                pyperclip = importlib.import_module(\"pyperclip\")\n                converted_file_path = Path(converted_file_paths[-1])\n                pyperclip.copy(converted_file_path.read_text(encoding=\"utf8\"))\n                print(f'⧉ {OK}The contents of \"{converted_file_path.relative_to(output_dir)}\" has been copied to the clipboard.{RESET}')\n"
  },
  {
    "path": "mocodo/mcd.py",
    "content": "import itertools\nfrom collections import defaultdict\nfrom hashlib import md5\nimport json\nfrom pathlib import Path\n\nfrom .association import Association\nfrom .attribute import Attribute\nfrom .constraint import Constraint\nfrom .diagram_link import DiagramLink\nfrom .entity import Entity\nfrom .grid import Grid\nfrom .inheritance import Inheritance\nfrom .mocodo_error import MocodoError\nfrom .phantom import Phantom\nfrom .tools.string_tools import raw_to_bid\nfrom .tools.parser_tools import extract_clauses\n\ndef cmp(x, y):\n    return (x > y) - (x < y)\n\nSYS_MAXINT = 9223372036854775807 # an integer larger than any practical list or string index\n\nclass Mcd:\n\n    def __init__(self, source, get_font_metrics=None, **params):\n        \n        def calculate_uid():\n            h = md5(source.encode(\"utf-8\")).hexdigest()\n            if params.get(\"uid_suffix\"):\n                return f\"{h[:8]}_{params['uid_suffix']}\"\n            else:\n                return h[:8]\n\n        def create():\n            self.entities = {}\n            self.associations = {}\n            self.constraints = []\n            self.inheritances = []\n            mcd_has_cif = False\n            self.commented_lines = []\n            self.constraint_clauses = []\n            seen = set()\n            self.rows = [[]]\n            pages = defaultdict(list)\n            for clause in extract_clauses(source):\n                indentation = clause.get(\"indent\", \"\")\n                if clause[\"type\"] == \"break\":\n                    self.rows.append([])\n                    continue\n                if clause[\"type\"] == \"comment\":\n                    if not self.rows[-1]:\n                        self.commented_lines.append(clause[\"text\"])\n                    continue\n                if clause[\"type\"] == \"phantoms\":\n                    phantoms = [Phantom() for _ in range(clause[\"count\"])]\n                    if self.rows[-1]:\n                        self.rows[-1].extend(phantoms)\n                    else:\n                        self.rows.append(phantoms)\n                    continue\n                if clause[\"type\"] == \"constraint\":\n                    element = Constraint(clause)\n                    if element.name_view == \"CIF\":\n                        mcd_has_cif = True\n                    self.constraints.append(element)\n                    pages[indentation].append(element)\n                    self.constraint_clauses.append(clause)\n                    continue\n                if clause[\"type\"] == \"inheritance\":\n                    element = Inheritance(clause, **params)\n                    self.inheritances.append(element)\n                    pages[indentation].append(element)\n                else:\n                    if clause[\"type\"] == \"association\":\n                        element = Association(clause, **params)\n                        if element.bid in self.associations:\n                            raise MocodoError(7, _('Duplicate association \"{name}\". If you want to make two associations appear with the same name, you must suffix it with a number.').format(name=element.raw_name)) # fmt: skip\n                        self.associations[element.bid] = element\n                        pages[indentation].append(element)\n                    elif clause[\"type\"] == \"entity\":\n                        element = Entity(clause)\n                        if element.bid in self.entities:\n                            raise MocodoError(6, _('Duplicate entity \"{name}\". If you want to make two entities appear with the same name, you must suffix it with a number.').format(name=element.raw_name)) # fmt: skip\n                        self.entities[element.bid] = element\n                        pages[indentation].append(element)\n                    else:\n                        raise NotImplementedError\n                    if element.bid in seen:\n                        raise MocodoError(8, _('One entity and one association share the same name \"{name}\".').format(name=element.raw_name)) # fmt: skip\n                    seen.add(element.bid)\n                self.rows[-1].append(element)\n            if not seen:\n                raise MocodoError(4, _('The ERD \"{title}\" is empty.').format(title=params[\"title\"])) # fmt: skip\n            self.rows = [row for row in self.rows if row]\n            self.col_count = max(len(row) for row in self.rows)\n            self.row_count = len(self.rows)\n            self.page_count = len(pages)\n            for (i, (indentation, elements)) in enumerate(sorted(pages.items(), key=lambda x: x[0])):\n                for element in elements:\n                    element.page = i\n            self.header = \"\\n\".join(self.commented_lines) + \"\\n\\n\" if self.commented_lines else \"\"\n            for association in self.associations.values():\n                association.register_mcd_has_cif(mcd_has_cif)\n        \n        def add_legs():\n            for association in self.associations.values():\n                for leg in association.legs:\n                    if leg.entity_bid in self.entities:\n                        entity = self.entities[leg.entity_bid]\n                    elif leg.entity_bid in self.associations:\n                        raise MocodoError(18, _('Association \"{association}\" linked to another association \"{entity}\"!').format(association=association.bid, entity=leg.entity_bid)) # fmt: skip\n                    else:\n                        raise MocodoError(1, _('Association \"{association}\" linked to an unknown entity \"{entity}\"!').format(association=association.bid, entity=leg.entity_bid)) # fmt: skip\n                    leg.register_entity(entity)\n            for inheritance in self.inheritances:\n                for leg in inheritance.legs:\n                    if leg.entity_bid in self.entities:\n                        entity = self.entities[leg.entity_bid]\n                    elif leg.entity_bid in self.associations:\n                        raise MocodoError(44, _('Inheritance \"{inheritance}\" linked to an association \"{entity}\"!').format(inheritance=inheritance.bid, entity=leg.entity_bid))\n                    else:\n                        raise MocodoError(42, _('Inheritance \"{inheritance}\" linked to an unknown entity \"{entity}\"!').format(inheritance=inheritance.bid, entity=leg.entity_bid))\n                    leg.register_entity(entity)\n            for constraint in self.constraints:\n                for leg in constraint.legs:\n                    if leg.bid in self.associations:\n                        box = self.associations[leg.bid]\n                    elif leg.bid in self.entities:\n                        box = self.entities[leg.bid]\n                    else:\n                        raise MocodoError(40, _('Constraint \"{constraint}\" linked to an unknown entity or association \"{box}\"!').format(constraint=constraint.bid, box=leg.bid)) # fmt: skip\n                    leg.register_box(box)\n                for coord in constraint.coords:\n                    if isinstance(coord, (float, int)):\n                        continue\n                    bid = raw_to_bid(coord)\n                    if bid in self.associations or bid in self.entities:\n                        continue\n                    raise MocodoError(43, _('Constraint \"{constraint}\" aligned with an unknown entity or association \"{box}\"!').format(constraint=constraint.bid, box=bid)) # fmt: skip\n        \n        def add_attributes():\n            strengthening_legs = dict((entity_bid, []) for entity_bid in self.entities)\n            for association in self.associations.values():\n                for leg in association.legs:\n                    if leg.kind == \"strengthening\":\n                        strengthening_legs[leg.entity_bid].append(leg)\n            children = set()\n            for inheritance in self.inheritances:\n                for leg in inheritance.legs[1:]: # the first leg is the parent\n                    children.add(leg.entity_bid) # the other legs are its children\n            Attribute.id_gutter_strong_string = params[\"id_gutter_strong_string\"]\n            Attribute.id_gutter_weak_string = params[\"id_gutter_weak_string\"]\n            Attribute.id_gutter_alts = params[\"id_gutter_alts\"]\n            for (entity_bid, entity) in self.entities.items():\n                entity.add_attributes(\n                    legs_to_strengthen=strengthening_legs[entity_bid],\n                    is_child=entity_bid in children,\n                    fk_format=params.get(\"fk_format\", \"#{label}\")\n                )\n            self.has_alt_identifier = any(entity.has_alt_identifier for entity in self.entities.values())\n\n        def check_weak_entities_without_discriminator():\n            too_weak_entities = defaultdict(int)\n            for association in self.associations.values():\n                for leg in association.legs:\n                    if leg.kind != \"strengthening\":\n                        continue\n                    for attribute in leg.entity.attributes:\n                        if attribute.kind == \"weak\":\n                            break\n                    else: # the weak entity has no discriminator.\n                        # Ensure the max cards of the other legs are 1\n                        for other_leg in association.legs:\n                            if other_leg is leg:\n                                continue\n                            if other_leg.card[1] != \"1\":\n                                # Otherwise, accumulate them\n                                too_weak_entities[leg.entity.bid] += 1\n            for (too_weak_entity, count) in too_weak_entities.items():\n                if count < 2: # one isolated \"too weak entity\"\n                    raise MocodoError(50, _('The weak entity \"{entity}\" should have a discriminator.').format(entity=too_weak_entity)) # fmt: skip\n        \n        def set_id_gutter_visibility():\n            flag = params[\"id_gutter_visibility\"]\n            is_visible = flag == \"on\" or (flag == \"auto\" and self.has_alt_identifier)\n            for entity in self.entities.values():\n                entity.set_id_gutter_visibility(is_visible)\n        \n        def tweak_straight_cards():\n            coordinates = {}\n            for (j, row) in enumerate(self.rows):\n                for (i, box) in enumerate(row):\n                    coordinates[box] = (i, j)\n            d = defaultdict(list)\n            tweakable_legs = {}\n            for association in self.associations.values():\n                if association.is_invisible:\n                    continue\n                for leg in association.legs:\n                    (ei, ej) = coordinates[leg.entity]\n                    (ai, aj) = coordinates[leg.association]\n                    vector = (cmp(ai, ei), cmp(aj, ej))\n                    vector = (\" SN\"[cmp(aj, ej)] + \" EW\"[cmp(ai, ei)]).strip()\n                    d[leg.entity].append(vector)\n                    tweakable_legs[(leg.entity, vector)] = leg\n            flex = params.get(\"flex\", 0)\n            for (entity, vectors) in d.items():\n                for vector in vectors:\n                    leg = tweakable_legs[(entity, vector)]\n                    if not leg.card_view.strip():\n                        continue\n                    elif vector == \"E\":\n                        if vectors.count(\"E\") == 1 and \"SE\" in vectors and \"NE\" not in vectors:\n                            leg.twist = True\n                    elif vector == \"S\":\n                        if vectors.count(\"S\") == 1 and \"SE\" in vectors and \"SW\" not in vectors:\n                            leg.twist = True\n                    elif vector == \"W\":\n                        if vectors.count(\"W\") == 1 and \"SW\" in vectors and \"NW\" not in vectors:\n                            leg.twist = True\n                    elif vector == \"N\":\n                        if vectors.count(\"N\") == 1 and \"NE\" in vectors and \"NW\" not in vectors:\n                            leg.twist = True\n                    elif flex == 0:\n                        continue\n                    elif vector == \"SE\" and vectors.count(\"SE\") == 1:\n                        if vectors.count(\"E\") > 1:\n                            leg.set_spin_strategy(flex)\n                        elif vectors.count(\"S\") > 1:\n                            leg.set_spin_strategy(-flex)\n                    elif vector == \"SW\" and vectors.count(\"SW\") == 1:\n                        if vectors.count(\"S\") > 1:\n                            leg.set_spin_strategy(flex)\n                        elif vectors.count(\"W\") > 1:\n                            leg.set_spin_strategy(-flex)\n                    elif vector == \"NW\" and vectors.count(\"NW\") == 1:\n                        if vectors.count(\"W\") > 1:\n                            leg.set_spin_strategy(flex)\n                        elif vectors.count(\"N\") > 1:\n                            leg.set_spin_strategy(-flex)\n                    elif vector == \"NE\" and vectors.count(\"NE\") == 1:\n                        if vectors.count(\"N\") > 1:\n                            leg.set_spin_strategy(flex)\n                        elif vectors.count(\"E\") > 1:\n                            leg.set_spin_strategy(-flex)\n        \n        def add_diagram_links():\n            self.diagram_links = []\n            for entity in self.entities.values():\n                for attribute in entity.attributes:\n                    if attribute.primary_entity_bid:\n                        self.diagram_links.append(DiagramLink(self.entities, entity, attribute))\n            \n        def may_center():\n            for row in self.rows:\n                n = self.col_count - len(row)\n                if n:\n                    row[0:0] = [Phantom() for i in range(n // 2)]\n                    row.extend(Phantom() for i in range(n // 2 + n % 2))\n        \n        def make_boxes():\n            i = itertools.count()\n            self.boxes = []\n            for row in self.rows:\n                for box in row:\n                    box.index = next(i)\n                    self.boxes.append(box)\n                    box.register_boxes(self.boxes)\n            self.box_count = len(self.boxes)\n\n        # The following keys are actually created by __main__.py.\n        # Using `get` instead of `[]` is for testing purposes only.\n        params.setdefault(\"id_gutter_strong_string\", \"ID\")\n        params.setdefault(\"id_gutter_weak_string\", \"id\")\n        params.setdefault(\"id_gutter_alts\", dict(zip(\"123456789\", \"123456789\")))\n        params.setdefault(\"id_gutter_visibility\", \"auto\")\n\n        self.get_font_metrics = get_font_metrics\n        Phantom.reset_counter()\n        Association.reset_df_counter()\n        Inheritance.reset_counter()\n        Constraint.reset_counter()\n        self.uid = calculate_uid()\n        create()\n        self.update_footer()\n        add_legs()\n        add_attributes()\n        check_weak_entities_without_discriminator()\n        set_id_gutter_visibility()\n        add_diagram_links()\n        may_center()\n        make_boxes()\n        tweak_straight_cards()\n        self.title = params.get(\"title\", \"Untitled\")\n\n    def get_notes_data(self):\n        notes_data = {}\n        for association in self.associations.values():\n            components = association.get_note_data()\n            for (lid, leg) in components.items():\n                leg[\"subject\"] = self.entities[leg[\"subject\"]].name_view\n                leg[\"objects\"] = [self.entities[bid].name_view for bid in leg[\"objects\"]]\n                note = leg.pop(\"note\")\n                leg[\"jsonl\"] = json.dumps(leg, ensure_ascii=False)\n                leg[\"tsv\"] = \"\\t\".join(str(leg[k]) for k in [\"subject\", \"predicate\", \"min\", \"max\", \"objects\"])\n                leg[\"note\"] = note\n                notes_data[lid] = leg   \n        return notes_data\n    \n    def update_notes_data(self, notes_data):\n        for association in self.associations.values():\n            for leg in association.legs:\n                if leg.lid in notes_data:\n                    leg.note = notes_data[leg.lid]\n\n    def update_footer(self):\n        constraint_sources = [constraint.source for constraint in self.constraints]\n        self.footer = \"\\n\\n\" + \"\\n\".join(constraint_sources) if constraint_sources else \"\"\n\n    def get_layout_data(self):\n        successors = [set() for i in range(self.box_count)] # use `set` to deduplicate reflexive associations\n        multiplicity = defaultdict(int) # but count the multiplicity (1 or 2) of each link\n        for inheritance in self.inheritances:\n            for leg in inheritance.legs:\n                successors[inheritance.index].add(leg.entity.index)\n                successors[leg.entity.index].add(inheritance.index)\n                multiplicity[(inheritance.index, leg.entity.index)] += 1\n                multiplicity[(leg.entity.index, inheritance.index)] += 1\n        if self.associations:\n            for association in self.associations.values():\n                for leg in association.legs:\n                    successors[association.index].add(leg.entity.index)\n                    successors[leg.entity.index].add(association.index)\n                    multiplicity[(association.index, leg.entity.index)] += 1\n                    multiplicity[(leg.entity.index, association.index)] += 1\n        else:\n            for diagram_link in self.diagram_links:\n                fei = diagram_link.foreign_entity.index\n                pei = diagram_link.primary_entity.index\n                if fei != pei:\n                    successors[fei].add(pei)\n                    successors[pei].add(fei)\n                    multiplicity[(fei, pei)] += 1\n                    multiplicity[(pei, fei)] += 1\n        links = tuple((node, child) for (node, children) in enumerate(successors) for child in children if node < child)\n        return {\n            \"links\": links,\n            \"successors\": successors,\n            \"col_count\": self.col_count,\n            \"row_count\": self.row_count,\n            \"multiplicity\": dict(multiplicity)\n        }\n    \n    def get_layout(self):\n        return [box.index for row in self.rows for box in row]\n    \n    def get_row_text(self, row):\n        return \"\\n\".join(box.source for box in row)\n    \n    def get_non_phantom_count(self):\n        return sum(box.kind != \"phantom\" for box in self.boxes)\n\n    def set_layout(self, layout, col_count=None, row_count=None, **kwargs):\n        if col_count and row_count:\n            (self.col_count, self.row_count) = (col_count, row_count)\n        def get_or_create_box(index):\n            return Phantom() if layout[index] is None else self.boxes[layout[index]]\n        i = itertools.count()\n        self.rows = [[get_or_create_box(next(i)) for x in range(self.col_count)] for y in range(self.row_count)]\n        def suppress_empty_rows(y):\n            while self.rows: # there's at least one row\n                for box in self.rows[y]:\n                    if box.kind != \"phantom\":\n                        return\n                del self.rows[y]\n                self.row_count -= 1\n        suppress_empty_rows(0)\n        suppress_empty_rows(-1)\n        def suppress_empty_cols(x):\n            while self.rows[0]: # there's at least one column\n                for row in self.rows:\n                    if row[x].kind != \"phantom\":\n                        return\n                for row in self.rows:\n                    del row[x]\n                self.col_count -= 1\n        suppress_empty_cols(0)\n        suppress_empty_cols(-1)\n    \n    def get_clauses(self):\n        result = self.header\n        if self.associations:\n            result += \"\\n\\n\".join(self.get_row_text(row) for row in self.rows)\n        else:\n            result += \"\\n\\n\".join(\":\\n\" + \"\\n:\\n\".join(self.get_row_text(row).split(\"\\n\")) + \"\\n:\" for row in self.rows)\n        return result + self.footer\n\n    def get_vertically_flipped_clauses(self):\n        for constraint in self.constraints:\n            constraint.invert_coords_horizontal_mirror()\n        self.update_footer()\n        return self.header + \"\\n\\n\".join(self.get_row_text(row) for row in self.rows[::-1]) + self.footer\n    \n    def get_horizontally_flipped_clauses(self):\n        for constraint in self.constraints:\n            constraint.invert_coords_vertical_mirror()\n        self.update_footer()\n        return self.header + \"\\n\\n\".join(self.get_row_text(row[::-1]) for row in self.rows) + self.footer\n    \n    def get_diagonally_flipped_clauses(self):\n        for constraint in self.constraints:\n            constraint.invert_coords_diagonal_mirror()\n        self.update_footer()\n        return self.header + \"\\n\\n\".join(self.get_row_text(row) for row in zip(*self.rows)) + self.footer\n    \n    def get_refitted_clauses(self, nth_fit_or_col_count, row_count=None):\n        if row_count:\n            col_count = nth_fit_or_col_count\n        else:\n            nth_fit = nth_fit_or_col_count\n            grid = Grid(len(self.boxes) + 100) # make sure there are enough precalculated grids\n            start = len(self.entities) + len(self.associations) # number of nonempty boxes\n            (col_count, row_count) = grid.get_nth_next(start, nth_fit)\n        result = []\n        i = 0\n        for box in self.boxes:\n            if box.kind != \"phantom\":\n                if i % col_count == 0 and i:\n                    result.append(\"\")\n                result.append(\"  \" * box.page + box.source.rstrip())\n                i += 1\n        for i in range(i, col_count * row_count):\n            if i % col_count == 0 and i:\n                result.append(\"\")\n            result.append(\":\")\n        return self.header + \"\\n\".join(result) + self.footer\n\n\n    def calculate_or_retrieve_geo(self, params):\n        geo_path = Path(f\"{params['output_name']}_geo.json\")\n        if geo_path.is_file() and params[\"scale\"] == 1 and params[\"reuse_geo\"]:\n            try:\n                web_geo = json.loads(geo_path.read_text(encoding=\"utf8\"))\n            except:\n                raise MocodoError(33, _('Unable to reuse the geometry file \"{filename}\".').format(filename=geo_path)) # fmt: skip\n            # convert lists of couples to dicts\n            geo = {}\n            for (k, v) in web_geo.items():\n                if isinstance(v, list):\n                    geo[k] = dict(v)\n                else:\n                    geo[k] = v\n            return geo\n        geo = {\n            \"width\": self.w,\n            \"height\": self.h,\n            \"cx\": {\n                box.bid: box.x + box.w // 2\n                for row in self.rows\n                for box in row\n                if box.kind != \"phantom\"\n            },\n            \"cy\": {\n                box.bid: box.y + box.h // 2\n                for row in self.rows\n                for box in row\n                if box.kind != \"phantom\"\n            },\n            \"shift\": {\n                leg.lid: 0\n                for row in self.rows\n                for box in row\n                for leg in box.legs\n                if hasattr(leg, \"card_view\")},\n            \"ratio\": {\n                leg.lid: 1.0\n                for row in self.rows\n                for box in row\n                for leg in box.legs\n                if leg.arrow\n            },\n        }\n        web_geo = {k: list(v.items()) if isinstance(v, dict) else v for (k, v) in geo.items()}\n        text = json.dumps(web_geo, indent=2, ensure_ascii=False)\n        text = text.replace(\"\\n      \", \" \")\n        text = text.replace(\"\\n    ]\", \" ]\")\n        text = text + \"\\n\"\n        try:\n            geo_path.write_text(text, encoding=\"utf8\")\n        except IOError:\n            raise MocodoError(34, _('Unable to save geometry file \"{filename}\".').format(filename=geo_path)) # fmt: skip\n        return geo\n\n\n    def calculate_size(self, style):\n\n        def increase_margins_in_presence_of_clusters():\n            if not self.associations: # relational diagram or MCD without associations\n                return\n            factor = 1 + max(a.peg_count for a in self.associations.values())\n            style[\"margin\"] *= factor\n            style[\"card_margin\"] *= factor\n\n        def card_max_width():\n            get_pixel_width = self.get_font_metrics(style[\"card_font\"]).get_pixel_width\n            cardinalities = {\"0,N\"} # default value, in case there is no cardinalities at all\n            for association in self.associations.values():\n                for leg in association.legs:\n                    cardinalities.add(leg.card_view.strip(\"_\"))\n            return max(map(get_pixel_width, cardinalities))\n        #\n        def calculate_sizes():\n            for row in self.rows:\n                for (i, box) in enumerate(row):\n                    box.calculate_size(style, self.get_font_metrics)\n                    max_box_width_per_column[i] = max(box.w, max_box_width_per_column[i])\n            for diagram_link in self.diagram_links:\n                diagram_link.calculate_size(style, self.get_font_metrics)\n            for constraint in self.constraints:\n                constraint.calculate_size(style, self.get_font_metrics)\n        #\n        def make_horizontal_layout():\n            self.w = style[\"margin\"]\n            for row in self.rows:\n                horizontal_offset = style[\"margin\"]\n                for (i, box) in enumerate(row):\n                    box.x = horizontal_offset + (max_box_width_per_column[i] - box.w) // 2\n                    horizontal_offset += max_box_width_per_column[i] + join_width\n                self.w = max(self.w, horizontal_offset)\n            self.w += style[\"margin\"] - join_width\n        #\n        def compress_horizontally():\n            dx = 0\n            for i in range(1, self.col_count):\n                dx = SYS_MAXINT\n                for row in self.rows:\n                    b1 = row[i-1]\n                    b2 = row[i]\n                    space = b2.x - b1.x - b1.w - join_width\n                    dx = min(dx, space)\n                for row in self.rows:\n                    row[i].x -= dx\n            self.w -= dx\n        #\n        def make_vertical_layout():\n            vertical_offset = style[\"margin\"]\n            for row in self.rows:\n                max_box_height = max(box.h for box in row)\n                for box in row:\n                    box.y = vertical_offset + (max_box_height - box.h) // 2\n                vertical_offset += max_box_height + join_height\n            self.h = vertical_offset + style[\"margin\"] - join_height\n        #\n        def compress_vertically():\n            dy = 0\n            for j in range(1, self.row_count):\n                dy = SYS_MAXINT\n                for (i2, b2) in enumerate(self.rows[j]):\n                    y1_max = 0\n                    for (i1, b1) in enumerate(self.rows[j-1]):\n                        if (i1 == i2) or (b1.x < b2.x < b1.x + b1.w + join_width) or (b1.x - join_width < b2.x + b2.w < b1.x + b1.w):\n                            y1_max = max(y1_max, b1.y + b1.h)\n                    space = b2.y - y1_max - join_height\n                    dy = min(dy, space)\n                for box in self.rows[j]:\n                    box.y -= dy\n            self.h -= dy\n        #\n\n        increase_margins_in_presence_of_clusters()\n        style[\"card_max_width\"] = card_max_width()\n        style[\"card_max_height\"] = self.get_font_metrics(style[\"card_font\"]).get_pixel_height()\n        join_width  = 2 * style[\"card_margin\"] + style[\"card_max_width\"]\n        join_height = 2 * style[\"card_margin\"] + style[\"card_max_height\"]\n        max_box_width_per_column = [0] * self.col_count\n        calculate_sizes()\n        make_horizontal_layout()\n        compress_horizontally()\n        make_vertical_layout()\n        compress_vertically()\n    \n    def description(self, style, geo):\n        for box in self.boxes:\n            box.register_center(geo)\n        for constraint in self.constraints:\n            constraint.register_center(geo)\n        result = []\n        for element in self.entities.values():\n            result.extend(element.description(style, geo))\n        for element in self.associations.values():\n            result.extend(element.description(style, geo))\n        for element in self.inheritances:\n            result.extend(element.description(style, geo))\n        for element in self.diagram_links:\n            result.extend(element.description(style, geo))\n        for element in self.constraints:\n            result.extend(element.description(style, geo))\n        result.append((\"comment\", {\"text\": \"Notes\"}))\n        result.append(\n            (\n                \"notes\",\n                {\n                    \"height_threshold\": geo[\"height\"] - style[\"note_overlay_height\"] - style[\"card_margin\"],\n                    \"overlay_height\": style[\"note_overlay_height\"],\n                    \"x\": geo[\"width\"] // 2,\n                    \"y_top\": style[\"note_baseline\"],\n                    \"y_bottom\": geo[\"height\"] - style[\"note_overlay_height\"] + style[\"note_baseline\"],\n                    \"y\": geo[\"height\"] - style[\"note_overlay_height\"],\n                    \"color\": style[\"note_color\"],\n                    \"text_color\": style[\"note_text_color\"],\n                    \"opacity\": style[\"note_opacity\"],\n                    \"font_family\": style[\"note_font\"][\"family\"],\n                    \"font_size\": style[\"note_font\"][\"size\"],\n                }\n            )\n        )\n        if self.page_count > 1:\n            diameter = style[\"note_overlay_height\"] / 4\n            result.append((\"comment\", {\"text\": \"Pager\"}))\n            for i in range(self.page_count):\n                result.append(\n                    (\n                        \"pager_dot\",\n                        {\n                            \"cx\": geo[\"width\"] / 2 - (self.page_count - 1 - 2 * i) * diameter,\n                            \"cy\": geo[\"height\"] + 2 * diameter,\n                            \"r\": diameter / 2,\n                            \"color\": \"lightgray\" if i else \"gray\",\n                            \"page\": i,\n                        }\n                    )\n                )\n            result.append((\"pager\", {\"page_count\": self.page_count}))\n        return result\n    \n    def get_overlaps(self):\n        \"\"\"\n        Detect the cases when two legs overlap each other or when a leg overlaps a box.\n        \n        The detection is based on the assumption that the boxes are arranged in a grid\n        (and doesn't take into account any tweaks that may have been applied to the box\n        centers). To unify the detection, the boxes are treated as zero-length legs.\n        Only horizontal and vertical overlaps are detected.\n        \"\"\"\n        coordinates = {}\n        for (j, row) in enumerate(self.rows):\n            for (i, box) in enumerate(row):\n                coordinates[box] = (i, j)\n        segments = defaultdict(list)\n        for entity in self.entities.values():\n            if entity.is_invisible:\n                continue\n            (ie, je) = coordinates[entity]\n            segments[\"i\", ie].append((je, je, entity, entity))\n            segments[\"j\", je].append((ie, ie, entity, entity))\n        for association in self.associations.values():\n            if association.is_invisible:\n                continue\n            (ia, ja) = coordinates[association]\n            segments[(\"i\", ia)].append((ja, ja, association, association))\n            segments[(\"j\", ja)].append((ia, ia, association, association))\n            for leg in association.legs:\n                (ie, je) = coordinates[leg.entity]\n                if ia == ie:\n                    segments[(\"i\", ia)].append((*sorted([ja, je]), association, leg.entity))\n                elif ja == je:\n                    segments[(\"j\", ja)].append((*sorted([ia, ie]), association, leg.entity))\n        result = []\n        for quadruples in segments.values():\n            quadruples.sort()\n            for (l1, r1, e1, a1), (l2, r2, e2, a2) in zip(quadruples, quadruples[1:]):\n                if e1.bid == e2.bid and a1.bid == a2.bid: # reflexive association\n                    continue\n                if l2 < r1:\n                    result.append((e1.bid, a1.bid, e2.bid, a2.bid))\n        return result\n\nif __name__==\"__main__\":\n    from .argument_parser import parsed_arguments\n    source = \"\"\"\n        CLIENT: Réf. client, Nom, Prénom, Adresse\n        PASSER, 0N CLIENT, 11 COMMANDE\n        COMMANDE: Num commande, Date, Montant\n        INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n        PRODUIT: Réf. produit, Libellé, Prix unitaire\n    \"\"\".replace(\"  \", \"\").split(\"\\n\")\n    params = parsed_arguments()\n    mcd = Mcd(source, **params)\n    print(mcd.get_horizontally_flipped_clauses())\n"
  },
  {
    "path": "mocodo/mcd_to_svg.py",
    "content": "from pathlib import Path\nimport re\n\nfrom .mocodo_error import MocodoError\nfrom . import __version__\n\ntry:\n    from cairosvg import svg2png, svg2pdf\nexcept:\n    def svg2png(**kargs):\n        raise MocodoError(13, _(\"PNG and PDF generation requires cairosvg to be installed\")) # fmt: skip\n    svg2pdf = svg2png\n\n\ndef main(mcd, common, suppress_mocodo_header=False):\n    mocodo_header = \"\" if suppress_mocodo_header else f\"<!-- Generated by Mocodo {__version__} -->\\n\"\n    style = common.load_style()\n    mcd.calculate_size(style)\n    geo = mcd.calculate_or_retrieve_geo(common.params)\n    try:\n        description = mcd.description(style, geo)\n    except KeyError: # retry silently with a fresh geo file if the previous one concerns another MCD\n        Path(f\"{common.params['output_name']}_geo.json\").unlink()\n        geo = mcd.calculate_or_retrieve_geo(common.params)\n        description = mcd.description(style, geo)\n    description = [\n        (\n            \"preamble\",\n            {\n                \"width\": geo[\"width\"],\n                \"height\": geo[\"height\"],\n                \"total_height\": geo[\"height\"] + (mcd.page_count > 1 and style[\"note_overlay_height\"]),\n            }\n        ),\n        (\n            \"background\",\n            {\n                \"width\": geo[\"width\"],\n                \"height\": geo[\"height\"],\n                \"background_color\": style[\"background_color\"],\n            }\n        ),\n        *description,\n    ]\n    has_note_card = False\n    tabs = 0\n    categories = { # the order is that of the drawing in the SVG\n        \"\": [],\n        \"Constraint\": [],\n        \"Inheritance\": [],\n        \"Association\": [],\n        \"Entity\": [],\n        \"Link\": [],\n        \"Notes\": [],\n        \"Pager\": [],\n    }\n    category = \"\"\n    for (key, mapping) in description:\n        mapping[\"mcd_uid\"] = mcd.uid\n        has_note_card |= key.endswith(\"with_note\")\n        if key == \"comment\":\n            category = mapping[\"text\"].partition(\" \")[0]\n        for (k, v) in mapping.items():\n            if isinstance(v, float):\n                mapping[k] = int(v) if v.is_integer() else round(v, 2)\n            elif isinstance(v, str):\n                mapping[k] = html_escape(v)\n            elif v is None:\n                mapping[k] = \"none\"\n        mapping[\"mocodo_header\"] = mocodo_header\n        # print(key, mapping, end=\"\\n\")\n        tabs -= (key == \"end\")\n        categories[category].append('\\t' * tabs + svg_elements[key].format_map(mapping))\n        tabs += key.startswith(\"begin\")\n    if not has_note_card:\n        del categories[\"Notes\"]\n    text = \"\\n\".join(sum(categories.values(), [])) + \"\\n</svg>\"\n    is_interactive = categories.get(\"Notes\") or categories.get(\"Pager\")\n    if not is_interactive:\n        text = re.sub(r'<g class=\"page_0_\\w{8}(_\\d+)? diagram_page\" visibility=\"visible\">', \"<g>\", text)\n    path = Path(f\"{common.params['output_name']}.svg\")\n    path.write_text(text, encoding=\"utf8\")\n    resulting_paths = [path]\n    if categories.pop(\"Notes\", []) + categories.pop(\"Pager\"): # don't use `or` to avoid short-circuit\n        text = \"\\n\".join(sum(categories.values(), [])) + \"\\n</svg>\"\n        text = re.sub(\n            r\"(?m)^<\\?xml .+\\n<svg .+\",\n            svg_elements[\"preamble\"].format(mocodo_header=mocodo_header, total_height=geo[\"height\"], **geo),\n            text\n        )\n        text = re.sub(r\"(?m)^<g class.+\", \"<g>\", text)\n        text = re.sub(r' (onmouseover|onmouseout|style|id)=\".+?\"', \"\", text)\n        path = Path(f\"{common.params['output_name']}_static.svg\")\n        path.write_text(text, encoding=\"utf8\")\n        resulting_paths.append(path)\n    svg = bytes(text, \"utf-8\")\n    for (format, function) in ((\"png\", svg2png), (\"pdf\", svg2pdf)):\n        if format in common.params[\"svg_to\"]:\n            path = Path(f\"{common.params['output_name']}.{format}\")\n            function(bytestring=svg, write_to=str(path))\n            resulting_paths.append(path)\n    return resulting_paths\n\n\n\ndef html_escape(\n    text,\n    table={\n        \"&\": \"&amp;\",\n        \">\": \"&gt;\",\n        \"<\": \"&lt;\",\n        '\"': \"&quot;\",\n        \"'\": \"’\",  # neither &#39; nor &apos; make the job in notes\n        \"-\": \"&#45;\", # prevent double hyphen in SVG comments: https://stackoverflow.com/questions/10842131/xml-comments-and\n}):\n    return \"\".join(table.get(c, c) for c in text)\n\nsvg_elements = {\n    \"preamble\":         \"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n{mocodo_header}<svg width=\"{width}\" height=\"{total_height}\" viewBox=\"0 0 {width} {total_height}\" xmlns=\"http://www.w3.org/2000/svg\">\"\"\",\n    \"background\":       \"\"\"<rect x=\"0\" y=\"0\" width=\"{width}\" height=\"{height}\" fill=\"{background_color}\" stroke=\"none\" stroke-width=\"0\"/>\"\"\",\n    \"comment\":          \"\"\"\\n<!-- {text} -->\"\"\",\n    \"begin_component\":  \"\"\"<g class=\"page_{page}_{mcd_uid} diagram_page\" visibility=\"{visibility}\">\"\"\",\n    \"begin_group\":      \"\"\"<g>\"\"\",\n    \"end\":              \"\"\"</g>\"\"\",\n    \"text\":             \"\"\"<text x=\"{x}\" y=\"{y}\" fill=\"{text_color}\" font-family=\"{family}\" font-size=\"{size}\">{text}</text>\"\"\",\n    \"text_above_note\":  \"\"\"<text x=\"{x}\" y=\"{y}\" fill=\"{text_color}\" font-family=\"{family}\" font-size=\"{size}\" style=\"pointer-events: none;\">{text}</text>\"\"\",\n    \"text_with_note\":   \"\"\"<text x=\"{x}\" y=\"{y}\" fill=\"{text_color}\" font-family=\"{family}\" font-size=\"{size}\" onmouseover=\"show_{mcd_uid}(evt,'{note}')\" onmouseout=\"hide_{mcd_uid}(evt)\" style=\"cursor: pointer;\">{text}</text>\"\"\",\n    \"line\":             \"\"\"<line x1=\"{x0}\" y1=\"{y0}\" x2=\"{x1}\" y2=\"{y1}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"/>\"\"\",\n    \"dash_line\":        \"\"\"<line x1=\"{x0}\" y1=\"{y0}\" x2=\"{x1}\" y2=\"{y1}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" stroke-dasharray=\"{dash_width}\"/>\"\"\",\n    \"dot_line\":         \"\"\"<line x1=\"{x0}\" y1=\"{y0}\" x2=\"{x1}\" y2=\"{y1}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"  stroke-dasharray=\"0,{dash_gap}\" stroke-linecap=\"round\"/>\"\"\",\n    \"rect\":             \"\"\"<rect x=\"{x}\" y=\"{y}\" width=\"{w}\" height=\"{h}\" fill=\"{color}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" opacity=\"{opacity}\"/>\"\"\",\n    \"polygon\":          \"\"\"<path d=\"{path}\" fill=\"{color}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" opacity=\"{opacity}\"/>\"\"\",\n    \"dot_polygon\":      \"\"\"<path d=\"{path}\" fill=\"{color}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" stroke-dasharray=\"0,{dash_gap}\" stroke-linecap=\"round\"/>\"\"\",\n    \"circle\":           \"\"\"<circle cx=\"{cx}\" cy=\"{cy}\" r=\"{r}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" fill=\"{color}\"/>\"\"\",\n    \"circle_with_note\": \"\"\"<circle cx=\"{cx}\" cy=\"{cy}\" r=\"{r}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" fill=\"{color}\" onmouseover=\"show_{mcd_uid}(evt,'{note}')\" onmouseout=\"hide_{mcd_uid}(evt)\" style=\"cursor: pointer;\"/>\"\"\",\n    \"pager_dot\":        \"\"\"<circle cx=\"{cx}\" cy=\"{cy}\" r=\"{r}\" fill=\"{color}\" id=\"pager_dot_{page}_{mcd_uid}\" class=\"pager_dot\" stroke-width=\"0\" onclick=\"switch_page_visibility_{mcd_uid}(evt,{page})\" style=\"cursor: pointer;\"/>\"\"\",\n    \"triangle\":         \"\"\"<polygon points=\"{x1} {y1} {x2} {y2} {x3} {y3}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\" fill=\"{color}\"/>\"\"\",\n    \"arrow\":            \"\"\"<polygon points=\"{x0} {y0} {x1} {y1} {x2} {y2} {x3} {y3}\" fill=\"{stroke_color}\" stroke-width=\"0\"/>\"\"\",\n    \"curve\":            \"\"\"<path d=\"M{x0} {y0} C{x1} {y1} {x2} {y2} {x3} {y3}\" fill=\"none\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"/>\"\"\",\n    \"round_rect\":       \"\"\"<rect x=\"{x}\" y=\"{y}\" width=\"{w}\" height=\"{h}\" fill=\"{color}\" rx=\"{radius}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"/>\"\"\",\n    \"upper_round_rect\": \"\"\"<path d=\"M{x0} {y0} a{r} {r} 90 0 1 {r} {r} V{y1} h-{w} V{y2} a{r} {r} 90 0 1 {r} -{r}\" fill=\"{color}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"/>\"\"\",\n    \"lower_round_rect\": \"\"\"<path d=\"M{x0} {y0} v{y1} a{r} {r} 90 0 1 -{r} {r} H{x1} a{r} {r} 90 0 1 -{r} -{r} V{y0} H{w}\" fill=\"{color}\" stroke=\"{stroke_color}\" stroke-width=\"{stroke_depth}\"/>\"\"\",\n    \"notes\":            \"\"\"<script type=\"text/ecmascript\">\n                            <![CDATA[\n                            \tfunction show_{mcd_uid}(evt, text) {{\n                            \t\tvar pos = (evt.target.getAttribute(\"y\") < {height_threshold}) ? \"bottom\" : \"top\";\n                            \t\tvar note = document.getElementById(pos + \"_note_{mcd_uid}\");\n                            \t\tnote.textContent = text;\n                            \t\tnote.setAttributeNS(null, \"visibility\", \"visible\");\n                            \t\tdocument.getElementById(pos + \"_overlay_{mcd_uid}\").setAttributeNS(null, \"visibility\", \"visible\");\n                            \t}}\n                            \tfunction hide_{mcd_uid}(evt) {{\n                            \t\tdocument.getElementById(\"top_note_{mcd_uid}\").setAttributeNS(null, \"visibility\", \"hidden\");\n                            \t\tdocument.getElementById(\"top_overlay_{mcd_uid}\").setAttributeNS(null, \"visibility\", \"hidden\");\n                            \t\tdocument.getElementById(\"bottom_note_{mcd_uid}\").setAttributeNS(null, \"visibility\", \"hidden\");\n                            \t\tdocument.getElementById(\"bottom_overlay_{mcd_uid}\").setAttributeNS(null, \"visibility\", \"hidden\");\n                            \t}}\n                            ]]>\n                            </script>\n                            <rect id=\"top_overlay_{mcd_uid}\" x=\"0\" y=\"0\" width=\"100%\" height=\"{overlay_height}\" fill=\"{color}\" stroke-width=\"0\" opacity=\"{opacity}\" visibility=\"hidden\"/>\n                            <text id=\"top_note_{mcd_uid}\" text-anchor=\"middle\" x=\"{x}\" y=\"{y_top}\" fill=\"{text_color}\" font-family=\"{font_family}\" font-size=\"{font_size}\" visibility=\"hidden\"></text>\n                            <rect id=\"bottom_overlay_{mcd_uid}\" x=\"0\" y=\"{y}\" width=\"100%\" height=\"{overlay_height}\" fill=\"{color}\" stroke-width=\"0\" opacity=\"{opacity}\" visibility=\"hidden\"/>\n                            <text id=\"bottom_note_{mcd_uid}\" text-anchor=\"middle\" x=\"{x}\" y=\"{y_bottom}\" fill=\"{text_color}\" font-family=\"{font_family}\" font-size=\"{font_size}\" visibility=\"hidden\"></text>\"\"\".replace(\"    \", \"\"),\n    \"pager\":            \"\"\"<script type=\"text/ecmascript\">\n                            <![CDATA[\n                            \tfunction switch_page_visibility_{mcd_uid}(evt, page) {{\n                            \t\tfor (var i = 0; i < {page_count}; i++) {{\n                            \t\t\tcomponents = document.getElementsByClassName(`page_${{i}}_{mcd_uid}`);\n                            \t\t\tfor (var j = 0; j < components.length; j++) {{\n                            \t\t\t\tcomponents[j].setAttributeNS(null, \"visibility\", i <= page ? \"visible\" : \"hidden\");\n                            \t\t\t}};\n                            \t\t\tdot = document.getElementById(`pager_dot_${{i}}_{mcd_uid}`);\n                            \t\t\tdot.setAttributeNS(null, \"fill\", i <= page ? \"gray\" : \"lightgray\");\n                            \t\t}}\n                            \t}}\n                            ]]>\n                            </script>\"\"\".replace(\"    \", \"\"),\n}\n\n\nif __name__ == \"__main__\":\n    from .argument_parser import parsed_arguments\n    from .common import Common\n    from .mcd import Mcd\n\n    clauses = \"\"\"\n        CLIENT: Réf. client, Nom, Prénom, Adresse\n        PASSER, 0N CLIENT, 11 COMMANDE\n        COMMANDE: Num commande, Date, Montant\n        INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n        PRODUIT: Réf. produit, Libellé, Prix unitaire\n    \"\"\"\n    params = parsed_arguments()\n    common = Common(params)\n    mcd = Mcd(clauses, **params)\n    main(mcd, common)\n"
  },
  {
    "path": "mocodo/mocodo_error.py",
    "content": "import textwrap\n\n\nclass MocodoError(Exception):\n    def __init__(self, errno, message):\n        message = f\"Mocodo Err.{errno} - {message}\"\n        message = \"\\n\".join(\n            [\n                \"\\n\".join(\n                    textwrap.wrap(\n                        line,\n                        88,\n                        break_long_words=False,\n                        replace_whitespace=False,\n                    )\n                )\n                for line in message.splitlines()\n                if line.strip() != \"\"\n            ]\n        )\n        self.errno = errno\n        super(MocodoError, self).__init__(message)\n\ndef subarg_error(subsubopt, subsubarg):\n    return MocodoError(19, _('Invalid sub-argument: \"{subsubopt}={subsubarg}\".').format(subsubopt=subsubopt, subsubarg=subsubarg))  # fmt: skip\n\ndef subsubopt_error(subsubopt):\n    return MocodoError(20, _('Invalid sub-sub-option: \"{subsubopt}\".').format(subsubopt=subsubopt))  # fmt: skip\n\ndef subopt_error(opt, subopt):\n    raise MocodoError(21, _('Unknown \"{opt}\" sub-option: \"{subopt}\".').format(opt=opt, subopt=subopt))  # fmt: skip\n"
  },
  {
    "path": "mocodo/parse_mcd.py",
    "content": "# The file was automatically generated by Lark v1.1.7\n__version__ = \"1.1.7\"\n\n#\n#\n#   Lark Stand-alone Generator Tool\n# ----------------------------------\n# Generates a stand-alone LALR(1) parser\n#\n# Git:    https://github.com/erezsh/lark\n# Author: Erez Shinan (erezshin@gmail.com)\n#\n#\n#    >>> LICENSE\n#\n#    This tool and its generated code use a separate license from Lark,\n#    and are subject to the terms of the Mozilla Public License, v. 2.0.\n#    If a copy of the MPL was not distributed with this\n#    file, You can obtain one at https://mozilla.org/MPL/2.0/.\n#\n#    If you wish to purchase a commercial license for this tool and its\n#    generated code, you may contact me via email or otherwise.\n#\n#    If MPL2 is incompatible with your free or open-source project,\n#    contact me and we'll work it out.\n#\n#\n\nfrom abc import ABC, abstractmethod\nfrom collections.abc import Sequence\nfrom types import ModuleType\nfrom typing import (\n    TypeVar, Generic, Type, Tuple, List, Dict, Iterator, Collection, Callable, Optional, FrozenSet, Any,\n    Union, Iterable, IO, TYPE_CHECKING, overload,\n    Pattern as REPattern, ClassVar, Set, Mapping\n)\n\n\nclass LarkError(Exception):\n    pass\n\n\nclass ConfigurationError(LarkError, ValueError):\n    pass\n\n\ndef assert_config(value, options: Collection, msg='Got %r, expected one of %s'):\n    if value not in options:\n        raise ConfigurationError(msg % (value, options))\n\n\nclass GrammarError(LarkError):\n    pass\n\n\nclass ParseError(LarkError):\n    pass\n\n\nclass LexError(LarkError):\n    pass\n\nT = TypeVar('T')\n\nclass UnexpectedInput(LarkError):\n    #--\n    line: int\n    column: int\n    pos_in_stream = None\n    state: Any\n    _terminals_by_name = None\n\n    def get_context(self, text: str, span: int=40) -> str:\n        #--\n        assert self.pos_in_stream is not None, self\n        pos = self.pos_in_stream\n        start = max(pos - span, 0)\n        end = pos + span\n        if not isinstance(text, bytes):\n            before = text[start:pos].rsplit('\\n', 1)[-1]\n            after = text[pos:end].split('\\n', 1)[0]\n            return before + after + '\\n' + ' ' * len(before.expandtabs()) + '^\\n'\n        else:\n            before = text[start:pos].rsplit(b'\\n', 1)[-1]\n            after = text[pos:end].split(b'\\n', 1)[0]\n            return (before + after + b'\\n' + b' ' * len(before.expandtabs()) + b'^\\n').decode(\"ascii\", \"backslashreplace\")\n\n    def match_examples(self, parse_fn: 'Callable[[str], Tree]',\n                             examples: Union[Mapping[T, Iterable[str]], Iterable[Tuple[T, Iterable[str]]]],\n                             token_type_match_fallback: bool=False,\n                             use_accepts: bool=True\n                         ) -> Optional[T]:\n        #--\n        assert self.state is not None, \"Not supported for this exception\"\n\n        if isinstance(examples, Mapping):\n            examples = examples.items()\n\n        candidate = (None, False)\n        for i, (label, example) in enumerate(examples):\n            assert not isinstance(example, str), \"Expecting a list\"\n\n            for j, malformed in enumerate(example):\n                try:\n                    parse_fn(malformed)\n                except UnexpectedInput as ut:\n                    if ut.state == self.state:\n                        if (\n                            use_accepts\n                            and isinstance(self, UnexpectedToken)\n                            and isinstance(ut, UnexpectedToken)\n                            and ut.accepts != self.accepts\n                        ):\n                            logger.debug(\"Different accepts with same state[%d]: %s != %s at example [%s][%s]\" %\n                                         (self.state, self.accepts, ut.accepts, i, j))\n                            continue\n                        if (\n                            isinstance(self, (UnexpectedToken, UnexpectedEOF))\n                            and isinstance(ut, (UnexpectedToken, UnexpectedEOF))\n                        ):\n                            if ut.token == self.token:  ##\n\n                                logger.debug(\"Exact Match at example [%s][%s]\" % (i, j))\n                                return label\n\n                            if token_type_match_fallback:\n                                ##\n\n                                if (ut.token.type == self.token.type) and not candidate[-1]:\n                                    logger.debug(\"Token Type Fallback at example [%s][%s]\" % (i, j))\n                                    candidate = label, True\n\n                        if candidate[0] is None:\n                            logger.debug(\"Same State match at example [%s][%s]\" % (i, j))\n                            candidate = label, False\n\n        return candidate[0]\n\n    def _format_expected(self, expected):\n        if self._terminals_by_name:\n            d = self._terminals_by_name\n            expected = [d[t_name].user_repr() if t_name in d else t_name for t_name in expected]\n        return \"Expected one of: \\n\\t* %s\\n\" % '\\n\\t* '.join(expected)\n\n\nclass UnexpectedEOF(ParseError, UnexpectedInput):\n    #--\n    expected: 'List[Token]'\n\n    def __init__(self, expected, state=None, terminals_by_name=None):\n        super(UnexpectedEOF, self).__init__()\n\n        self.expected = expected\n        self.state = state\n        from .lexer import Token\n        self.token = Token(\"<EOF>\", \"\")  ##\n\n        self.pos_in_stream = -1\n        self.line = -1\n        self.column = -1\n        self._terminals_by_name = terminals_by_name\n\n\n    def __str__(self):\n        message = \"Unexpected end-of-input. \"\n        message += self._format_expected(self.expected)\n        return message\n\n\nclass UnexpectedCharacters(LexError, UnexpectedInput):\n    #--\n\n    allowed: Set[str]\n    considered_tokens: Set[Any]\n\n    def __init__(self, seq, lex_pos, line, column, allowed=None, considered_tokens=None, state=None, token_history=None,\n                 terminals_by_name=None, considered_rules=None):\n        super(UnexpectedCharacters, self).__init__()\n\n        ##\n\n        self.line = line\n        self.column = column\n        self.pos_in_stream = lex_pos\n        self.state = state\n        self._terminals_by_name = terminals_by_name\n\n        self.allowed = allowed\n        self.considered_tokens = considered_tokens\n        self.considered_rules = considered_rules\n        self.token_history = token_history\n\n        if isinstance(seq, bytes):\n            self.char = seq[lex_pos:lex_pos + 1].decode(\"ascii\", \"backslashreplace\")\n        else:\n            self.char = seq[lex_pos]\n        self._context = self.get_context(seq)\n\n\n    def __str__(self):\n        message = \"No terminal matches '%s' in the current parser context, at line %d col %d\" % (self.char, self.line, self.column)\n        message += '\\n\\n' + self._context\n        if self.allowed:\n            message += self._format_expected(self.allowed)\n        if self.token_history:\n            message += '\\nPrevious tokens: %s\\n' % ', '.join(repr(t) for t in self.token_history)\n        return message\n\n\nclass UnexpectedToken(ParseError, UnexpectedInput):\n    #--\n\n    expected: Set[str]\n    considered_rules: Set[str]\n    interactive_parser: 'InteractiveParser'\n\n    def __init__(self, token, expected, considered_rules=None, state=None, interactive_parser=None, terminals_by_name=None, token_history=None):\n        super(UnexpectedToken, self).__init__()\n\n        ##\n\n        self.line = getattr(token, 'line', '?')\n        self.column = getattr(token, 'column', '?')\n        self.pos_in_stream = getattr(token, 'start_pos', None)\n        self.state = state\n\n        self.token = token\n        self.expected = expected  ##\n\n        self._accepts = NO_VALUE\n        self.considered_rules = considered_rules\n        self.interactive_parser = interactive_parser\n        self._terminals_by_name = terminals_by_name\n        self.token_history = token_history\n\n\n    @property\n    def accepts(self) -> Set[str]:\n        if self._accepts is NO_VALUE:\n            self._accepts = self.interactive_parser and self.interactive_parser.accepts()\n        return self._accepts\n\n    def __str__(self):\n        message = (\"Unexpected token %r at line %s, column %s.\\n%s\"\n                   % (self.token, self.line, self.column, self._format_expected(self.accepts or self.expected)))\n        if self.token_history:\n            message += \"Previous tokens: %r\\n\" % self.token_history\n\n        return message\n\n\n\nclass VisitError(LarkError):\n    #--\n\n    obj: 'Union[Tree, Token]'\n    orig_exc: Exception\n\n    def __init__(self, rule, obj, orig_exc):\n        message = 'Error trying to process rule \"%s\":\\n\\n%s' % (rule, orig_exc)\n        super(VisitError, self).__init__(message)\n\n        self.rule = rule\n        self.obj = obj\n        self.orig_exc = orig_exc\n\n\nclass MissingVariableError(LarkError):\n    pass\n\n\nimport sys, re\nimport logging\n\nlogger: logging.Logger = logging.getLogger(\"lark\")\nlogger.addHandler(logging.StreamHandler())\n##\n\n##\n\nlogger.setLevel(logging.CRITICAL)\n\n\nNO_VALUE = object()\n\nT = TypeVar(\"T\")\n\n\ndef classify(seq: Iterable, key: Optional[Callable] = None, value: Optional[Callable] = None) -> Dict:\n    d: Dict[Any, Any] = {}\n    for item in seq:\n        k = key(item) if (key is not None) else item\n        v = value(item) if (value is not None) else item\n        try:\n            d[k].append(v)\n        except KeyError:\n            d[k] = [v]\n    return d\n\n\ndef _deserialize(data: Any, namespace: Dict[str, Any], memo: Dict) -> Any:\n    if isinstance(data, dict):\n        if '__type__' in data:  ##\n\n            class_ = namespace[data['__type__']]\n            return class_.deserialize(data, memo)\n        elif '@' in data:\n            return memo[data['@']]\n        return {key:_deserialize(value, namespace, memo) for key, value in data.items()}\n    elif isinstance(data, list):\n        return [_deserialize(value, namespace, memo) for value in data]\n    return data\n\n\n_T = TypeVar(\"_T\", bound=\"Serialize\")\n\nclass Serialize:\n    #--\n\n    def memo_serialize(self, types_to_memoize: List) -> Any:\n        memo = SerializeMemoizer(types_to_memoize)\n        return self.serialize(memo), memo.serialize()\n\n    def serialize(self, memo = None) -> Dict[str, Any]:\n        if memo and memo.in_types(self):\n            return {'@': memo.memoized.get(self)}\n\n        fields = getattr(self, '__serialize_fields__')\n        res = {f: _serialize(getattr(self, f), memo) for f in fields}\n        res['__type__'] = type(self).__name__\n        if hasattr(self, '_serialize'):\n            self._serialize(res, memo)  ##\n\n        return res\n\n    @classmethod\n    def deserialize(cls: Type[_T], data: Dict[str, Any], memo: Dict[int, Any]) -> _T:\n        namespace = getattr(cls, '__serialize_namespace__', [])\n        namespace = {c.__name__:c for c in namespace}\n\n        fields = getattr(cls, '__serialize_fields__')\n\n        if '@' in data:\n            return memo[data['@']]\n\n        inst = cls.__new__(cls)\n        for f in fields:\n            try:\n                setattr(inst, f, _deserialize(data[f], namespace, memo))\n            except KeyError as e:\n                raise KeyError(\"Cannot find key for class\", cls, e)\n\n        if hasattr(inst, '_deserialize'):\n            inst._deserialize()  ##\n\n\n        return inst\n\n\nclass SerializeMemoizer(Serialize):\n    #--\n\n    __serialize_fields__ = 'memoized',\n\n    def __init__(self, types_to_memoize: List) -> None:\n        self.types_to_memoize = tuple(types_to_memoize)\n        self.memoized = Enumerator()\n\n    def in_types(self, value: Serialize) -> bool:\n        return isinstance(value, self.types_to_memoize)\n\n    def serialize(self) -> Dict[int, Any]:  ##\n\n        return _serialize(self.memoized.reversed(), None)\n\n    @classmethod\n    def deserialize(cls, data: Dict[int, Any], namespace: Dict[str, Any], memo: Dict[Any, Any]) -> Dict[int, Any]:  ##\n\n        return _deserialize(data, namespace, memo)\n\n\ntry:\n    import regex\n    _has_regex = True\nexcept ImportError:\n    _has_regex = False\n\nif sys.version_info >= (3, 11):\n    import re._parser as sre_parse\n    import re._constants as sre_constants\nelse:\n    import sre_parse\n    import sre_constants\n\ncateg_pattern = re.compile(r'\\\\p{[A-Za-z_]+}')\n\ndef get_regexp_width(expr: str) -> Union[Tuple[int, int], List[int]]:\n    if _has_regex:\n        ##\n\n        ##\n\n        ##\n\n        regexp_final = re.sub(categ_pattern, 'A', expr)\n    else:\n        if re.search(categ_pattern, expr):\n            raise ImportError('`regex` module must be installed in order to use Unicode categories.', expr)\n        regexp_final = expr\n    try:\n        ##\n\n        return [int(x) for x in sre_parse.parse(regexp_final).getwidth()]   ##\n\n    except sre_constants.error:\n        if not _has_regex:\n            raise ValueError(expr)\n        else:\n            ##\n\n            ##\n\n            c = regex.compile(regexp_final)\n            if c.match('') is None:\n                ##\n\n                return 1, int(sre_constants.MAXREPEAT)\n            else:\n                return 0, int(sre_constants.MAXREPEAT)\n\n\nfrom collections import OrderedDict\n\nclass Meta:\n\n    empty: bool\n    line: int\n    column: int\n    start_pos: int\n    end_line: int\n    end_column: int\n    end_pos: int\n    orig_expansion: 'List[TerminalDef]'\n    match_tree: bool\n\n    def __init__(self):\n        self.empty = True\n\n\n_Leaf_T = TypeVar(\"_Leaf_T\")\nBranch = Union[_Leaf_T, 'Tree[_Leaf_T]']\n\n\nclass Tree(Generic[_Leaf_T]):\n    #--\n\n    data: str\n    children: 'List[Branch[_Leaf_T]]'\n\n    def __init__(self, data: str, children: 'List[Branch[_Leaf_T]]', meta: Optional[Meta]=None) -> None:\n        self.data = data\n        self.children = children\n        self._meta = meta\n\n    @property\n    def meta(self) -> Meta:\n        if self._meta is None:\n            self._meta = Meta()\n        return self._meta\n\n    def __repr__(self):\n        return 'Tree(%r, %r)' % (self.data, self.children)\n\n    def _pretty_label(self):\n        return self.data\n\n    def _pretty(self, level, indent_str):\n        yield f'{indent_str*level}{self._pretty_label()}'\n        if len(self.children) == 1 and not isinstance(self.children[0], Tree):\n            yield f'\\t{self.children[0]}\\n'\n        else:\n            yield '\\n'\n            for n in self.children:\n                if isinstance(n, Tree):\n                    yield from n._pretty(level+1, indent_str)\n                else:\n                    yield f'{indent_str*(level+1)}{n}\\n'\n\n    def pretty(self, indent_str: str='  ') -> str:\n        #--\n        return ''.join(self._pretty(0, indent_str))\n\n    def __rich__(self, parent:Optional['rich.tree.Tree']=None) -> 'rich.tree.Tree':\n        #--\n        return self._rich(parent)\n\n    def _rich(self, parent):\n        if parent:\n            tree = parent.add(f'[bold]{self.data}[/bold]')\n        else:\n            import rich.tree\n            tree = rich.tree.Tree(self.data)\n\n        for c in self.children:\n            if isinstance(c, Tree):\n                c._rich(tree)\n            else:\n                tree.add(f'[green]{c}[/green]')\n\n        return tree\n\n    def __eq__(self, other):\n        try:\n            return self.data == other.data and self.children == other.children\n        except AttributeError:\n            return False\n\n    def __ne__(self, other):\n        return not (self == other)\n\n    def __hash__(self) -> int:\n        return hash((self.data, tuple(self.children)))\n\n    def iter_subtrees(self) -> 'Iterator[Tree[_Leaf_T]]':\n        #--\n        queue = [self]\n        subtrees = OrderedDict()\n        for subtree in queue:\n            subtrees[id(subtree)] = subtree\n            ##\n\n            queue += [c for c in reversed(subtree.children)  ##\n\n                      if isinstance(c, Tree) and id(c) not in subtrees]\n\n        del queue\n        return reversed(list(subtrees.values()))\n\n    def iter_subtrees_topdown(self):\n        #--\n        stack = [self]\n        stack_append = stack.append\n        stack_pop = stack.pop\n        while stack:\n            node = stack_pop()\n            if not isinstance(node, Tree):\n                continue\n            yield node\n            for child in reversed(node.children):\n                stack_append(child)\n\n    def find_pred(self, pred: 'Callable[[Tree[_Leaf_T]], bool]') -> 'Iterator[Tree[_Leaf_T]]':\n        #--\n        return filter(pred, self.iter_subtrees())\n\n    def find_data(self, data: str) -> 'Iterator[Tree[_Leaf_T]]':\n        #--\n        return self.find_pred(lambda t: t.data == data)\n\n\nfrom functools import wraps, update_wrapper\nfrom inspect import getmembers, getmro\n\n_Return_T = TypeVar('_Return_T')\n_Return_V = TypeVar('_Return_V')\n_Leaf_T = TypeVar('_Leaf_T')\n_Leaf_U = TypeVar('_Leaf_U')\n_R = TypeVar('_R')\n_FUNC = Callable[..., _Return_T]\n_DECORATED = Union[_FUNC, type]\n\nclass _DiscardType:\n    #--\n\n    def __repr__(self):\n        return \"lark.visitors.Discard\"\n\nDiscard = _DiscardType()\n\n##\n\n\nclass _Decoratable:\n    #--\n\n    @classmethod\n    def _apply_v_args(cls, visit_wrapper):\n        mro = getmro(cls)\n        assert mro[0] is cls\n        libmembers = {name for _cls in mro[1:] for name, _ in getmembers(_cls)}\n        for name, value in getmembers(cls):\n\n            ##\n\n            if name.startswith('_') or (name in libmembers and name not in cls.__dict__):\n                continue\n            if not callable(value):\n                continue\n\n            ##\n\n            if isinstance(cls.__dict__[name], _VArgsWrapper):\n                continue\n\n            setattr(cls, name, _VArgsWrapper(cls.__dict__[name], visit_wrapper))\n        return cls\n\n    def __class_getitem__(cls, _):\n        return cls\n\n\nclass Transformer(_Decoratable, ABC, Generic[_Leaf_T, _Return_T]):\n    #--\n    __visit_tokens__ = True   ##\n\n\n    def __init__(self,  visit_tokens: bool=True) -> None:\n        self.__visit_tokens__ = visit_tokens\n\n    def _call_userfunc(self, tree, new_children=None):\n        ##\n\n        children = new_children if new_children is not None else tree.children\n        try:\n            f = getattr(self, tree.data)\n        except AttributeError:\n            return self.__default__(tree.data, children, tree.meta)\n        else:\n            try:\n                wrapper = getattr(f, 'visit_wrapper', None)\n                if wrapper is not None:\n                    return f.visit_wrapper(f, tree.data, children, tree.meta)\n                else:\n                    return f(children)\n            except GrammarError:\n                raise\n            except Exception as e:\n                raise VisitError(tree.data, tree, e)\n\n    def _call_userfunc_token(self, token):\n        try:\n            f = getattr(self, token.type)\n        except AttributeError:\n            return self.__default_token__(token)\n        else:\n            try:\n                return f(token)\n            except GrammarError:\n                raise\n            except Exception as e:\n                raise VisitError(token.type, token, e)\n\n    def _transform_children(self, children):\n        for c in children:\n            if isinstance(c, Tree):\n                res = self._transform_tree(c)\n            elif self.__visit_tokens__ and isinstance(c, Token):\n                res = self._call_userfunc_token(c)\n            else:\n                res = c\n\n            if res is not Discard:\n                yield res\n\n    def _transform_tree(self, tree):\n        children = list(self._transform_children(tree.children))\n        return self._call_userfunc(tree, children)\n\n    def transform(self, tree: Tree[_Leaf_T]) -> _Return_T:\n        #--\n        return self._transform_tree(tree)\n\n    def __mul__(\n            self: 'Transformer[_Leaf_T, Tree[_Leaf_U]]',\n            other: 'Union[Transformer[_Leaf_U, _Return_V], TransformerChain[_Leaf_U, _Return_V,]]'\n    ) -> 'TransformerChain[_Leaf_T, _Return_V]':\n        #--\n        return TransformerChain(self, other)\n\n    def __default__(self, data, children, meta):\n        #--\n        return Tree(data, children, meta)\n\n    def __default_token__(self, token):\n        #--\n        return token\n\n\ndef merge_transformers(base_transformer=None, **transformers_to_merge):\n    #--\n    if base_transformer is None:\n        base_transformer = Transformer()\n    for prefix, transformer in transformers_to_merge.items():\n        for method_name in dir(transformer):\n            method = getattr(transformer, method_name)\n            if not callable(method):\n                continue\n            if method_name.startswith(\"_\") or method_name == \"transform\":\n                continue\n            prefixed_method = prefix + \"__\" + method_name\n            if hasattr(base_transformer, prefixed_method):\n                raise AttributeError(\"Cannot merge: method '%s' appears more than once\" % prefixed_method)\n\n            setattr(base_transformer, prefixed_method, method)\n\n    return base_transformer\n\n\nclass InlineTransformer(Transformer):   ##\n\n    def _call_userfunc(self, tree, new_children=None):\n        ##\n\n        children = new_children if new_children is not None else tree.children\n        try:\n            f = getattr(self, tree.data)\n        except AttributeError:\n            return self.__default__(tree.data, children, tree.meta)\n        else:\n            return f(*children)\n\n\nclass TransformerChain(Generic[_Leaf_T, _Return_T]):\n\n    transformers: 'Tuple[Union[Transformer, TransformerChain], ...]'\n\n    def __init__(self, *transformers: 'Union[Transformer, TransformerChain]') -> None:\n        self.transformers = transformers\n\n    def transform(self, tree: Tree[_Leaf_T]) -> _Return_T:\n        for t in self.transformers:\n            tree = t.transform(tree)\n        return cast(_Return_T, tree)\n\n    def __mul__(\n            self: 'TransformerChain[_Leaf_T, Tree[_Leaf_U]]',\n            other: 'Union[Transformer[_Leaf_U, _Return_V], TransformerChain[_Leaf_U, _Return_V]]'\n    ) -> 'TransformerChain[_Leaf_T, _Return_V]':\n        return TransformerChain(*self.transformers + (other,))\n\n\nclass Transformer_InPlace(Transformer):\n    #--\n    def _transform_tree(self, tree):           ##\n\n        return self._call_userfunc(tree)\n\n    def transform(self, tree: Tree[_Leaf_T]) -> _Return_T:\n        for subtree in tree.iter_subtrees():\n            subtree.children = list(self._transform_children(subtree.children))\n\n        return self._transform_tree(tree)\n\n\nclass Transformer_NonRecursive(Transformer):\n    #--\n\n    def transform(self, tree: Tree[_Leaf_T]) -> _Return_T:\n        ##\n\n        rev_postfix = []\n        q: List[Branch[_Leaf_T]] = [tree]\n        while q:\n            t = q.pop()\n            rev_postfix.append(t)\n            if isinstance(t, Tree):\n                q += t.children\n\n        ##\n\n        stack: List = []\n        for x in reversed(rev_postfix):\n            if isinstance(x, Tree):\n                size = len(x.children)\n                if size:\n                    args = stack[-size:]\n                    del stack[-size:]\n                else:\n                    args = []\n\n                res = self._call_userfunc(x, args)\n                if res is not Discard:\n                    stack.append(res)\n\n            elif self.__visit_tokens__ and isinstance(x, Token):\n                res = self._call_userfunc_token(x)\n                if res is not Discard:\n                    stack.append(res)\n            else:\n                stack.append(x)\n\n        result, = stack  ##\n\n        ##\n\n        ##\n\n        ##\n\n        return cast(_Return_T, result)\n\n\nclass Transformer_InPlaceRecursive(Transformer):\n    #--\n    def _transform_tree(self, tree):\n        tree.children = list(self._transform_children(tree.children))\n        return self._call_userfunc(tree)\n\n\n##\n\n\nclass VisitorBase:\n    def _call_userfunc(self, tree):\n        return getattr(self, tree.data, self.__default__)(tree)\n\n    def __default__(self, tree):\n        #--\n        return tree\n\n    def __class_getitem__(cls, _):\n        return cls\n\n\nclass Visitor(VisitorBase, ABC, Generic[_Leaf_T]):\n    #--\n\n    def visit(self, tree: Tree[_Leaf_T]) -> Tree[_Leaf_T]:\n        #--\n        for subtree in tree.iter_subtrees():\n            self._call_userfunc(subtree)\n        return tree\n\n    def visit_topdown(self, tree: Tree[_Leaf_T]) -> Tree[_Leaf_T]:\n        #--\n        for subtree in tree.iter_subtrees_topdown():\n            self._call_userfunc(subtree)\n        return tree\n\n\nclass Visitor_Recursive(VisitorBase, Generic[_Leaf_T]):\n    #--\n\n    def visit(self, tree: Tree[_Leaf_T]) -> Tree[_Leaf_T]:\n        #--\n        for child in tree.children:\n            if isinstance(child, Tree):\n                self.visit(child)\n\n        self._call_userfunc(tree)\n        return tree\n\n    def visit_topdown(self,tree: Tree[_Leaf_T]) -> Tree[_Leaf_T]:\n        #--\n        self._call_userfunc(tree)\n\n        for child in tree.children:\n            if isinstance(child, Tree):\n                self.visit_topdown(child)\n\n        return tree\n\n\nclass Interpreter(_Decoratable, ABC, Generic[_Leaf_T, _Return_T]):\n    #--\n\n    def visit(self, tree: Tree[_Leaf_T]) -> _Return_T:\n        ##\n\n        ##\n\n        ##\n\n        return self._visit_tree(tree)\n\n    def _visit_tree(self, tree: Tree[_Leaf_T]):\n        f = getattr(self, tree.data)\n        wrapper = getattr(f, 'visit_wrapper', None)\n        if wrapper is not None:\n            return f.visit_wrapper(f, tree.data, tree.children, tree.meta)\n        else:\n            return f(tree)\n\n    def visit_children(self, tree: Tree[_Leaf_T]) -> List:\n        return [self._visit_tree(child) if isinstance(child, Tree) else child\n                for child in tree.children]\n\n    def __getattr__(self, name):\n        return self.__default__\n\n    def __default__(self, tree):\n        return self.visit_children(tree)\n\n\n_InterMethod = Callable[[Type[Interpreter], _Return_T], _R]\n\ndef visit_children_decor(func: _InterMethod) -> _InterMethod:\n    #--\n    @wraps(func)\n    def inner(cls, tree):\n        values = cls.visit_children(tree)\n        return func(cls, values)\n    return inner\n\n##\n\n\ndef _apply_v_args(obj, visit_wrapper):\n    try:\n        _apply = obj._apply_v_args\n    except AttributeError:\n        return _VArgsWrapper(obj, visit_wrapper)\n    else:\n        return _apply(visit_wrapper)\n\n\nclass _VArgsWrapper:\n    #--\n    base_func: Callable\n\n    def __init__(self, func: Callable, visit_wrapper: Callable[[Callable, str, list, Any], Any]):\n        if isinstance(func, _VArgsWrapper):\n            func = func.base_func\n        ##\n\n        self.base_func = func  ##\n\n        self.visit_wrapper = visit_wrapper\n        update_wrapper(self, func)\n\n    def __call__(self, *args, **kwargs):\n        return self.base_func(*args, **kwargs)\n\n    def __get__(self, instance, owner=None):\n        try:\n            ##\n\n            ##\n\n            g = type(self.base_func).__get__\n        except AttributeError:\n            return self\n        else:\n            return _VArgsWrapper(g(self.base_func, instance, owner), self.visit_wrapper)\n\n    def __set_name__(self, owner, name):\n        try:\n            f = type(self.base_func).__set_name__\n        except AttributeError:\n            return\n        else:\n            f(self.base_func, owner, name)\n\n\ndef _vargs_inline(f, _data, children, _meta):\n    return f(*children)\ndef _vargs_meta_inline(f, _data, children, meta):\n    return f(meta, *children)\ndef _vargs_meta(f, _data, children, meta):\n    return f(meta, children)\ndef _vargs_tree(f, data, children, meta):\n    return f(Tree(data, children, meta))\n\n\ndef v_args(inline: bool = False, meta: bool = False, tree: bool = False, wrapper: Optional[Callable] = None) -> Callable[[_DECORATED], _DECORATED]:\n    #--\n    if tree and (meta or inline):\n        raise ValueError(\"Visitor functions cannot combine 'tree' with 'meta' or 'inline'.\")\n\n    func = None\n    if meta:\n        if inline:\n            func = _vargs_meta_inline\n        else:\n            func = _vargs_meta\n    elif inline:\n        func = _vargs_inline\n    elif tree:\n        func = _vargs_tree\n\n    if wrapper is not None:\n        if func is not None:\n            raise ValueError(\"Cannot use 'wrapper' along with 'tree', 'meta' or 'inline'.\")\n        func = wrapper\n\n    def _visitor_args_dec(obj):\n        return _apply_v_args(obj, func)\n    return _visitor_args_dec\n\n\n\nTOKEN_DEFAULT_PRIORITY = 0\n\n\nclass Symbol(Serialize):\n    __slots__ = ('name',)\n\n    name: str\n    is_term: ClassVar[bool] = NotImplemented\n\n    def __init__(self, name: str) -> None:\n        self.name = name\n\n    def __eq__(self, other):\n        assert isinstance(other, Symbol), other\n        return self.is_term == other.is_term and self.name == other.name\n\n    def __ne__(self, other):\n        return not (self == other)\n\n    def __hash__(self):\n        return hash(self.name)\n\n    def __repr__(self):\n        return '%s(%r)' % (type(self).__name__, self.name)\n\n    fullrepr = property(__repr__)\n\n    def renamed(self, f):\n        return type(self)(f(self.name))\n\n\nclass Terminal(Symbol):\n    __serialize_fields__ = 'name', 'filter_out'\n\n    is_term: ClassVar[bool] = True\n\n    def __init__(self, name, filter_out=False):\n        self.name = name\n        self.filter_out = filter_out\n\n    @property\n    def fullrepr(self):\n        return '%s(%r, %r)' % (type(self).__name__, self.name, self.filter_out)\n\n    def renamed(self, f):\n        return type(self)(f(self.name), self.filter_out)\n\n\nclass NonTerminal(Symbol):\n    __serialize_fields__ = 'name',\n\n    is_term: ClassVar[bool] = False\n\n\nclass RuleOptions(Serialize):\n    __serialize_fields__ = 'keep_all_tokens', 'expand1', 'priority', 'template_source', 'empty_indices'\n\n    keep_all_tokens: bool\n    expand1: bool\n    priority: Optional[int]\n    template_source: Optional[str]\n    empty_indices: Tuple[bool, ...]\n\n    def __init__(self, keep_all_tokens: bool=False, expand1: bool=False, priority: Optional[int]=None, template_source: Optional[str]=None, empty_indices: Tuple[bool, ...]=()) -> None:\n        self.keep_all_tokens = keep_all_tokens\n        self.expand1 = expand1\n        self.priority = priority\n        self.template_source = template_source\n        self.empty_indices = empty_indices\n\n    def __repr__(self):\n        return 'RuleOptions(%r, %r, %r, %r)' % (\n            self.keep_all_tokens,\n            self.expand1,\n            self.priority,\n            self.template_source\n        )\n\n\nclass Rule(Serialize):\n    #--\n    __slots__ = ('origin', 'expansion', 'alias', 'options', 'order', '_hash')\n\n    __serialize_fields__ = 'origin', 'expansion', 'order', 'alias', 'options'\n    __serialize_namespace__ = Terminal, NonTerminal, RuleOptions\n\n    def __init__(self, origin, expansion, order=0, alias=None, options=None):\n        self.origin = origin\n        self.expansion = expansion\n        self.alias = alias\n        self.order = order\n        self.options = options or RuleOptions()\n        self._hash = hash((self.origin, tuple(self.expansion)))\n\n    def _deserialize(self):\n        self._hash = hash((self.origin, tuple(self.expansion)))\n\n    def __str__(self):\n        return '<%s : %s>' % (self.origin.name, ' '.join(x.name for x in self.expansion))\n\n    def __repr__(self):\n        return 'Rule(%r, %r, %r, %r)' % (self.origin, self.expansion, self.alias, self.options)\n\n    def __hash__(self):\n        return self._hash\n\n    def __eq__(self, other):\n        if not isinstance(other, Rule):\n            return False\n        return self.origin == other.origin and self.expansion == other.expansion\n\n\n\nfrom copy import copy\n\ntry:  ##\n\n    has_interegular = bool(interegular)\nexcept NameError:\n    has_interegular = False\n\nclass Pattern(Serialize, ABC):\n\n    value: str\n    flags: Collection[str]\n    raw: Optional[str]\n    type: ClassVar[str]\n\n    def __init__(self, value: str, flags: Collection[str] = (), raw: Optional[str] = None) -> None:\n        self.value = value\n        self.flags = frozenset(flags)\n        self.raw = raw\n\n    def __repr__(self):\n        return repr(self.to_regexp())\n\n    ##\n\n    def __hash__(self):\n        return hash((type(self), self.value, self.flags))\n\n    def __eq__(self, other):\n        return type(self) == type(other) and self.value == other.value and self.flags == other.flags\n\n    @abstractmethod\n    def to_regexp(self) -> str:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def min_width(self) -> int:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def max_width(self) -> int:\n        raise NotImplementedError()\n\n    def _get_flags(self, value):\n        for f in self.flags:\n            value = ('(?%s:%s)' % (f, value))\n        return value\n\n\nclass PatternStr(Pattern):\n    __serialize_fields__ = 'value', 'flags', 'raw'\n\n    type: ClassVar[str] = \"str\"\n\n    def to_regexp(self) -> str:\n        return self._get_flags(re.escape(self.value))\n\n    @property\n    def min_width(self) -> int:\n        return len(self.value)\n\n    @property\n    def max_width(self) -> int:\n        return len(self.value)\n\n\nclass PatternRE(Pattern):\n    __serialize_fields__ = 'value', 'flags', 'raw', '_width'\n\n    type: ClassVar[str] = \"re\"\n\n    def to_regexp(self) -> str:\n        return self._get_flags(self.value)\n\n    _width = None\n    def _get_width(self):\n        if self._width is None:\n            self._width = get_regexp_width(self.to_regexp())\n        return self._width\n\n    @property\n    def min_width(self) -> int:\n        return self._get_width()[0]\n\n    @property\n    def max_width(self) -> int:\n        return self._get_width()[1]\n\n\nclass TerminalDef(Serialize):\n    __serialize_fields__ = 'name', 'pattern', 'priority'\n    __serialize_namespace__ = PatternStr, PatternRE\n\n    name: str\n    pattern: Pattern\n    priority: int\n\n    def __init__(self, name: str, pattern: Pattern, priority: int = TOKEN_DEFAULT_PRIORITY) -> None:\n        assert isinstance(pattern, Pattern), pattern\n        self.name = name\n        self.pattern = pattern\n        self.priority = priority\n\n    def __repr__(self):\n        return '%s(%r, %r)' % (type(self).__name__, self.name, self.pattern)\n\n    def user_repr(self) -> str:\n        if self.name.startswith('__'):  ##\n\n            return self.pattern.raw or self.name\n        else:\n            return self.name\n\n_T = TypeVar('_T', bound=\"Token\")\n\nclass Token(str):\n    #--\n    __slots__ = ('type', 'start_pos', 'value', 'line', 'column', 'end_line', 'end_column', 'end_pos')\n\n    __match_args__ = ('type', 'value')\n\n    type: str\n    start_pos: Optional[int]\n    value: Any\n    line: Optional[int]\n    column: Optional[int]\n    end_line: Optional[int]\n    end_column: Optional[int]\n    end_pos: Optional[int]\n\n\n    @overload\n    def __new__(\n            cls,\n            type: str,\n            value: Any,\n            start_pos: Optional[int] = None,\n            line: Optional[int] = None,\n            column: Optional[int] = None,\n            end_line: Optional[int] = None,\n            end_column: Optional[int] = None,\n            end_pos: Optional[int] = None\n    ) -> 'Token':\n        ...\n\n    @overload\n    def __new__(\n            cls,\n            type_: str,\n            value: Any,\n            start_pos: Optional[int] = None,\n            line: Optional[int] = None,\n            column: Optional[int] = None,\n            end_line: Optional[int] = None,\n            end_column: Optional[int] = None,\n            end_pos: Optional[int] = None\n    ) -> 'Token':        ...\n\n    def __new__(cls, *args, **kwargs):\n        if \"type_\" in kwargs:\n            warnings.warn(\"`type_` is deprecated use `type` instead\", DeprecationWarning)\n\n            if \"type\" in kwargs:\n                raise TypeError(\"Error: using both 'type' and the deprecated 'type_' as arguments.\")\n            kwargs[\"type\"] = kwargs.pop(\"type_\")\n\n        return cls._future_new(*args, **kwargs)\n\n\n    @classmethod\n    def _future_new(cls, type, value, start_pos=None, line=None, column=None, end_line=None, end_column=None, end_pos=None):\n        inst = super(Token, cls).__new__(cls, value)\n\n        inst.type = type\n        inst.start_pos = start_pos\n        inst.value = value\n        inst.line = line\n        inst.column = column\n        inst.end_line = end_line\n        inst.end_column = end_column\n        inst.end_pos = end_pos\n        return inst\n\n    @overload\n    def update(self, type: Optional[str] = None, value: Optional[Any] = None) -> 'Token':\n        ...\n\n    @overload\n    def update(self, type_: Optional[str] = None, value: Optional[Any] = None) -> 'Token':\n        ...\n\n    def update(self, *args, **kwargs):\n        if \"type_\" in kwargs:\n            warnings.warn(\"`type_` is deprecated use `type` instead\", DeprecationWarning)\n\n            if \"type\" in kwargs:\n                raise TypeError(\"Error: using both 'type' and the deprecated 'type_' as arguments.\")\n            kwargs[\"type\"] = kwargs.pop(\"type_\")\n\n        return self._future_update(*args, **kwargs)\n\n    def _future_update(self, type: Optional[str] = None, value: Optional[Any] = None) -> 'Token':\n        return Token.new_borrow_pos(\n            type if type is not None else self.type,\n            value if value is not None else self.value,\n            self\n        )\n\n    @classmethod\n    def new_borrow_pos(cls: Type[_T], type_: str, value: Any, borrow_t: 'Token') -> _T:\n        return cls(type_, value, borrow_t.start_pos, borrow_t.line, borrow_t.column, borrow_t.end_line, borrow_t.end_column, borrow_t.end_pos)\n\n    def __reduce__(self):\n        return (self.__class__, (self.type, self.value, self.start_pos, self.line, self.column))\n\n    def __repr__(self):\n        return 'Token(%r, %r)' % (self.type, self.value)\n\n    def __deepcopy__(self, memo):\n        return Token(self.type, self.value, self.start_pos, self.line, self.column)\n\n    def __eq__(self, other):\n        if isinstance(other, Token) and self.type != other.type:\n            return False\n\n        return str.__eq__(self, other)\n\n    __hash__ = str.__hash__\n\n\nclass LineCounter:\n    __slots__ = 'char_pos', 'line', 'column', 'line_start_pos', 'newline_char'\n\n    def __init__(self, newline_char):\n        self.newline_char = newline_char\n        self.char_pos = 0\n        self.line = 1\n        self.column = 1\n        self.line_start_pos = 0\n\n    def __eq__(self, other):\n        if not isinstance(other, LineCounter):\n            return NotImplemented\n\n        return self.char_pos == other.char_pos and self.newline_char == other.newline_char\n\n    def feed(self, token: Token, test_newline=True):\n        #--\n        if test_newline:\n            newlines = token.count(self.newline_char)\n            if newlines:\n                self.line += newlines\n                self.line_start_pos = self.char_pos + token.rindex(self.newline_char) + 1\n\n        self.char_pos += len(token)\n        self.column = self.char_pos - self.line_start_pos + 1\n\n\nclass UnlessCallback:\n    def __init__(self, scanner):\n        self.scanner = scanner\n\n    def __call__(self, t):\n        res = self.scanner.match(t.value, 0)\n        if res:\n            _value, t.type = res\n        return t\n\n\nclass CallChain:\n    def __init__(self, callback1, callback2, cond):\n        self.callback1 = callback1\n        self.callback2 = callback2\n        self.cond = cond\n\n    def __call__(self, t):\n        t2 = self.callback1(t)\n        return self.callback2(t) if self.cond(t2) else t2\n\n\ndef _get_match(re_, regexp, s, flags):\n    m = re_.match(regexp, s, flags)\n    if m:\n        return m.group(0)\n\ndef _create_unless(terminals, g_regex_flags, re_, use_bytes):\n    tokens_by_type = classify(terminals, lambda t: type(t.pattern))\n    assert len(tokens_by_type) <= 2, tokens_by_type.keys()\n    embedded_strs = set()\n    callback = {}\n    for retok in tokens_by_type.get(PatternRE, []):\n        unless = []\n        for strtok in tokens_by_type.get(PatternStr, []):\n            if strtok.priority != retok.priority:\n                continue\n            s = strtok.pattern.value\n            if s == _get_match(re_, retok.pattern.to_regexp(), s, g_regex_flags):\n                unless.append(strtok)\n                if strtok.pattern.flags <= retok.pattern.flags:\n                    embedded_strs.add(strtok)\n        if unless:\n            callback[retok.name] = UnlessCallback(Scanner(unless, g_regex_flags, re_, match_whole=True, use_bytes=use_bytes))\n\n    new_terminals = [t for t in terminals if t not in embedded_strs]\n    return new_terminals, callback\n\n\nclass Scanner:\n    def __init__(self, terminals, g_regex_flags, re_, use_bytes, match_whole=False):\n        self.terminals = terminals\n        self.g_regex_flags = g_regex_flags\n        self.re_ = re_\n        self.use_bytes = use_bytes\n        self.match_whole = match_whole\n\n        self.allowed_types = {t.name for t in self.terminals}\n\n        self._mres = self._build_mres(terminals, len(terminals))\n\n    def _build_mres(self, terminals, max_size):\n        ##\n\n        ##\n\n        ##\n\n        postfix = '$' if self.match_whole else ''\n        mres = []\n        while terminals:\n            pattern = u'|'.join(u'(?P<%s>%s)' % (t.name, t.pattern.to_regexp() + postfix) for t in terminals[:max_size])\n            if self.use_bytes:\n                pattern = pattern.encode('latin-1')\n            try:\n                mre = self.re_.compile(pattern, self.g_regex_flags)\n            except AssertionError:  ##\n\n                return self._build_mres(terminals, max_size // 2)\n\n            mres.append(mre)\n            terminals = terminals[max_size:]\n        return mres\n\n    def match(self, text, pos):\n        for mre in self._mres:\n            m = mre.match(text, pos)\n            if m:\n                return m.group(0), m.lastgroup\n\n\ndef _regexp_has_newline(r: str):\n    #--\n    return '\\n' in r or '\\\\n' in r or '\\\\s' in r or '[^' in r or ('(?s' in r and '.' in r)\n\n\nclass LexerState:\n    #--\n\n    __slots__ = 'text', 'line_ctr', 'last_token'\n\n    text: str\n    line_ctr: LineCounter\n    last_token: Optional[Token]\n\n    def __init__(self, text: str, line_ctr: Optional[LineCounter]=None, last_token: Optional[Token]=None):\n        self.text = text\n        self.line_ctr = line_ctr or LineCounter(b'\\n' if isinstance(text, bytes) else '\\n')\n        self.last_token = last_token\n\n    def __eq__(self, other):\n        if not isinstance(other, LexerState):\n            return NotImplemented\n\n        return self.text is other.text and self.line_ctr == other.line_ctr and self.last_token == other.last_token\n\n    def __copy__(self):\n        return type(self)(self.text, copy(self.line_ctr), self.last_token)\n\n\nclass LexerThread:\n    #--\n\n    def __init__(self, lexer: 'Lexer', lexer_state: LexerState):\n        self.lexer = lexer\n        self.state = lexer_state\n\n    @classmethod\n    def from_text(cls, lexer: 'Lexer', text: str):\n        return cls(lexer, LexerState(text))\n\n    def lex(self, parser_state):\n        return self.lexer.lex(self.state, parser_state)\n\n    def __copy__(self):\n        return type(self)(self.lexer, copy(self.state))\n\n    _Token = Token\n\n\n_Callback = Callable[[Token], Token]\n\nclass Lexer(ABC):\n    #--\n    @abstractmethod\n    def lex(self, lexer_state: LexerState, parser_state: Any) -> Iterator[Token]:\n        return NotImplemented\n\n    def make_lexer_state(self, text):\n        #--\n        return LexerState(text)\n\n\ndef _check_regex_collisions(terminal_to_regexp: Dict[TerminalDef, str], comparator, strict_mode, max_collisions_to_show=8):\n    if not comparator:\n        comparator = interegular.Comparator.from_regexes(terminal_to_regexp)\n\n    ##\n\n    ##\n\n    max_time = 2 if strict_mode else 0.2\n\n    ##\n\n    if comparator.count_marked_pairs() >= max_collisions_to_show:\n        return\n    for group in classify(terminal_to_regexp, lambda t: t.priority).values():\n        for a, b in comparator.check(group, skip_marked=True):\n            assert a.priority == b.priority\n            ##\n\n            comparator.mark(a, b)\n\n            ##\n\n            message = f\"Collision between Terminals {a.name} and {b.name}. \"\n            try:\n                example = comparator.get_example_overlap(a, b, max_time).format_multiline()\n            except ValueError:\n                ##\n\n                example = \"No example could be found fast enough. However, the collision does still exists\"\n            if strict_mode:\n                raise LexError(f\"{message}\\n{example}\")\n            logger.warning(\"%s The lexer will choose between them arbitrarily.\\n%s\", message, example)\n            if comparator.count_marked_pairs() >= max_collisions_to_show:\n                logger.warning(\"Found 8 regex collisions, will not check for more.\")\n                return\n\n\nclass BasicLexer(Lexer):\n    terminals: Collection[TerminalDef]\n    ignore_types: FrozenSet[str]\n    newline_types: FrozenSet[str]\n    user_callbacks: Dict[str, _Callback]\n    callback: Dict[str, _Callback]\n    re: ModuleType\n\n    def __init__(self, conf: 'LexerConf', comparator=None) -> None:\n        terminals = list(conf.terminals)\n        assert all(isinstance(t, TerminalDef) for t in terminals), terminals\n\n        self.re = conf.re_module\n\n        if not conf.skip_validation:\n            ##\n\n            terminal_to_regexp = {}\n            for t in terminals:\n                regexp = t.pattern.to_regexp()\n                try:\n                    self.re.compile(regexp, conf.g_regex_flags)\n                except self.re.error:\n                    raise LexError(\"Cannot compile token %s: %s\" % (t.name, t.pattern))\n\n                if t.pattern.min_width == 0:\n                    raise LexError(\"Lexer does not allow zero-width terminals. (%s: %s)\" % (t.name, t.pattern))\n                if t.pattern.type == \"re\":\n                    terminal_to_regexp[t] = regexp\n\n            if not (set(conf.ignore) <= {t.name for t in terminals}):\n                raise LexError(\"Ignore terminals are not defined: %s\" % (set(conf.ignore) - {t.name for t in terminals}))\n\n            if has_interegular:\n                _check_regex_collisions(terminal_to_regexp, comparator, conf.strict)\n            elif conf.strict:\n                raise LexError(\"interegular must be installed for strict mode. Use `pip install 'lark[interegular]'`.\")\n\n        ##\n\n        self.newline_types = frozenset(t.name for t in terminals if _regexp_has_newline(t.pattern.to_regexp()))\n        self.ignore_types = frozenset(conf.ignore)\n\n        terminals.sort(key=lambda x: (-x.priority, -x.pattern.max_width, -len(x.pattern.value), x.name))\n        self.terminals = terminals\n        self.user_callbacks = conf.callbacks\n        self.g_regex_flags = conf.g_regex_flags\n        self.use_bytes = conf.use_bytes\n        self.terminals_by_name = conf.terminals_by_name\n\n        self._scanner = None\n\n    def _build_scanner(self):\n        terminals, self.callback = _create_unless(self.terminals, self.g_regex_flags, self.re, self.use_bytes)\n        assert all(self.callback.values())\n\n        for type_, f in self.user_callbacks.items():\n            if type_ in self.callback:\n                ##\n\n                self.callback[type_] = CallChain(self.callback[type_], f, lambda t: t.type == type_)\n            else:\n                self.callback[type_] = f\n\n        self._scanner = Scanner(terminals, self.g_regex_flags, self.re, self.use_bytes)\n\n    @property\n    def scanner(self):\n        if self._scanner is None:\n            self._build_scanner()\n        return self._scanner\n\n    def match(self, text, pos):\n        return self.scanner.match(text, pos)\n\n    def lex(self, state: LexerState, parser_state: Any) -> Iterator[Token]:\n        with suppress(EOFError):\n            while True:\n                yield self.next_token(state, parser_state)\n\n    def next_token(self, lex_state: LexerState, parser_state: Any = None) -> Token:\n        line_ctr = lex_state.line_ctr\n        while line_ctr.char_pos < len(lex_state.text):\n            res = self.match(lex_state.text, line_ctr.char_pos)\n            if not res:\n                allowed = self.scanner.allowed_types - self.ignore_types\n                if not allowed:\n                    allowed = {\"<END-OF-FILE>\"}\n                raise UnexpectedCharacters(lex_state.text, line_ctr.char_pos, line_ctr.line, line_ctr.column,\n                                           allowed=allowed, token_history=lex_state.last_token and [lex_state.last_token],\n                                           state=parser_state, terminals_by_name=self.terminals_by_name)\n\n            value, type_ = res\n\n            if type_ not in self.ignore_types:\n                t = Token(type_, value, line_ctr.char_pos, line_ctr.line, line_ctr.column)\n                line_ctr.feed(value, type_ in self.newline_types)\n                t.end_line = line_ctr.line\n                t.end_column = line_ctr.column\n                t.end_pos = line_ctr.char_pos\n                if t.type in self.callback:\n                    t = self.callback[t.type](t)\n                    if not isinstance(t, Token):\n                        raise LexError(\"Callbacks must return a token (returned %r)\" % t)\n                lex_state.last_token = t\n                return t\n            else:\n                if type_ in self.callback:\n                    t2 = Token(type_, value, line_ctr.char_pos, line_ctr.line, line_ctr.column)\n                    self.callback[type_](t2)\n                line_ctr.feed(value, type_ in self.newline_types)\n\n        ##\n\n        raise EOFError(self)\n\n\nclass ContextualLexer(Lexer):\n\n    lexers: Dict[str, BasicLexer]\n    root_lexer: BasicLexer\n\n    def __init__(self, conf: 'LexerConf', states: Dict[str, Collection[str]], always_accept: Collection[str]=()) -> None:\n        terminals = list(conf.terminals)\n        terminals_by_name = conf.terminals_by_name\n\n        trad_conf = copy(conf)\n        trad_conf.terminals = terminals\n\n        if has_interegular and not conf.skip_validation:\n            comparator = interegular.Comparator.from_regexes({t: t.pattern.to_regexp() for t in terminals})\n        else:\n            comparator = None\n        lexer_by_tokens: Dict[FrozenSet[str], BasicLexer] = {}\n        self.lexers = {}\n        for state, accepts in states.items():\n            key = frozenset(accepts)\n            try:\n                lexer = lexer_by_tokens[key]\n            except KeyError:\n                accepts = set(accepts) | set(conf.ignore) | set(always_accept)\n                lexer_conf = copy(trad_conf)\n                lexer_conf.terminals = [terminals_by_name[n] for n in accepts if n in terminals_by_name]\n                lexer = BasicLexer(lexer_conf, comparator)\n                lexer_by_tokens[key] = lexer\n\n            self.lexers[state] = lexer\n\n        assert trad_conf.terminals is terminals\n        trad_conf.skip_validation = True  ##\n\n        self.root_lexer = BasicLexer(trad_conf, comparator)\n\n    def lex(self, lexer_state: LexerState, parser_state: Any) -> Iterator[Token]:\n        try:\n            while True:\n                lexer = self.lexers[parser_state.position]\n                yield lexer.next_token(lexer_state, parser_state)\n        except EOFError:\n            pass\n        except UnexpectedCharacters as e:\n            ##\n\n            ##\n\n            try:\n                last_token = lexer_state.last_token  ##\n\n                token = self.root_lexer.next_token(lexer_state, parser_state)\n                raise UnexpectedToken(token, e.allowed, state=parser_state, token_history=[last_token], terminals_by_name=self.root_lexer.terminals_by_name)\n            except UnexpectedCharacters:\n                raise e  ##\n\n\n\n\n_ParserArgType: 'TypeAlias' = 'Literal[\"earley\", \"lalr\", \"cyk\", \"auto\"]'\n_LexerArgType: 'TypeAlias' = 'Union[Literal[\"auto\", \"basic\", \"contextual\", \"dynamic\", \"dynamic_complete\"], Type[Lexer]]'\n_Callback = Callable[[Token], Token]\n\nclass LexerConf(Serialize):\n    __serialize_fields__ = 'terminals', 'ignore', 'g_regex_flags', 'use_bytes', 'lexer_type'\n    __serialize_namespace__ = TerminalDef,\n\n    terminals: Collection[TerminalDef]\n    re_module: ModuleType\n    ignore: Collection[str]\n    postlex: 'Optional[PostLex]'\n    callbacks: Dict[str, _Callback]\n    g_regex_flags: int\n    skip_validation: bool\n    use_bytes: bool\n    lexer_type: Optional[_LexerArgType]\n    strict: bool\n\n    def __init__(self, terminals: Collection[TerminalDef], re_module: ModuleType, ignore: Collection[str]=(), postlex: 'Optional[PostLex]'=None,\n                 callbacks: Optional[Dict[str, _Callback]]=None, g_regex_flags: int=0, skip_validation: bool=False, use_bytes: bool=False, strict: bool=False):\n        self.terminals = terminals\n        self.terminals_by_name = {t.name: t for t in self.terminals}\n        assert len(self.terminals) == len(self.terminals_by_name)\n        self.ignore = ignore\n        self.postlex = postlex\n        self.callbacks = callbacks or {}\n        self.g_regex_flags = g_regex_flags\n        self.re_module = re_module\n        self.skip_validation = skip_validation\n        self.use_bytes = use_bytes\n        self.strict = strict\n        self.lexer_type = None\n\n    def _deserialize(self):\n        self.terminals_by_name = {t.name: t for t in self.terminals}\n\n    def __deepcopy__(self, memo=None):\n        return type(self)(\n            deepcopy(self.terminals, memo),\n            self.re_module,\n            deepcopy(self.ignore, memo),\n            deepcopy(self.postlex, memo),\n            deepcopy(self.callbacks, memo),\n            deepcopy(self.g_regex_flags, memo),\n            deepcopy(self.skip_validation, memo),\n            deepcopy(self.use_bytes, memo),\n        )\n\n\nclass ParserConf(Serialize):\n    __serialize_fields__ = 'rules', 'start', 'parser_type'\n\n    def __init__(self, rules, callbacks, start):\n        assert isinstance(start, list)\n        self.rules = rules\n        self.callbacks = callbacks\n        self.start = start\n\n        self.parser_type = None\n\n\nfrom functools import partial, wraps\nfrom itertools import product\n\n\nclass ExpandSingleChild:\n    def __init__(self, node_builder):\n        self.node_builder = node_builder\n\n    def __call__(self, children):\n        if len(children) == 1:\n            return children[0]\n        else:\n            return self.node_builder(children)\n\n\n\nclass PropagatePositions:\n    def __init__(self, node_builder, node_filter=None):\n        self.node_builder = node_builder\n        self.node_filter = node_filter\n\n    def __call__(self, children):\n        res = self.node_builder(children)\n\n        if isinstance(res, Tree):\n            ##\n\n            ##\n\n            ##\n\n            ##\n\n\n            res_meta = res.meta\n\n            first_meta = self._pp_get_meta(children)\n            if first_meta is not None:\n                if not hasattr(res_meta, 'line'):\n                    ##\n\n                    res_meta.line = getattr(first_meta, 'container_line', first_meta.line)\n                    res_meta.column = getattr(first_meta, 'container_column', first_meta.column)\n                    res_meta.start_pos = getattr(first_meta, 'container_start_pos', first_meta.start_pos)\n                    res_meta.empty = False\n\n                res_meta.container_line = getattr(first_meta, 'container_line', first_meta.line)\n                res_meta.container_column = getattr(first_meta, 'container_column', first_meta.column)\n                res_meta.container_start_pos = getattr(first_meta, 'container_start_pos', first_meta.start_pos)\n\n            last_meta = self._pp_get_meta(reversed(children))\n            if last_meta is not None:\n                if not hasattr(res_meta, 'end_line'):\n                    res_meta.end_line = getattr(last_meta, 'container_end_line', last_meta.end_line)\n                    res_meta.end_column = getattr(last_meta, 'container_end_column', last_meta.end_column)\n                    res_meta.end_pos = getattr(last_meta, 'container_end_pos', last_meta.end_pos)\n                    res_meta.empty = False\n\n                res_meta.container_end_line = getattr(last_meta, 'container_end_line', last_meta.end_line)\n                res_meta.container_end_column = getattr(last_meta, 'container_end_column', last_meta.end_column)\n                res_meta.container_end_pos = getattr(last_meta, 'container_end_pos', last_meta.end_pos)\n\n        return res\n\n    def _pp_get_meta(self, children):\n        for c in children:\n            if self.node_filter is not None and not self.node_filter(c):\n                continue\n            if isinstance(c, Tree):\n                if not c.meta.empty:\n                    return c.meta\n            elif isinstance(c, Token):\n                return c\n            elif hasattr(c, '__lark_meta__'):\n                return c.__lark_meta__()\n\ndef make_propagate_positions(option):\n    if callable(option):\n        return partial(PropagatePositions, node_filter=option)\n    elif option is True:\n        return PropagatePositions\n    elif option is False:\n        return None\n\n    raise ConfigurationError('Invalid option for propagate_positions: %r' % option)\n\n\nclass ChildFilter:\n    def __init__(self, to_include, append_none, node_builder):\n        self.node_builder = node_builder\n        self.to_include = to_include\n        self.append_none = append_none\n\n    def __call__(self, children):\n        filtered = []\n\n        for i, to_expand, add_none in self.to_include:\n            if add_none:\n                filtered += [None] * add_none\n            if to_expand:\n                filtered += children[i].children\n            else:\n                filtered.append(children[i])\n\n        if self.append_none:\n            filtered += [None] * self.append_none\n\n        return self.node_builder(filtered)\n\n\nclass ChildFilterLALR(ChildFilter):\n    #--\n\n    def __call__(self, children):\n        filtered = []\n        for i, to_expand, add_none in self.to_include:\n            if add_none:\n                filtered += [None] * add_none\n            if to_expand:\n                if filtered:\n                    filtered += children[i].children\n                else:   ##\n\n                    filtered = children[i].children\n            else:\n                filtered.append(children[i])\n\n        if self.append_none:\n            filtered += [None] * self.append_none\n\n        return self.node_builder(filtered)\n\n\nclass ChildFilterLALR_NoPlaceholders(ChildFilter):\n    #--\n    def __init__(self, to_include, node_builder):\n        self.node_builder = node_builder\n        self.to_include = to_include\n\n    def __call__(self, children):\n        filtered = []\n        for i, to_expand in self.to_include:\n            if to_expand:\n                if filtered:\n                    filtered += children[i].children\n                else:   ##\n\n                    filtered = children[i].children\n            else:\n                filtered.append(children[i])\n        return self.node_builder(filtered)\n\n\ndef _should_expand(sym):\n    return not sym.is_term and sym.name.startswith('_')\n\n\ndef maybe_create_child_filter(expansion, keep_all_tokens, ambiguous, _empty_indices: List[bool]):\n    ##\n\n    if _empty_indices:\n        assert _empty_indices.count(False) == len(expansion)\n        s = ''.join(str(int(b)) for b in _empty_indices)\n        empty_indices = [len(ones) for ones in s.split('0')]\n        assert len(empty_indices) == len(expansion)+1, (empty_indices, len(expansion))\n    else:\n        empty_indices = [0] * (len(expansion)+1)\n\n    to_include = []\n    nones_to_add = 0\n    for i, sym in enumerate(expansion):\n        nones_to_add += empty_indices[i]\n        if keep_all_tokens or not (sym.is_term and sym.filter_out):\n            to_include.append((i, _should_expand(sym), nones_to_add))\n            nones_to_add = 0\n\n    nones_to_add += empty_indices[len(expansion)]\n\n    if _empty_indices or len(to_include) < len(expansion) or any(to_expand for i, to_expand,_ in to_include):\n        if _empty_indices or ambiguous:\n            return partial(ChildFilter if ambiguous else ChildFilterLALR, to_include, nones_to_add)\n        else:\n            ##\n\n            return partial(ChildFilterLALR_NoPlaceholders, [(i, x) for i,x,_ in to_include])\n\n\nclass AmbiguousExpander:\n    #--\n    def __init__(self, to_expand, tree_class, node_builder):\n        self.node_builder = node_builder\n        self.tree_class = tree_class\n        self.to_expand = to_expand\n\n    def __call__(self, children):\n        def _is_ambig_tree(t):\n            return hasattr(t, 'data') and t.data == '_ambig'\n\n        ##\n\n        ##\n\n        ##\n\n        ##\n\n        ambiguous = []\n        for i, child in enumerate(children):\n            if _is_ambig_tree(child):\n                if i in self.to_expand:\n                    ambiguous.append(i)\n\n                child.expand_kids_by_data('_ambig')\n\n        if not ambiguous:\n            return self.node_builder(children)\n\n        expand = [child.children if i in ambiguous else (child,) for i, child in enumerate(children)]\n        return self.tree_class('_ambig', [self.node_builder(list(f)) for f in product(*expand)])\n\n\ndef maybe_create_ambiguous_expander(tree_class, expansion, keep_all_tokens):\n    to_expand = [i for i, sym in enumerate(expansion)\n                 if keep_all_tokens or ((not (sym.is_term and sym.filter_out)) and _should_expand(sym))]\n    if to_expand:\n        return partial(AmbiguousExpander, to_expand, tree_class)\n\n\nclass AmbiguousIntermediateExpander:\n    #--\n\n    def __init__(self, tree_class, node_builder):\n        self.node_builder = node_builder\n        self.tree_class = tree_class\n\n    def __call__(self, children):\n        def _is_iambig_tree(child):\n            return hasattr(child, 'data') and child.data == '_iambig'\n\n        def _collapse_iambig(children):\n            #--\n\n            ##\n\n            ##\n\n            if children and _is_iambig_tree(children[0]):\n                iambig_node = children[0]\n                result = []\n                for grandchild in iambig_node.children:\n                    collapsed = _collapse_iambig(grandchild.children)\n                    if collapsed:\n                        for child in collapsed:\n                            child.children += children[1:]\n                        result += collapsed\n                    else:\n                        new_tree = self.tree_class('_inter', grandchild.children + children[1:])\n                        result.append(new_tree)\n                return result\n\n        collapsed = _collapse_iambig(children)\n        if collapsed:\n            processed_nodes = [self.node_builder(c.children) for c in collapsed]\n            return self.tree_class('_ambig', processed_nodes)\n\n        return self.node_builder(children)\n\n\n\ndef inplace_transformer(func):\n    @wraps(func)\n    def f(children):\n        ##\n\n        tree = Tree(func.__name__, children)\n        return func(tree)\n    return f\n\n\ndef apply_visit_wrapper(func, name, wrapper):\n    if wrapper is _vargs_meta or wrapper is _vargs_meta_inline:\n        raise NotImplementedError(\"Meta args not supported for internal transformer\")\n\n    @wraps(func)\n    def f(children):\n        return wrapper(func, name, children, None)\n    return f\n\n\nclass ParseTreeBuilder:\n    def __init__(self, rules, tree_class, propagate_positions=False, ambiguous=False, maybe_placeholders=False):\n        self.tree_class = tree_class\n        self.propagate_positions = propagate_positions\n        self.ambiguous = ambiguous\n        self.maybe_placeholders = maybe_placeholders\n\n        self.rule_builders = list(self._init_builders(rules))\n\n    def _init_builders(self, rules):\n        propagate_positions = make_propagate_positions(self.propagate_positions)\n\n        for rule in rules:\n            options = rule.options\n            keep_all_tokens = options.keep_all_tokens\n            expand_single_child = options.expand1\n\n            wrapper_chain = list(filter(None, [\n                (expand_single_child and not rule.alias) and ExpandSingleChild,\n                maybe_create_child_filter(rule.expansion, keep_all_tokens, self.ambiguous, options.empty_indices if self.maybe_placeholders else None),\n                propagate_positions,\n                self.ambiguous and maybe_create_ambiguous_expander(self.tree_class, rule.expansion, keep_all_tokens),\n                self.ambiguous and partial(AmbiguousIntermediateExpander, self.tree_class)\n            ]))\n\n            yield rule, wrapper_chain\n\n    def create_callback(self, transformer=None):\n        callbacks = {}\n\n        default_handler = getattr(transformer, '__default__', None)\n        if default_handler:\n            def default_callback(data, children):\n                return default_handler(data, children, None)\n        else:\n            default_callback = self.tree_class\n\n        for rule, wrapper_chain in self.rule_builders:\n\n            user_callback_name = rule.alias or rule.options.template_source or rule.origin.name\n            try:\n                f = getattr(transformer, user_callback_name)\n                wrapper = getattr(f, 'visit_wrapper', None)\n                if wrapper is not None:\n                    f = apply_visit_wrapper(f, user_callback_name, wrapper)\n                elif isinstance(transformer, Transformer_InPlace):\n                    f = inplace_transformer(f)\n            except AttributeError:\n                f = partial(default_callback, user_callback_name)\n\n            for w in wrapper_chain:\n                f = w(f)\n\n            if rule in callbacks:\n                raise GrammarError(\"Rule '%s' already exists\" % (rule,))\n\n            callbacks[rule] = f\n\n        return callbacks\n\n\n\nclass LALR_Parser(Serialize):\n    def __init__(self, parser_conf, debug=False, strict=False):\n        analysis = LALR_Analyzer(parser_conf, debug=debug, strict=strict)\n        analysis.compute_lalr()\n        callbacks = parser_conf.callbacks\n\n        self._parse_table = analysis.parse_table\n        self.parser_conf = parser_conf\n        self.parser = _Parser(analysis.parse_table, callbacks, debug)\n\n    @classmethod\n    def deserialize(cls, data, memo, callbacks, debug=False):\n        inst = cls.__new__(cls)\n        inst._parse_table = IntParseTable.deserialize(data, memo)\n        inst.parser = _Parser(inst._parse_table, callbacks, debug)\n        return inst\n\n    def serialize(self, memo: Any = None) -> Dict[str, Any]:\n        return self._parse_table.serialize(memo)\n\n    def parse_interactive(self, lexer, start):\n        return self.parser.parse(lexer, start, start_interactive=True)\n\n    def parse(self, lexer, start, on_error=None):\n        try:\n            return self.parser.parse(lexer, start)\n        except UnexpectedInput as e:\n            if on_error is None:\n                raise\n\n            while True:\n                if isinstance(e, UnexpectedCharacters):\n                    s = e.interactive_parser.lexer_thread.state\n                    p = s.line_ctr.char_pos\n\n                if not on_error(e):\n                    raise e\n\n                if isinstance(e, UnexpectedCharacters):\n                    ##\n\n                    if p == s.line_ctr.char_pos:\n                        s.line_ctr.feed(s.text[p:p+1])\n\n                try:\n                    return e.interactive_parser.resume_parse()\n                except UnexpectedToken as e2:\n                    if (isinstance(e, UnexpectedToken)\n                        and e.token.type == e2.token.type == '$END'\n                        and e.interactive_parser == e2.interactive_parser):\n                        ##\n\n                        raise e2\n                    e = e2\n                except UnexpectedCharacters as e2:\n                    e = e2\n\n\nclass ParseConf:\n    __slots__ = 'parse_table', 'callbacks', 'start', 'start_state', 'end_state', 'states'\n\n    def __init__(self, parse_table, callbacks, start):\n        self.parse_table = parse_table\n\n        self.start_state = self.parse_table.start_states[start]\n        self.end_state = self.parse_table.end_states[start]\n        self.states = self.parse_table.states\n\n        self.callbacks = callbacks\n        self.start = start\n\n\nclass ParserState:\n    __slots__ = 'parse_conf', 'lexer', 'state_stack', 'value_stack'\n\n    def __init__(self, parse_conf, lexer, state_stack=None, value_stack=None):\n        self.parse_conf = parse_conf\n        self.lexer = lexer\n        self.state_stack = state_stack or [self.parse_conf.start_state]\n        self.value_stack = value_stack or []\n\n    @property\n    def position(self):\n        return self.state_stack[-1]\n\n    ##\n\n    def __eq__(self, other):\n        if not isinstance(other, ParserState):\n            return NotImplemented\n        return len(self.state_stack) == len(other.state_stack) and self.position == other.position\n\n    def __copy__(self):\n        return type(self)(\n            self.parse_conf,\n            self.lexer, ##\n\n            copy(self.state_stack),\n            deepcopy(self.value_stack),\n        )\n\n    def copy(self):\n        return copy(self)\n\n    def feed_token(self, token, is_end=False):\n        state_stack = self.state_stack\n        value_stack = self.value_stack\n        states = self.parse_conf.states\n        end_state = self.parse_conf.end_state\n        callbacks = self.parse_conf.callbacks\n\n        while True:\n            state = state_stack[-1]\n            try:\n                action, arg = states[state][token.type]\n            except KeyError:\n                expected = {s for s in states[state].keys() if s.isupper()}\n                raise UnexpectedToken(token, expected, state=self, interactive_parser=None)\n\n            assert arg != end_state\n\n            if action is Shift:\n                ##\n\n                assert not is_end\n                state_stack.append(arg)\n                value_stack.append(token if token.type not in callbacks else callbacks[token.type](token))\n                return\n            else:\n                ##\n\n                rule = arg\n                size = len(rule.expansion)\n                if size:\n                    s = value_stack[-size:]\n                    del state_stack[-size:]\n                    del value_stack[-size:]\n                else:\n                    s = []\n\n                value = callbacks[rule](s)\n\n                _action, new_state = states[state_stack[-1]][rule.origin.name]\n                assert _action is Shift\n                state_stack.append(new_state)\n                value_stack.append(value)\n\n                if is_end and state_stack[-1] == end_state:\n                    return value_stack[-1]\n\nclass _Parser:\n    def __init__(self, parse_table, callbacks, debug=False):\n        self.parse_table = parse_table\n        self.callbacks = callbacks\n        self.debug = debug\n\n    def parse(self, lexer, start, value_stack=None, state_stack=None, start_interactive=False):\n        parse_conf = ParseConf(self.parse_table, self.callbacks, start)\n        parser_state = ParserState(parse_conf, lexer, state_stack, value_stack)\n        if start_interactive:\n            return InteractiveParser(self, parser_state, parser_state.lexer)\n        return self.parse_from_state(parser_state)\n\n\n    def parse_from_state(self, state, last_token=None):\n        #--\n        try:\n            token = last_token\n            for token in state.lexer.lex(state):\n                state.feed_token(token)\n\n            end_token = Token.new_borrow_pos('$END', '', token) if token else Token('$END', '', 0, 1, 1)\n            return state.feed_token(end_token, True)\n        except UnexpectedInput as e:\n            try:\n                e.interactive_parser = InteractiveParser(self, state, state.lexer)\n            except NameError:\n                pass\n            raise e\n        except Exception as e:\n            if self.debug:\n                print(\"\")\n                print(\"STATE STACK DUMP\")\n                print(\"----------------\")\n                for i, s in enumerate(state.state_stack):\n                    print('%d)' % i , s)\n                print(\"\")\n\n            raise\n\n\nclass Action:\n    def __init__(self, name):\n        self.name = name\n    def __str__(self):\n        return self.name\n    def __repr__(self):\n        return str(self)\n\nShift = Action('Shift')\nReduce = Action('Reduce')\n\n\nclass ParseTable:\n    def __init__(self, states, start_states, end_states):\n        self.states = states\n        self.start_states = start_states\n        self.end_states = end_states\n\n    def serialize(self, memo):\n        tokens = Enumerator()\n\n        states = {\n            state: {tokens.get(token): ((1, arg.serialize(memo)) if action is Reduce else (0, arg))\n                    for token, (action, arg) in actions.items()}\n            for state, actions in self.states.items()\n        }\n\n        return {\n            'tokens': tokens.reversed(),\n            'states': states,\n            'start_states': self.start_states,\n            'end_states': self.end_states,\n        }\n\n    @classmethod\n    def deserialize(cls, data, memo):\n        tokens = data['tokens']\n        states = {\n            state: {tokens[token]: ((Reduce, Rule.deserialize(arg, memo)) if action==1 else (Shift, arg))\n                    for token, (action, arg) in actions.items()}\n            for state, actions in data['states'].items()\n        }\n        return cls(states, data['start_states'], data['end_states'])\n\n\nclass IntParseTable(ParseTable):\n\n    @classmethod\n    def from_ParseTable(cls, parse_table):\n        enum = list(parse_table.states)\n        state_to_idx = {s:i for i,s in enumerate(enum)}\n        int_states = {}\n\n        for s, la in parse_table.states.items():\n            la = {k:(v[0], state_to_idx[v[1]]) if v[0] is Shift else v\n                  for k,v in la.items()}\n            int_states[ state_to_idx[s] ] = la\n\n\n        start_states = {start:state_to_idx[s] for start, s in parse_table.start_states.items()}\n        end_states = {start:state_to_idx[s] for start, s in parse_table.end_states.items()}\n        return cls(int_states, start_states, end_states)\n\n\n\ndef _wrap_lexer(lexer_class):\n    future_interface = getattr(lexer_class, '__future_interface__', False)\n    if future_interface:\n        return lexer_class\n    else:\n        class CustomLexerWrapper(Lexer):\n            def __init__(self, lexer_conf):\n                self.lexer = lexer_class(lexer_conf)\n            def lex(self, lexer_state, parser_state):\n                return self.lexer.lex(lexer_state.text)\n        return CustomLexerWrapper\n\n\ndef _deserialize_parsing_frontend(data, memo, lexer_conf, callbacks, options):\n    parser_conf = ParserConf.deserialize(data['parser_conf'], memo)\n    cls = (options and options._plugins.get('LALR_Parser')) or LALR_Parser\n    parser = cls.deserialize(data['parser'], memo, callbacks, options.debug)\n    parser_conf.callbacks = callbacks\n    return ParsingFrontend(lexer_conf, parser_conf, options, parser=parser)\n\n\n_parser_creators: 'Dict[str, Callable[[LexerConf, Any, Any], Any]]' = {}\n\n\nclass ParsingFrontend(Serialize):\n    __serialize_fields__ = 'lexer_conf', 'parser_conf', 'parser'\n\n    lexer_conf: LexerConf\n    parser_conf: ParserConf\n    options: Any\n\n    def __init__(self, lexer_conf: LexerConf, parser_conf: ParserConf, options, parser=None):\n        self.parser_conf = parser_conf\n        self.lexer_conf = lexer_conf\n        self.options = options\n\n        ##\n\n        if parser:  ##\n\n            self.parser = parser\n        else:\n            create_parser = _parser_creators.get(parser_conf.parser_type)\n            assert create_parser is not None, \"{} is not supported in standalone mode\".format(\n                    parser_conf.parser_type\n                )\n            self.parser = create_parser(lexer_conf, parser_conf, options)\n\n        ##\n\n        lexer_type = lexer_conf.lexer_type\n        self.skip_lexer = False\n        if lexer_type in ('dynamic', 'dynamic_complete'):\n            assert lexer_conf.postlex is None\n            self.skip_lexer = True\n            return\n\n        if isinstance(lexer_type, type):\n            assert issubclass(lexer_type, Lexer)\n            self.lexer = _wrap_lexer(lexer_type)(lexer_conf)\n        elif isinstance(lexer_type, str):\n            create_lexer = {\n                'basic': create_basic_lexer,\n                'contextual': create_contextual_lexer,\n            }[lexer_type]\n            self.lexer = create_lexer(lexer_conf, self.parser, lexer_conf.postlex, options)\n        else:\n            raise TypeError(\"Bad value for lexer_type: {lexer_type}\")\n\n        if lexer_conf.postlex:\n            self.lexer = PostLexConnector(self.lexer, lexer_conf.postlex)\n\n    def _verify_start(self, start=None):\n        if start is None:\n            start_decls = self.parser_conf.start\n            if len(start_decls) > 1:\n                raise ConfigurationError(\"Lark initialized with more than 1 possible start rule. Must specify which start rule to parse\", start_decls)\n            start ,= start_decls\n        elif start not in self.parser_conf.start:\n            raise ConfigurationError(\"Unknown start rule %s. Must be one of %r\" % (start, self.parser_conf.start))\n        return start\n\n    def _make_lexer_thread(self, text: str):\n        cls = (self.options and self.options._plugins.get('LexerThread')) or LexerThread\n        return text if self.skip_lexer else cls.from_text(self.lexer, text)\n\n    def parse(self, text: str, start=None, on_error=None):\n        chosen_start = self._verify_start(start)\n        kw = {} if on_error is None else {'on_error': on_error}\n        stream = self._make_lexer_thread(text)\n        return self.parser.parse(stream, chosen_start, **kw)\n\n    def parse_interactive(self, text: Optional[str]=None, start=None):\n        ##\n\n        ##\n\n        chosen_start = self._verify_start(start)\n        if self.parser_conf.parser_type != 'lalr':\n            raise ConfigurationError(\"parse_interactive() currently only works with parser='lalr' \")\n        stream = self._make_lexer_thread(text)  ##\n\n        return self.parser.parse_interactive(stream, chosen_start)\n\n\ndef _validate_frontend_args(parser, lexer) -> None:\n    assert_config(parser, ('lalr', 'earley', 'cyk'))\n    if not isinstance(lexer, type):     ##\n\n        expected = {\n            'lalr': ('basic', 'contextual'),\n            'earley': ('basic', 'dynamic', 'dynamic_complete'),\n            'cyk': ('basic', ),\n         }[parser]\n        assert_config(lexer, expected, 'Parser %r does not support lexer %%r, expected one of %%s' % parser)\n\n\ndef _get_lexer_callbacks(transformer, terminals):\n    result = {}\n    for terminal in terminals:\n        callback = getattr(transformer, terminal.name, None)\n        if callback is not None:\n            result[terminal.name] = callback\n    return result\n\nclass PostLexConnector:\n    def __init__(self, lexer, postlexer):\n        self.lexer = lexer\n        self.postlexer = postlexer\n\n    def lex(self, lexer_state, parser_state):\n        i = self.lexer.lex(lexer_state, parser_state)\n        return self.postlexer.process(i)\n\n\n\ndef create_basic_lexer(lexer_conf, parser, postlex, options) -> BasicLexer:\n    cls = (options and options._plugins.get('BasicLexer')) or BasicLexer\n    return cls(lexer_conf)\n\ndef create_contextual_lexer(lexer_conf: LexerConf, parser, postlex, options) -> ContextualLexer:\n    cls = (options and options._plugins.get('ContextualLexer')) or ContextualLexer\n    states: Dict[str, Collection[str]] = {idx:list(t.keys()) for idx, t in parser._parse_table.states.items()}\n    always_accept: Collection[str] = postlex.always_accept if postlex else ()\n    return cls(lexer_conf, states, always_accept=always_accept)\n\ndef create_lalr_parser(lexer_conf: LexerConf, parser_conf: ParserConf, options=None) -> LALR_Parser:\n    debug = options.debug if options else False\n    strict = options.strict if options else False\n    cls = (options and options._plugins.get('LALR_Parser')) or LALR_Parser\n    return cls(parser_conf, debug=debug, strict=strict)\n\n_parser_creators['lalr'] = create_lalr_parser\n\n\n\n\nclass PostLex(ABC):\n    @abstractmethod\n    def process(self, stream: Iterator[Token]) -> Iterator[Token]:\n        return stream\n\n    always_accept: Iterable[str] = ()\n\nclass LarkOptions(Serialize):\n    #--\n\n    start: List[str]\n    debug: bool\n    strict: bool\n    transformer: 'Optional[Transformer]'\n    propagate_positions: Union[bool, str]\n    maybe_placeholders: bool\n    cache: Union[bool, str]\n    regex: bool\n    g_regex_flags: int\n    keep_all_tokens: bool\n    tree_class: Any\n    parser: _ParserArgType\n    lexer: _LexerArgType\n    ambiguity: 'Literal[\"auto\", \"resolve\", \"explicit\", \"forest\"]'\n    postlex: Optional[PostLex]\n    priority: 'Optional[Literal[\"auto\", \"normal\", \"invert\"]]'\n    lexer_callbacks: Dict[str, Callable[[Token], Token]]\n    use_bytes: bool\n    edit_terminals: Optional[Callable[[TerminalDef], TerminalDef]]\n    import_paths: 'List[Union[str, Callable[[Union[None, str, PackageResource], str], Tuple[str, str]]]]'\n    source_path: Optional[str]\n\n    OPTIONS_DOC = \"\"\"\n    **===  General Options  ===**\n\n    start\n            The start symbol. Either a string, or a list of strings for multiple possible starts (Default: \"start\")\n    debug\n            Display debug information and extra warnings. Use only when debugging (Default: ``False``)\n            When used with Earley, it generates a forest graph as \"sppf.png\", if 'dot' is installed.\n    strict\n            Throw an exception on any potential ambiguity, including shift/reduce conflicts, and regex collisions.\n    transformer\n            Applies the transformer to every parse tree (equivalent to applying it after the parse, but faster)\n    propagate_positions\n            Propagates positional attributes into the 'meta' attribute of all tree branches.\n            Sets attributes: (line, column, end_line, end_column, start_pos, end_pos,\n                              container_line, container_column, container_end_line, container_end_column)\n            Accepts ``False``, ``True``, or a callable, which will filter which nodes to ignore when propagating.\n    maybe_placeholders\n            When ``True``, the ``[]`` operator returns ``None`` when not matched.\n            When ``False``,  ``[]`` behaves like the ``?`` operator, and returns no value at all.\n            (default= ``True``)\n    cache\n            Cache the results of the Lark grammar analysis, for x2 to x3 faster loading. LALR only for now.\n\n            - When ``False``, does nothing (default)\n            - When ``True``, caches to a temporary file in the local directory\n            - When given a string, caches to the path pointed by the string\n    regex\n            When True, uses the ``regex`` module instead of the stdlib ``re``.\n    g_regex_flags\n            Flags that are applied to all terminals (both regex and strings)\n    keep_all_tokens\n            Prevent the tree builder from automagically removing \"punctuation\" tokens (Default: ``False``)\n    tree_class\n            Lark will produce trees comprised of instances of this class instead of the default ``lark.Tree``.\n\n    **=== Algorithm Options ===**\n\n    parser\n            Decides which parser engine to use. Accepts \"earley\" or \"lalr\". (Default: \"earley\").\n            (there is also a \"cyk\" option for legacy)\n    lexer\n            Decides whether or not to use a lexer stage\n\n            - \"auto\" (default): Choose for me based on the parser\n            - \"basic\": Use a basic lexer\n            - \"contextual\": Stronger lexer (only works with parser=\"lalr\")\n            - \"dynamic\": Flexible and powerful (only with parser=\"earley\")\n            - \"dynamic_complete\": Same as dynamic, but tries *every* variation of tokenizing possible.\n    ambiguity\n            Decides how to handle ambiguity in the parse. Only relevant if parser=\"earley\"\n\n            - \"resolve\": The parser will automatically choose the simplest derivation\n              (it chooses consistently: greedy for tokens, non-greedy for rules)\n            - \"explicit\": The parser will return all derivations wrapped in \"_ambig\" tree nodes (i.e. a forest).\n            - \"forest\": The parser will return the root of the shared packed parse forest.\n\n    **=== Misc. / Domain Specific Options ===**\n\n    postlex\n            Lexer post-processing (Default: ``None``) Only works with the basic and contextual lexers.\n    priority\n            How priorities should be evaluated - \"auto\", ``None``, \"normal\", \"invert\" (Default: \"auto\")\n    lexer_callbacks\n            Dictionary of callbacks for the lexer. May alter tokens during lexing. Use with caution.\n    use_bytes\n            Accept an input of type ``bytes`` instead of ``str``.\n    edit_terminals\n            A callback for editing the terminals before parse.\n    import_paths\n            A List of either paths or loader functions to specify from where grammars are imported\n    source_path\n            Override the source of from where the grammar was loaded. Useful for relative imports and unconventional grammar loading\n    **=== End of Options ===**\n    \"\"\"\n    if __doc__:\n        __doc__ += OPTIONS_DOC\n\n\n    ##\n\n    ##\n\n    ##\n\n    ##\n\n    ##\n\n    ##\n\n    _defaults: Dict[str, Any] = {\n        'debug': False,\n        'strict': False,\n        'keep_all_tokens': False,\n        'tree_class': None,\n        'cache': False,\n        'postlex': None,\n        'parser': 'earley',\n        'lexer': 'auto',\n        'transformer': None,\n        'start': 'start',\n        'priority': 'auto',\n        'ambiguity': 'auto',\n        'regex': False,\n        'propagate_positions': False,\n        'lexer_callbacks': {},\n        'maybe_placeholders': True,\n        'edit_terminals': None,\n        'g_regex_flags': 0,\n        'use_bytes': False,\n        'import_paths': [],\n        'source_path': None,\n        '_plugins': {},\n    }\n\n    def __init__(self, options_dict: Dict[str, Any]) -> None:\n        o = dict(options_dict)\n\n        options = {}\n        for name, default in self._defaults.items():\n            if name in o:\n                value = o.pop(name)\n                if isinstance(default, bool) and name not in ('cache', 'use_bytes', 'propagate_positions'):\n                    value = bool(value)\n            else:\n                value = default\n\n            options[name] = value\n\n        if isinstance(options['start'], str):\n            options['start'] = [options['start']]\n\n        self.__dict__['options'] = options\n\n\n        assert_config(self.parser, ('earley', 'lalr', 'cyk', None))\n\n        if self.parser == 'earley' and self.transformer:\n            raise ConfigurationError('Cannot specify an embedded transformer when using the Earley algorithm. '\n                             'Please use your transformer on the resulting parse tree, or use a different algorithm (i.e. LALR)')\n\n        if o:\n            raise ConfigurationError(\"Unknown options: %s\" % o.keys())\n\n    def __getattr__(self, name: str) -> Any:\n        try:\n            return self.__dict__['options'][name]\n        except KeyError as e:\n            raise AttributeError(e)\n\n    def __setattr__(self, name: str, value: str) -> None:\n        assert_config(name, self.options.keys(), \"%r isn't a valid option. Expected one of: %s\")\n        self.options[name] = value\n\n    def serialize(self, memo = None) -> Dict[str, Any]:\n        return self.options\n\n    @classmethod\n    def deserialize(cls, data: Dict[str, Any], memo: Dict[int, Union[TerminalDef, Rule]]) -> \"LarkOptions\":\n        return cls(data)\n\n\n##\n\n##\n\n_LOAD_ALLOWED_OPTIONS = {'postlex', 'transformer', 'lexer_callbacks', 'use_bytes', 'debug', 'g_regex_flags', 'regex', 'propagate_positions', 'tree_class', '_plugins'}\n\n_VALID_PRIORITY_OPTIONS = ('auto', 'normal', 'invert', None)\n_VALID_AMBIGUITY_OPTIONS = ('auto', 'resolve', 'explicit', 'forest')\n\n\n_T = TypeVar('_T', bound=\"Lark\")\n\nclass Lark(Serialize):\n    #--\n\n    source_path: str\n    source_grammar: str\n    grammar: 'Grammar'\n    options: LarkOptions\n    lexer: Lexer\n    parser: 'ParsingFrontend'\n    terminals: Collection[TerminalDef]\n\n    def __init__(self, grammar: 'Union[Grammar, str, IO[str]]', **options) -> None:\n        self.options = LarkOptions(options)\n        re_module: types.ModuleType\n\n        ##\n\n        use_regex = self.options.regex\n        if use_regex:\n            if _has_regex:\n                re_module = regex\n            else:\n                raise ImportError('`regex` module must be installed if calling `Lark(regex=True)`.')\n        else:\n            re_module = re\n\n        ##\n\n        if self.options.source_path is None:\n            try:\n                self.source_path = grammar.name  ##\n\n            except AttributeError:\n                self.source_path = '<string>'\n        else:\n            self.source_path = self.options.source_path\n\n        ##\n\n        try:\n            read = grammar.read  ##\n\n        except AttributeError:\n            pass\n        else:\n            grammar = read()\n\n        cache_fn = None\n        cache_sha256 = None\n        if isinstance(grammar, str):\n            self.source_grammar = grammar\n            if self.options.use_bytes:\n                if not isascii(grammar):\n                    raise ConfigurationError(\"Grammar must be ascii only, when use_bytes=True\")\n\n            if self.options.cache:\n                if self.options.parser != 'lalr':\n                    raise ConfigurationError(\"cache only works with parser='lalr' for now\")\n\n                unhashable = ('transformer', 'postlex', 'lexer_callbacks', 'edit_terminals', '_plugins')\n                options_str = ''.join(k+str(v) for k, v in options.items() if k not in unhashable)\n                from . import __version__\n                s = grammar + options_str + __version__ + str(sys.version_info[:2])\n                cache_sha256 = sha256_digest(s)\n\n                if isinstance(self.options.cache, str):\n                    cache_fn = self.options.cache\n                else:\n                    if self.options.cache is not True:\n                        raise ConfigurationError(\"cache argument must be bool or str\")\n\n                    try:\n                        username = getpass.getuser()\n                    except Exception:\n                        ##\n\n                        ##\n\n                        ##\n\n                        username = \"unknown\"\n\n                    cache_fn = tempfile.gettempdir() + \"/.lark_cache_%s_%s_%s_%s.tmp\" % (username, cache_sha256, *sys.version_info[:2])\n\n                old_options = self.options\n                try:\n                    with FS.open(cache_fn, 'rb') as f:\n                        logger.debug('Loading grammar from cache: %s', cache_fn)\n                        ##\n\n                        for name in (set(options) - _LOAD_ALLOWED_OPTIONS):\n                            del options[name]\n                        file_sha256 = f.readline().rstrip(b'\\n')\n                        cached_used_files = pickle.load(f)\n                        if file_sha256 == cache_sha256.encode('utf8') and verify_used_files(cached_used_files):\n                            cached_parser_data = pickle.load(f)\n                            self._load(cached_parser_data, **options)\n                            return\n                except FileNotFoundError:\n                    ##\n\n                    pass\n                except Exception: ##\n\n                    logger.exception(\"Failed to load Lark from cache: %r. We will try to carry on.\", cache_fn)\n\n                    ##\n\n                    ##\n\n                    self.options = old_options\n\n\n            ##\n\n            self.grammar, used_files = load_grammar(grammar, self.source_path, self.options.import_paths, self.options.keep_all_tokens)\n        else:\n            assert isinstance(grammar, Grammar)\n            self.grammar = grammar\n\n\n        if self.options.lexer == 'auto':\n            if self.options.parser == 'lalr':\n                self.options.lexer = 'contextual'\n            elif self.options.parser == 'earley':\n                if self.options.postlex is not None:\n                    logger.info(\"postlex can't be used with the dynamic lexer, so we use 'basic' instead. \"\n                                \"Consider using lalr with contextual instead of earley\")\n                    self.options.lexer = 'basic'\n                else:\n                    self.options.lexer = 'dynamic'\n            elif self.options.parser == 'cyk':\n                self.options.lexer = 'basic'\n            else:\n                assert False, self.options.parser\n        lexer = self.options.lexer\n        if isinstance(lexer, type):\n            assert issubclass(lexer, Lexer)     ##\n\n        else:\n            assert_config(lexer, ('basic', 'contextual', 'dynamic', 'dynamic_complete'))\n            if self.options.postlex is not None and 'dynamic' in lexer:\n                raise ConfigurationError(\"Can't use postlex with a dynamic lexer. Use basic or contextual instead\")\n\n        if self.options.ambiguity == 'auto':\n            if self.options.parser == 'earley':\n                self.options.ambiguity = 'resolve'\n        else:\n            assert_config(self.options.parser, ('earley', 'cyk'), \"%r doesn't support disambiguation. Use one of these parsers instead: %s\")\n\n        if self.options.priority == 'auto':\n            self.options.priority = 'normal'\n\n        if self.options.priority not in _VALID_PRIORITY_OPTIONS:\n            raise ConfigurationError(\"invalid priority option: %r. Must be one of %r\" % (self.options.priority, _VALID_PRIORITY_OPTIONS))\n        if self.options.ambiguity not in _VALID_AMBIGUITY_OPTIONS:\n            raise ConfigurationError(\"invalid ambiguity option: %r. Must be one of %r\" % (self.options.ambiguity, _VALID_AMBIGUITY_OPTIONS))\n\n        if self.options.parser is None:\n            terminals_to_keep = '*'\n        elif self.options.postlex is not None:\n            terminals_to_keep = set(self.options.postlex.always_accept)\n        else:\n            terminals_to_keep = set()\n\n        ##\n\n        self.terminals, self.rules, self.ignore_tokens = self.grammar.compile(self.options.start, terminals_to_keep)\n\n        if self.options.edit_terminals:\n            for t in self.terminals:\n                self.options.edit_terminals(t)\n\n        self._terminals_dict = {t.name: t for t in self.terminals}\n\n        ##\n\n        if self.options.priority == 'invert':\n            for rule in self.rules:\n                if rule.options.priority is not None:\n                    rule.options.priority = -rule.options.priority\n            for term in self.terminals:\n                term.priority = -term.priority\n        ##\n\n        ##\n\n        ##\n\n        elif self.options.priority is None:\n            for rule in self.rules:\n                if rule.options.priority is not None:\n                    rule.options.priority = None\n            for term in self.terminals:\n                term.priority = 0\n\n        ##\n\n        self.lexer_conf = LexerConf(\n                self.terminals, re_module, self.ignore_tokens, self.options.postlex,\n                self.options.lexer_callbacks, self.options.g_regex_flags, use_bytes=self.options.use_bytes, strict=self.options.strict\n            )\n\n        if self.options.parser:\n            self.parser = self._build_parser()\n        elif lexer:\n            self.lexer = self._build_lexer()\n\n        if cache_fn:\n            logger.debug('Saving grammar to cache: %s', cache_fn)\n            try:\n                with FS.open(cache_fn, 'wb') as f:\n                    assert cache_sha256 is not None\n                    f.write(cache_sha256.encode('utf8') + b'\\n')\n                    pickle.dump(used_files, f)\n                    self.save(f, _LOAD_ALLOWED_OPTIONS)\n            except IOError as e:\n                logger.exception(\"Failed to save Lark to cache: %r.\", cache_fn, e)\n\n    if __doc__:\n        __doc__ += \"\\n\\n\" + LarkOptions.OPTIONS_DOC\n\n    __serialize_fields__ = 'parser', 'rules', 'options'\n\n    def _build_lexer(self, dont_ignore: bool=False) -> BasicLexer:\n        lexer_conf = self.lexer_conf\n        if dont_ignore:\n            from copy import copy\n            lexer_conf = copy(lexer_conf)\n            lexer_conf.ignore = ()\n        return BasicLexer(lexer_conf)\n\n    def _prepare_callbacks(self) -> None:\n        self._callbacks = {}\n        ##\n\n        if self.options.ambiguity != 'forest':\n            self._parse_tree_builder = ParseTreeBuilder(\n                    self.rules,\n                    self.options.tree_class or Tree,\n                    self.options.propagate_positions,\n                    self.options.parser != 'lalr' and self.options.ambiguity == 'explicit',\n                    self.options.maybe_placeholders\n                )\n            self._callbacks = self._parse_tree_builder.create_callback(self.options.transformer)\n        self._callbacks.update(_get_lexer_callbacks(self.options.transformer, self.terminals))\n\n    def _build_parser(self) -> \"ParsingFrontend\":\n        self._prepare_callbacks()\n        _validate_frontend_args(self.options.parser, self.options.lexer)\n        parser_conf = ParserConf(self.rules, self._callbacks, self.options.start)\n        return _construct_parsing_frontend(\n            self.options.parser,\n            self.options.lexer,\n            self.lexer_conf,\n            parser_conf,\n            options=self.options\n        )\n\n    def save(self, f, exclude_options: Collection[str] = ()) -> None:\n        #--\n        data, m = self.memo_serialize([TerminalDef, Rule])\n        if exclude_options:\n            data[\"options\"] = {n: v for n, v in data[\"options\"].items() if n not in exclude_options}\n        pickle.dump({'data': data, 'memo': m}, f, protocol=pickle.HIGHEST_PROTOCOL)\n\n    @classmethod\n    def load(cls: Type[_T], f) -> _T:\n        #--\n        inst = cls.__new__(cls)\n        return inst._load(f)\n\n    def _deserialize_lexer_conf(self, data: Dict[str, Any], memo: Dict[int, Union[TerminalDef, Rule]], options: LarkOptions) -> LexerConf:\n        lexer_conf = LexerConf.deserialize(data['lexer_conf'], memo)\n        lexer_conf.callbacks = options.lexer_callbacks or {}\n        lexer_conf.re_module = regex if options.regex else re\n        lexer_conf.use_bytes = options.use_bytes\n        lexer_conf.g_regex_flags = options.g_regex_flags\n        lexer_conf.skip_validation = True\n        lexer_conf.postlex = options.postlex\n        return lexer_conf\n\n    def _load(self: _T, f: Any, **kwargs) -> _T:\n        if isinstance(f, dict):\n            d = f\n        else:\n            d = pickle.load(f)\n        memo_json = d['memo']\n        data = d['data']\n\n        assert memo_json\n        memo = SerializeMemoizer.deserialize(memo_json, {'Rule': Rule, 'TerminalDef': TerminalDef}, {})\n        options = dict(data['options'])\n        if (set(kwargs) - _LOAD_ALLOWED_OPTIONS) & set(LarkOptions._defaults):\n            raise ConfigurationError(\"Some options are not allowed when loading a Parser: {}\"\n                             .format(set(kwargs) - _LOAD_ALLOWED_OPTIONS))\n        options.update(kwargs)\n        self.options = LarkOptions.deserialize(options, memo)\n        self.rules = [Rule.deserialize(r, memo) for r in data['rules']]\n        self.source_path = '<deserialized>'\n        _validate_frontend_args(self.options.parser, self.options.lexer)\n        self.lexer_conf = self._deserialize_lexer_conf(data['parser'], memo, self.options)\n        self.terminals = self.lexer_conf.terminals\n        self._prepare_callbacks()\n        self._terminals_dict = {t.name: t for t in self.terminals}\n        self.parser = _deserialize_parsing_frontend(\n            data['parser'],\n            memo,\n            self.lexer_conf,\n            self._callbacks,\n            self.options,  ##\n\n        )\n        return self\n\n    @classmethod\n    def _load_from_dict(cls, data, memo, **kwargs):\n        inst = cls.__new__(cls)\n        return inst._load({'data': data, 'memo': memo}, **kwargs)\n\n    @classmethod\n    def open(cls: Type[_T], grammar_filename: str, rel_to: Optional[str]=None, **options) -> _T:\n        #--\n        if rel_to:\n            basepath = os.path.dirname(rel_to)\n            grammar_filename = os.path.join(basepath, grammar_filename)\n        with open(grammar_filename, encoding='utf8') as f:\n            return cls(f, **options)\n\n    @classmethod\n    def open_from_package(cls: Type[_T], package: str, grammar_path: str, search_paths: 'Sequence[str]'=[\"\"], **options) -> _T:\n        #--\n        package_loader = FromPackageLoader(package, search_paths)\n        full_path, text = package_loader(None, grammar_path)\n        options.setdefault('source_path', full_path)\n        options.setdefault('import_paths', [])\n        options['import_paths'].append(package_loader)\n        return cls(text, **options)\n\n    def __repr__(self):\n        return 'Lark(open(%r), parser=%r, lexer=%r, ...)' % (self.source_path, self.options.parser, self.options.lexer)\n\n\n    def lex(self, text: str, dont_ignore: bool=False) -> Iterator[Token]:\n        #--\n        lexer: Lexer\n        if not hasattr(self, 'lexer') or dont_ignore:\n            lexer = self._build_lexer(dont_ignore)\n        else:\n            lexer = self.lexer\n        lexer_thread = LexerThread.from_text(lexer, text)\n        stream = lexer_thread.lex(None)\n        if self.options.postlex:\n            return self.options.postlex.process(stream)\n        return stream\n\n    def get_terminal(self, name: str) -> TerminalDef:\n        #--\n        return self._terminals_dict[name]\n\n    def parse_interactive(self, text: Optional[str]=None, start: Optional[str]=None) -> 'InteractiveParser':\n        #--\n        return self.parser.parse_interactive(text, start=start)\n\n    def parse(self, text: str, start: Optional[str]=None, on_error: 'Optional[Callable[[UnexpectedInput], bool]]'=None) -> 'ParseTree':\n        #--\n        return self.parser.parse(text, start=start, on_error=on_error)\n\n\n\n\nclass DedentError(LarkError):\n    pass\n\nclass Indenter(PostLex, ABC):\n    paren_level: int\n    indent_level: List[int]\n\n    def __init__(self) -> None:\n        self.paren_level = 0\n        self.indent_level = [0]\n        assert self.tab_len > 0\n\n    def handle_NL(self, token: Token) -> Iterator[Token]:\n        if self.paren_level > 0:\n            return\n\n        yield token\n\n        indent_str = token.rsplit('\\n', 1)[1] ##\n\n        indent = indent_str.count(' ') + indent_str.count('\\t') * self.tab_len\n\n        if indent > self.indent_level[-1]:\n            self.indent_level.append(indent)\n            yield Token.new_borrow_pos(self.INDENT_type, indent_str, token)\n        else:\n            while indent < self.indent_level[-1]:\n                self.indent_level.pop()\n                yield Token.new_borrow_pos(self.DEDENT_type, indent_str, token)\n\n            if indent != self.indent_level[-1]:\n                raise DedentError('Unexpected dedent to column %s. Expected dedent to %s' % (indent, self.indent_level[-1]))\n\n    def _process(self, stream):\n        for token in stream:\n            if token.type == self.NL_type:\n                yield from self.handle_NL(token)\n            else:\n                yield token\n\n            if token.type in self.OPEN_PAREN_types:\n                self.paren_level += 1\n            elif token.type in self.CLOSE_PAREN_types:\n                self.paren_level -= 1\n                assert self.paren_level >= 0\n\n        while len(self.indent_level) > 1:\n            self.indent_level.pop()\n            yield Token(self.DEDENT_type, '')\n\n        assert self.indent_level == [0], self.indent_level\n\n    def process(self, stream):\n        self.paren_level = 0\n        self.indent_level = [0]\n        return self._process(stream)\n\n    ##\n\n    @property\n    def always_accept(self):\n        return (self.NL_type,)\n\n    @property\n    @abstractmethod\n    def NL_type(self) -> str:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def OPEN_PAREN_types(self) -> List[str]:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def CLOSE_PAREN_types(self) -> List[str]:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def INDENT_type(self) -> str:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def DEDENT_type(self) -> str:\n        raise NotImplementedError()\n\n    @property\n    @abstractmethod\n    def tab_len(self) -> int:\n        raise NotImplementedError()\n\n\nclass PythonIndenter(Indenter):\n    NL_type = '_NEWLINE'\n    OPEN_PAREN_types = ['LPAR', 'LSQB', 'LBRACE']\n    CLOSE_PAREN_types = ['RPAR', 'RSQB', 'RBRACE']\n    INDENT_type = '_INDENT'\n    DEDENT_type = '_DEDENT'\n    tab_len = 8\n\n\nimport pickle, zlib, base64\nDATA = (\n{'parser': {'lexer_conf': {'terminals': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}, {'@': 12}, {'@': 13}, {'@': 14}, {'@': 15}, {'@': 16}, {'@': 17}, {'@': 18}, {'@': 19}, {'@': 20}, {'@': 21}, {'@': 22}, {'@': 23}, {'@': 24}, {'@': 25}, {'@': 26}, {'@': 27}, {'@': 28}, {'@': 29}, {'@': 30}], 'ignore': [], 'g_regex_flags': 0, 'use_bytes': False, 'lexer_type': 'contextual', '__type__': 'LexerConf'}, 'parser_conf': {'rules': [{'@': 31}, {'@': 32}, {'@': 33}, {'@': 34}, {'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}, {'@': 131}, {'@': 132}, {'@': 133}, {'@': 134}, {'@': 135}, {'@': 136}, {'@': 137}, {'@': 138}, {'@': 139}, {'@': 140}, {'@': 141}, {'@': 142}, {'@': 143}, {'@': 144}, {'@': 145}, {'@': 146}, {'@': 147}, {'@': 148}, {'@': 149}, {'@': 150}, {'@': 151}, {'@': 152}, {'@': 153}, {'@': 154}, {'@': 155}, {'@': 156}, {'@': 157}, {'@': 158}, {'@': 159}, {'@': 160}, {'@': 161}, {'@': 162}, {'@': 163}, {'@': 164}, {'@': 165}, {'@': 166}, {'@': 167}, {'@': 168}, {'@': 169}, {'@': 170}, {'@': 171}, {'@': 172}, {'@': 173}, {'@': 174}, {'@': 175}, {'@': 176}, {'@': 177}, {'@': 178}, {'@': 179}, {'@': 180}, {'@': 181}, {'@': 182}, {'@': 183}, {'@': 184}, {'@': 185}, {'@': 186}, {'@': 187}, {'@': 188}, {'@': 189}, {'@': 190}, {'@': 191}, {'@': 192}, {'@': 193}, {'@': 194}, {'@': 195}, {'@': 196}, {'@': 197}, {'@': 198}, {'@': 199}, {'@': 200}, {'@': 201}, {'@': 202}, {'@': 203}, {'@': 204}, {'@': 205}, {'@': 206}, {'@': 207}, {'@': 208}, {'@': 209}, {'@': 210}, {'@': 211}, {'@': 212}, {'@': 213}, {'@': 214}, {'@': 215}, {'@': 216}, {'@': 217}, {'@': 218}], 'start': ['start'], 'parser_type': 'lalr', '__type__': 'ParserConf'}, 'parser': {'tokens': {0: 'PHANTOMS', 1: 'SLASH', 2: 'BOX_NAME', 3: 'PERCENT', 4: 'BREAK', 5: 'CONSTRAINT_LPAREN', 6: 'NL', 7: 'MINUS', 8: 'INDENT', 9: '$END', 10: 'PLUS', 11: 'RBRACKET', 12: 'seq{constraint_target}', 13: 'constraint_target', 14: 'box_name', 15: 'COLON', 16: 'CONSTRAINT_LEG', 17: 'SP', 18: 'constraint_leg', 19: 'box_name_ref', 20: '__constraint_target_star_1', 21: 'COMMA', 22: 'leg_arrow', 23: 'LBRACKET', 24: 'LEG_ARROW', 25: 'entity_name_ref', 26: 'inheritance_parent', 27: 'comment', 28: 'assoc_name_def', 29: 'box_def_prefix', 30: 'assoc_clause', 31: 'constraint_clause', 32: 'entity_clause', 33: 'entity_name_def', 34: 'inheritance_clause', 35: 'phantoms', 36: 'clause', 37: '__ANON_1', 38: 'seq{inheritance_child}', 39: 'inheritance_child', 40: 'ATTR', 41: 'HASHTAG', 42: 'inheritance_name', 43: 'BACKSLASH', 44: 'INHERITANCE_NAME', 45: 'indent', 46: 'start', 47: 'line', 48: '__start_star_0', 49: 'break_', 50: 'NUMBER', 51: 'constraint_coords', 52: '_constraint_coord', 53: 'CONSTRAINT_RPAREN', 54: 'constraint_name', 55: 'CONSTRAINT_NAME', 56: '__seq{inheritance_child}_star_7', 57: 'note', 58: '__ANON_0', 59: 'leg_note', 60: 'INHERITANCE_ARROW', 61: 'inheritance_arrow', 62: 'MORETHAN', 63: 'ID_MARK', 64: 'attr', 65: 'assoc_attr', 66: 'typed_attr', 67: 'seq{assoc_attr}', 68: '_id_symbols', 69: 'entity_or_table_attr', 70: 'id_mark', 71: 'ID_GROUPS', 72: 'id_groups', 73: 'that_table', 74: 'foreign_reference', 75: 'this_table_attr', 76: 'seq{entity_or_table_attr}', 77: 'CARD', 78: 'card', 79: 'seq{typed_attr}', 80: 'constraint_note', 81: '_assoc_card', 82: 'card_prefix', 83: 'assoc_leg', 84: 'card_hidden', 85: '__seq{typed_attr}_star_6', 86: 'seq{assoc_leg}', 87: '__seq{constraint_target}_star_5', 88: '__seq{assoc_attr}_star_2', 89: 'that_table_attr', 90: '__seq{entity_or_table_attr}_star_4', 91: 'datatype', 92: '__seq{assoc_leg}_star_3'}, 'states': {0: {0: (1, {'@': 119}), 1: (1, {'@': 119}), 2: (1, {'@': 119}), 3: (1, {'@': 119}), 4: (1, {'@': 119}), 5: (1, {'@': 119}), 6: (1, {'@': 119}), 7: (1, {'@': 119}), 8: (1, {'@': 119}), 9: (1, {'@': 119}), 10: (1, {'@': 119})}, 1: {11: (0, 173)}, 2: {12: (0, 310), 13: (0, 241), 14: (0, 215), 15: (0, 117), 2: (0, 60), 16: (0, 237), 6: (0, 126), 17: (0, 221), 18: (0, 239), 19: (0, 224), 20: (0, 232)}, 3: {6: (1, {'@': 68}), 15: (1, {'@': 68}), 21: (1, {'@': 68})}, 4: {0: (1, {'@': 43}), 1: (1, {'@': 43}), 2: (1, {'@': 43}), 5: (1, {'@': 43}), 3: (1, {'@': 43}), 4: (1, {'@': 43}), 6: (1, {'@': 43}), 7: (1, {'@': 43}), 8: (1, {'@': 43}), 9: (1, {'@': 43}), 10: (1, {'@': 43})}, 5: {21: (1, {'@': 59}), 15: (1, {'@': 99})}, 6: {0: (1, {'@': 50}), 2: (1, {'@': 50}), 3: (1, {'@': 50}), 6: (1, {'@': 50}), 7: (1, {'@': 50}), 1: (1, {'@': 50}), 4: (1, {'@': 50}), 5: (1, {'@': 50}), 8: (1, {'@': 50}), 9: (1, {'@': 50}), 10: (1, {'@': 50})}, 7: {17: (0, 249), 22: (0, 93), 23: (0, 70), 24: (0, 362), 25: (0, 79), 2: (0, 60), 14: (0, 341)}, 8: {17: (0, 323), 26: (0, 123), 2: (0, 60), 25: (0, 246), 14: (0, 341)}, 9: {6: (1, {'@': 82}), 15: (1, {'@': 82}), 21: (1, {'@': 82})}, 10: {0: (1, {'@': 49}), 2: (1, {'@': 49}), 3: (1, {'@': 49}), 6: (1, {'@': 49}), 7: (1, {'@': 49}), 1: (1, {'@': 49}), 4: (1, {'@': 49}), 5: (1, {'@': 49}), 8: (1, {'@': 49}), 9: (1, {'@': 49}), 10: (1, {'@': 49})}, 11: {15: (0, 228), 23: (0, 251), 12: (0, 250), 13: (0, 241), 14: (0, 215), 2: (0, 60), 6: (0, 218), 19: (0, 224), 20: (0, 232), 16: (0, 237), 17: (0, 221), 18: (0, 239)}, 12: {5: (0, 42), 14: (0, 5), 1: (0, 21), 2: (0, 60), 27: (0, 273), 28: (0, 82), 0: (0, 86), 6: (0, 284), 10: (0, 19), 29: (0, 26), 30: (0, 10), 31: (0, 36), 3: (0, 13), 32: (0, 6), 33: (0, 53), 34: (0, 34), 7: (0, 160), 35: (0, 297), 36: (0, 4)}, 13: {37: (0, 262)}, 14: {0: (1, {'@': 182}), 1: (1, {'@': 182}), 2: (1, {'@': 182}), 5: (1, {'@': 182}), 3: (1, {'@': 182}), 4: (1, {'@': 182}), 6: (1, {'@': 182}), 7: (1, {'@': 182}), 8: (1, {'@': 182}), 9: (1, {'@': 182}), 10: (1, {'@': 182})}, 15: {2: (0, 60), 38: (0, 302), 39: (0, 47), 25: (0, 38), 14: (0, 341)}, 16: {0: (1, {'@': 202}), 1: (1, {'@': 202}), 2: (1, {'@': 202}), 5: (1, {'@': 202}), 3: (1, {'@': 202}), 4: (1, {'@': 202}), 6: (1, {'@': 202}), 7: (1, {'@': 202}), 8: (1, {'@': 202}), 9: (1, {'@': 202}), 10: (1, {'@': 202})}, 17: {0: (1, {'@': 113}), 1: (1, {'@': 113}), 2: (1, {'@': 113}), 3: (1, {'@': 113}), 4: (1, {'@': 113}), 5: (1, {'@': 113}), 6: (1, {'@': 113}), 7: (1, {'@': 113}), 8: (1, {'@': 113}), 9: (1, {'@': 113}), 10: (1, {'@': 113})}, 18: {0: (1, {'@': 167}), 1: (1, {'@': 167}), 2: (1, {'@': 167}), 3: (1, {'@': 167}), 4: (1, {'@': 167}), 5: (1, {'@': 167}), 6: (1, {'@': 167}), 7: (1, {'@': 167}), 8: (1, {'@': 167}), 9: (1, {'@': 167}), 10: (1, {'@': 167})}, 19: {2: (1, {'@': 36})}, 20: {40: (1, {'@': 104}), 6: (1, {'@': 104}), 41: (1, {'@': 104}), 21: (1, {'@': 104})}, 21: {42: (0, 293), 43: (0, 274), 44: (0, 279)}, 22: {6: (0, 69)}, 23: {6: (1, {'@': 64}), 15: (1, {'@': 64}), 21: (1, {'@': 64})}, 24: {5: (0, 42), 4: (0, 14), 1: (0, 21), 45: (0, 12), 27: (0, 30), 14: (0, 5), 2: (0, 60), 46: (0, 50), 28: (0, 82), 0: (0, 86), 47: (0, 16), 10: (0, 19), 29: (0, 26), 48: (0, 29), 30: (0, 10), 31: (0, 36), 3: (0, 13), 35: (0, 40), 49: (0, 67), 8: (0, 89), 36: (0, 46), 32: (0, 6), 33: (0, 53), 34: (0, 34), 7: (0, 160), 6: (0, 268), 9: (1, {'@': 40})}, 25: {38: (0, 158), 2: (0, 60), 39: (0, 47), 25: (0, 38), 14: (0, 341)}, 26: {14: (0, 5), 2: (0, 60), 33: (0, 143), 28: (0, 105)}, 27: {0: (1, {'@': 158}), 1: (1, {'@': 158}), 2: (1, {'@': 158}), 3: (1, {'@': 158}), 4: (1, {'@': 158}), 5: (1, {'@': 158}), 6: (1, {'@': 158}), 7: (1, {'@': 158}), 8: (1, {'@': 158}), 9: (1, {'@': 158}), 10: (1, {'@': 158})}, 28: {0: (1, {'@': 161}), 1: (1, {'@': 161}), 2: (1, {'@': 161}), 3: (1, {'@': 161}), 4: (1, {'@': 161}), 5: (1, {'@': 161}), 6: (1, {'@': 161}), 7: (1, {'@': 161}), 8: (1, {'@': 161}), 9: (1, {'@': 161}), 10: (1, {'@': 161})}, 29: {5: (0, 42), 14: (0, 5), 1: (0, 21), 45: (0, 12), 27: (0, 30), 2: (0, 60), 28: (0, 82), 0: (0, 86), 10: (0, 19), 49: (0, 94), 29: (0, 26), 30: (0, 10), 31: (0, 36), 3: (0, 13), 35: (0, 40), 47: (0, 96), 8: (0, 89), 36: (0, 46), 32: (0, 6), 33: (0, 53), 34: (0, 34), 7: (0, 160), 6: (0, 268), 4: (0, 14), 9: (1, {'@': 39})}, 30: {0: (1, {'@': 46}), 1: (1, {'@': 46}), 2: (1, {'@': 46}), 5: (1, {'@': 46}), 3: (1, {'@': 46}), 4: (1, {'@': 46}), 6: (1, {'@': 46}), 7: (1, {'@': 46}), 8: (1, {'@': 46}), 9: (1, {'@': 46}), 10: (1, {'@': 46})}, 31: {0: (1, {'@': 163}), 1: (1, {'@': 163}), 2: (1, {'@': 163}), 3: (1, {'@': 163}), 4: (1, {'@': 163}), 5: (1, {'@': 163}), 6: (1, {'@': 163}), 7: (1, {'@': 163}), 8: (1, {'@': 163}), 9: (1, {'@': 163}), 10: (1, {'@': 163})}, 32: {39: (0, 47), 17: (0, 288), 2: (0, 60), 25: (0, 38), 38: (0, 182), 14: (0, 341)}, 33: {6: (0, 84)}, 34: {0: (1, {'@': 52}), 2: (1, {'@': 52}), 3: (1, {'@': 52}), 6: (1, {'@': 52}), 7: (1, {'@': 52}), 1: (1, {'@': 52}), 4: (1, {'@': 52}), 5: (1, {'@': 52}), 8: (1, {'@': 52}), 9: (1, {'@': 52}), 10: (1, {'@': 52})}, 35: {0: (1, {'@': 166}), 1: (1, {'@': 166}), 2: (1, {'@': 166}), 3: (1, {'@': 166}), 4: (1, {'@': 166}), 5: (1, {'@': 166}), 6: (1, {'@': 166}), 7: (1, {'@': 166}), 8: (1, {'@': 166}), 9: (1, {'@': 166}), 10: (1, {'@': 166})}, 36: {0: (1, {'@': 51}), 2: (1, {'@': 51}), 3: (1, {'@': 51}), 6: (1, {'@': 51}), 7: (1, {'@': 51}), 1: (1, {'@': 51}), 4: (1, {'@': 51}), 5: (1, {'@': 51}), 8: (1, {'@': 51}), 9: (1, {'@': 51}), 10: (1, {'@': 51})}, 37: {0: (1, {'@': 155}), 1: (1, {'@': 155}), 2: (1, {'@': 155}), 3: (1, {'@': 155}), 4: (1, {'@': 155}), 5: (1, {'@': 155}), 6: (1, {'@': 155}), 7: (1, {'@': 155}), 8: (1, {'@': 155}), 9: (1, {'@': 155}), 10: (1, {'@': 155})}, 38: {6: (1, {'@': 176}), 15: (1, {'@': 176}), 21: (1, {'@': 176})}, 39: {15: (0, 255), 6: (0, 259)}, 40: {0: (1, {'@': 45}), 1: (1, {'@': 45}), 2: (1, {'@': 45}), 5: (1, {'@': 45}), 3: (1, {'@': 45}), 4: (1, {'@': 45}), 6: (1, {'@': 45}), 7: (1, {'@': 45}), 8: (1, {'@': 45}), 9: (1, {'@': 45}), 10: (1, {'@': 45})}, 41: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 299), 14: (0, 215), 52: (0, 217)}, 42: {53: (0, 11), 54: (0, 83), 55: (0, 290)}, 43: {6: (0, 109), 15: (0, 189)}, 44: {11: (0, 153)}, 45: {0: (1, {'@': 149}), 1: (1, {'@': 149}), 2: (1, {'@': 149}), 3: (1, {'@': 149}), 4: (1, {'@': 149}), 5: (1, {'@': 149}), 6: (1, {'@': 149}), 7: (1, {'@': 149}), 8: (1, {'@': 149}), 9: (1, {'@': 149}), 10: (1, {'@': 149})}, 46: {0: (1, {'@': 47}), 1: (1, {'@': 47}), 2: (1, {'@': 47}), 5: (1, {'@': 47}), 3: (1, {'@': 47}), 4: (1, {'@': 47}), 6: (1, {'@': 47}), 7: (1, {'@': 47}), 8: (1, {'@': 47}), 9: (1, {'@': 47}), 10: (1, {'@': 47})}, 47: {21: (0, 104), 56: (0, 154), 6: (1, {'@': 200}), 15: (1, {'@': 200})}, 48: {57: (0, 170), 58: (0, 118), 59: (0, 194), 11: (0, 176)}, 49: {17: (0, 278), 39: (0, 47), 38: (0, 181), 2: (0, 60), 25: (0, 38), 14: (0, 341)}, 50: {}, 51: {25: (0, 246), 26: (0, 364), 2: (0, 60), 14: (0, 341)}, 52: {0: (1, {'@': 147}), 1: (1, {'@': 147}), 2: (1, {'@': 147}), 3: (1, {'@': 147}), 4: (1, {'@': 147}), 5: (1, {'@': 147}), 6: (1, {'@': 147}), 7: (1, {'@': 147}), 8: (1, {'@': 147}), 9: (1, {'@': 147}), 10: (1, {'@': 147})}, 53: {15: (0, 120)}, 54: {0: (1, {'@': 56}), 1: (1, {'@': 56}), 2: (1, {'@': 56}), 3: (1, {'@': 56}), 4: (1, {'@': 56}), 5: (1, {'@': 56}), 6: (1, {'@': 56}), 7: (1, {'@': 56}), 8: (1, {'@': 56}), 9: (1, {'@': 56}), 10: (1, {'@': 56})}, 55: {6: (1, {'@': 216}), 21: (1, {'@': 216})}, 56: {60: (0, 136), 17: (0, 111), 61: (0, 165)}, 57: {2: (0, 60), 38: (0, 289), 39: (0, 47), 25: (0, 38), 14: (0, 341)}, 58: {11: (0, 195)}, 59: {2: (0, 60), 39: (0, 47), 25: (0, 38), 38: (0, 172), 14: (0, 341)}, 60: {6: (1, {'@': 179}), 15: (1, {'@': 179}), 21: (1, {'@': 179}), 17: (1, {'@': 179}), 60: (1, {'@': 179}), 62: (1, {'@': 179})}, 61: {63: (1, {'@': 188})}, 62: {6: (1, {'@': 217}), 15: (1, {'@': 217}), 21: (1, {'@': 217})}, 63: {6: (1, {'@': 69}), 15: (1, {'@': 69}), 21: (1, {'@': 69})}, 64: {0: (1, {'@': 145}), 1: (1, {'@': 145}), 2: (1, {'@': 145}), 3: (1, {'@': 145}), 4: (1, {'@': 145}), 5: (1, {'@': 145}), 6: (1, {'@': 145}), 7: (1, {'@': 145}), 8: (1, {'@': 145}), 9: (1, {'@': 145}), 10: (1, {'@': 145})}, 65: {6: (1, {'@': 80}), 15: (1, {'@': 80}), 21: (1, {'@': 80})}, 66: {0: (1, {'@': 143}), 1: (1, {'@': 143}), 2: (1, {'@': 143}), 3: (1, {'@': 143}), 4: (1, {'@': 143}), 5: (1, {'@': 143}), 6: (1, {'@': 143}), 7: (1, {'@': 143}), 8: (1, {'@': 143}), 9: (1, {'@': 143}), 10: (1, {'@': 143})}, 67: {0: (1, {'@': 201}), 1: (1, {'@': 201}), 2: (1, {'@': 201}), 5: (1, {'@': 201}), 3: (1, {'@': 201}), 4: (1, {'@': 201}), 6: (1, {'@': 201}), 7: (1, {'@': 201}), 8: (1, {'@': 201}), 9: (1, {'@': 201}), 10: (1, {'@': 201})}, 68: {40: (0, 305), 64: (0, 110), 65: (0, 261), 66: (0, 266), 63: (0, 282), 67: (0, 80), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 69: {0: (1, {'@': 159}), 1: (1, {'@': 159}), 2: (1, {'@': 159}), 3: (1, {'@': 159}), 4: (1, {'@': 159}), 5: (1, {'@': 159}), 6: (1, {'@': 159}), 7: (1, {'@': 159}), 8: (1, {'@': 159}), 9: (1, {'@': 159}), 10: (1, {'@': 159})}, 70: {57: (0, 170), 58: (0, 118), 11: (0, 148), 59: (0, 352)}, 71: {6: (1, {'@': 32}), 21: (1, {'@': 32})}, 72: {6: (0, 164), 15: (0, 190)}, 73: {40: (1, {'@': 105}), 6: (1, {'@': 105}), 41: (1, {'@': 105}), 21: (1, {'@': 105})}, 74: {40: (0, 305), 68: (0, 295), 69: (0, 309), 66: (0, 348), 70: (0, 73), 71: (0, 61), 64: (0, 110), 41: (0, 90), 63: (0, 395), 72: (0, 334), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 75: {6: (0, 343)}, 76: {11: (1, {'@': 35})}, 77: {6: (0, 66)}, 78: {0: (1, {'@': 170}), 1: (1, {'@': 170}), 2: (1, {'@': 170}), 3: (1, {'@': 170}), 4: (1, {'@': 170}), 5: (1, {'@': 170}), 6: (1, {'@': 170}), 7: (1, {'@': 170}), 8: (1, {'@': 170}), 9: (1, {'@': 170}), 10: (1, {'@': 170})}, 79: {6: (1, {'@': 71}), 15: (1, {'@': 71}), 21: (1, {'@': 71})}, 80: {6: (0, 275)}, 81: {15: (0, 257), 6: (0, 167)}, 82: {21: (0, 277)}, 83: {53: (0, 264)}, 84: {0: (1, {'@': 151}), 1: (1, {'@': 151}), 2: (1, {'@': 151}), 3: (1, {'@': 151}), 4: (1, {'@': 151}), 5: (1, {'@': 151}), 6: (1, {'@': 151}), 7: (1, {'@': 151}), 8: (1, {'@': 151}), 9: (1, {'@': 151}), 10: (1, {'@': 151})}, 85: {6: (0, 236), 15: (0, 270)}, 86: {0: (1, {'@': 181}), 2: (1, {'@': 181}), 3: (1, {'@': 181}), 6: (1, {'@': 181}), 7: (1, {'@': 181}), 1: (1, {'@': 181}), 4: (1, {'@': 181}), 5: (1, {'@': 181}), 8: (1, {'@': 181}), 9: (1, {'@': 181}), 10: (1, {'@': 181})}, 87: {11: (0, 390)}, 88: {2: (0, 60), 25: (0, 391), 73: (0, 357), 14: (0, 341)}, 89: {0: (1, {'@': 53}), 1: (1, {'@': 53}), 2: (1, {'@': 53}), 5: (1, {'@': 53}), 3: (1, {'@': 53}), 6: (1, {'@': 53}), 7: (1, {'@': 53}), 10: (1, {'@': 53})}, 90: {40: (0, 305), 74: (0, 300), 64: (0, 333), 75: (0, 349)}, 91: {15: (0, 335), 13: (0, 241), 14: (0, 215), 12: (0, 306), 2: (0, 60), 16: (0, 237), 6: (0, 345), 17: (0, 221), 18: (0, 239), 19: (0, 224), 20: (0, 232)}, 92: {6: (0, 28)}, 93: {23: (0, 48), 17: (0, 260), 25: (0, 258), 2: (0, 60), 14: (0, 341)}, 94: {0: (1, {'@': 203}), 1: (1, {'@': 203}), 2: (1, {'@': 203}), 5: (1, {'@': 203}), 3: (1, {'@': 203}), 4: (1, {'@': 203}), 6: (1, {'@': 203}), 7: (1, {'@': 203}), 8: (1, {'@': 203}), 9: (1, {'@': 203}), 10: (1, {'@': 203})}, 95: {15: (0, 328), 6: (0, 0)}, 96: {0: (1, {'@': 204}), 1: (1, {'@': 204}), 2: (1, {'@': 204}), 5: (1, {'@': 204}), 3: (1, {'@': 204}), 4: (1, {'@': 204}), 6: (1, {'@': 204}), 7: (1, {'@': 204}), 8: (1, {'@': 204}), 9: (1, {'@': 204}), 10: (1, {'@': 204})}, 97: {6: (1, {'@': 137}), 15: (1, {'@': 137}), 21: (1, {'@': 137})}, 98: {0: (1, {'@': 160}), 1: (1, {'@': 160}), 2: (1, {'@': 160}), 3: (1, {'@': 160}), 4: (1, {'@': 160}), 5: (1, {'@': 160}), 6: (1, {'@': 160}), 7: (1, {'@': 160}), 8: (1, {'@': 160}), 9: (1, {'@': 160}), 10: (1, {'@': 160})}, 99: {60: (0, 136), 61: (0, 32)}, 100: {0: (1, {'@': 169}), 1: (1, {'@': 169}), 2: (1, {'@': 169}), 3: (1, {'@': 169}), 4: (1, {'@': 169}), 5: (1, {'@': 169}), 6: (1, {'@': 169}), 7: (1, {'@': 169}), 8: (1, {'@': 169}), 9: (1, {'@': 169}), 10: (1, {'@': 169})}, 101: {2: (0, 60), 38: (0, 81), 39: (0, 47), 25: (0, 38), 14: (0, 341)}, 102: {0: (1, {'@': 153}), 1: (1, {'@': 153}), 2: (1, {'@': 153}), 3: (1, {'@': 153}), 4: (1, {'@': 153}), 5: (1, {'@': 153}), 6: (1, {'@': 153}), 7: (1, {'@': 153}), 8: (1, {'@': 153}), 9: (1, {'@': 153}), 10: (1, {'@': 153})}, 103: {6: (1, {'@': 140})}, 104: {2: (0, 60), 39: (0, 62), 25: (0, 38), 14: (0, 341)}, 105: {21: (0, 234)}, 106: {0: (1, {'@': 171}), 1: (1, {'@': 171}), 2: (1, {'@': 171}), 3: (1, {'@': 171}), 4: (1, {'@': 171}), 5: (1, {'@': 171}), 6: (1, {'@': 171}), 7: (1, {'@': 171}), 8: (1, {'@': 171}), 9: (1, {'@': 171}), 10: (1, {'@': 171})}, 107: {6: (1, {'@': 101}), 21: (1, {'@': 101})}, 108: {0: (1, {'@': 152}), 1: (1, {'@': 152}), 2: (1, {'@': 152}), 3: (1, {'@': 152}), 4: (1, {'@': 152}), 5: (1, {'@': 152}), 6: (1, {'@': 152}), 7: (1, {'@': 152}), 8: (1, {'@': 152}), 9: (1, {'@': 152}), 10: (1, {'@': 152})}, 109: {0: (1, {'@': 174}), 1: (1, {'@': 174}), 2: (1, {'@': 174}), 3: (1, {'@': 174}), 4: (1, {'@': 174}), 5: (1, {'@': 174}), 6: (1, {'@': 174}), 7: (1, {'@': 174}), 8: (1, {'@': 174}), 9: (1, {'@': 174}), 10: (1, {'@': 174})}, 110: {23: (0, 319), 6: (1, {'@': 33}), 21: (1, {'@': 33})}, 111: {61: (0, 49), 60: (0, 136)}, 112: {6: (1, {'@': 70}), 15: (1, {'@': 70}), 21: (1, {'@': 70})}, 113: {40: (0, 305), 64: (0, 110), 66: (0, 55), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 114: {17: (0, 330), 2: (0, 60), 14: (0, 215), 19: (0, 381)}, 115: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 119), 14: (0, 215), 52: (0, 217)}, 116: {0: (1, {'@': 110}), 1: (1, {'@': 110}), 2: (1, {'@': 110}), 3: (1, {'@': 110}), 4: (1, {'@': 110}), 5: (1, {'@': 110}), 6: (1, {'@': 110}), 7: (1, {'@': 110}), 8: (1, {'@': 110}), 9: (1, {'@': 110}), 10: (1, {'@': 110})}, 117: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 370), 14: (0, 215), 52: (0, 217)}, 118: {11: (1, {'@': 38})}, 119: {6: (0, 192)}, 120: {68: (0, 295), 76: (0, 269), 70: (0, 73), 71: (0, 61), 64: (0, 110), 41: (0, 90), 69: (0, 318), 72: (0, 334), 40: (0, 305), 6: (0, 332), 66: (0, 348), 63: (0, 395), 21: (1, {'@': 34})}, 121: {6: (0, 31)}, 122: {14: (0, 215), 13: (0, 342), 2: (0, 60), 17: (0, 221), 16: (0, 237), 18: (0, 239), 19: (0, 224), 20: (0, 232)}, 123: {60: (0, 136), 17: (0, 353), 61: (0, 287)}, 124: {2: (0, 60), 39: (0, 47), 25: (0, 38), 38: (0, 219), 14: (0, 341)}, 125: {24: (1, {'@': 85}), 23: (1, {'@': 85}), 2: (1, {'@': 85}), 17: (1, {'@': 85})}, 126: {0: (1, {'@': 117}), 1: (1, {'@': 117}), 2: (1, {'@': 117}), 3: (1, {'@': 117}), 4: (1, {'@': 117}), 5: (1, {'@': 117}), 6: (1, {'@': 117}), 7: (1, {'@': 117}), 8: (1, {'@': 117}), 9: (1, {'@': 117}), 10: (1, {'@': 117})}, 127: {0: (1, {'@': 97}), 1: (1, {'@': 97}), 2: (1, {'@': 97}), 3: (1, {'@': 97}), 4: (1, {'@': 97}), 5: (1, {'@': 97}), 6: (1, {'@': 97}), 7: (1, {'@': 97}), 8: (1, {'@': 97}), 9: (1, {'@': 97}), 10: (1, {'@': 97})}, 128: {15: (0, 253), 6: (0, 35)}, 129: {0: (1, {'@': 144}), 1: (1, {'@': 144}), 2: (1, {'@': 144}), 3: (1, {'@': 144}), 4: (1, {'@': 144}), 5: (1, {'@': 144}), 6: (1, {'@': 144}), 7: (1, {'@': 144}), 8: (1, {'@': 144}), 9: (1, {'@': 144}), 10: (1, {'@': 144})}, 130: {6: (1, {'@': 79}), 15: (1, {'@': 79}), 21: (1, {'@': 79})}, 131: {77: (0, 356), 78: (0, 280)}, 132: {40: (0, 305), 66: (0, 233), 79: (0, 22), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 133: {21: (0, 338), 6: (1, {'@': 195}), 15: (1, {'@': 195})}, 134: {6: (1, {'@': 215}), 21: (1, {'@': 215})}, 135: {6: (1, {'@': 136}), 15: (1, {'@': 136}), 21: (1, {'@': 136})}, 136: {2: (1, {'@': 186}), 17: (1, {'@': 186})}, 137: {6: (0, 18)}, 138: {6: (0, 37)}, 139: {11: (0, 2), 80: (0, 1), 57: (0, 389), 58: (0, 118)}, 140: {57: (0, 170), 59: (0, 44), 58: (0, 118), 11: (0, 296)}, 141: {11: (0, 142)}, 142: {2: (0, 60), 25: (0, 238), 14: (0, 341)}, 143: {15: (0, 243)}, 144: {40: (0, 305), 79: (0, 77), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 145: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 185), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 146: {6: (0, 64)}, 147: {0: (1, {'@': 130}), 1: (1, {'@': 130}), 2: (1, {'@': 130}), 3: (1, {'@': 130}), 4: (1, {'@': 130}), 5: (1, {'@': 130}), 6: (1, {'@': 130}), 7: (1, {'@': 130}), 8: (1, {'@': 130}), 9: (1, {'@': 130}), 10: (1, {'@': 130})}, 148: {2: (0, 60), 25: (0, 112), 14: (0, 341)}, 149: {15: (0, 145), 6: (0, 27)}, 150: {6: (0, 52)}, 151: {17: (0, 15), 39: (0, 47), 2: (0, 60), 25: (0, 38), 38: (0, 43), 14: (0, 341)}, 152: {0: (1, {'@': 121}), 1: (1, {'@': 121}), 2: (1, {'@': 121}), 3: (1, {'@': 121}), 4: (1, {'@': 121}), 5: (1, {'@': 121}), 6: (1, {'@': 121}), 7: (1, {'@': 121}), 8: (1, {'@': 121}), 9: (1, {'@': 121}), 10: (1, {'@': 121})}, 153: {2: (0, 60), 25: (0, 247), 14: (0, 341)}, 154: {21: (0, 248), 6: (1, {'@': 199}), 15: (1, {'@': 199})}, 155: {6: (1, {'@': 77}), 15: (1, {'@': 77}), 21: (1, {'@': 77})}, 156: {6: (1, {'@': 218}), 15: (1, {'@': 218}), 21: (1, {'@': 218})}, 157: {2: (0, 60), 14: (0, 341), 25: (0, 9)}, 158: {6: (0, 98), 15: (0, 132)}, 159: {50: (0, 312), 19: (0, 325), 2: (0, 60), 14: (0, 215), 52: (0, 217), 51: (0, 359)}, 160: {2: (1, {'@': 37})}, 161: {21: (0, 292), 6: (1, {'@': 191}), 15: (1, {'@': 191})}, 162: {6: (1, {'@': 214}), 15: (1, {'@': 214}), 21: (1, {'@': 214})}, 163: {39: (0, 47), 38: (0, 265), 17: (0, 59), 2: (0, 60), 25: (0, 38), 14: (0, 341)}, 164: {0: (1, {'@': 162}), 1: (1, {'@': 162}), 2: (1, {'@': 162}), 3: (1, {'@': 162}), 4: (1, {'@': 162}), 5: (1, {'@': 162}), 6: (1, {'@': 162}), 7: (1, {'@': 162}), 8: (1, {'@': 162}), 9: (1, {'@': 162}), 10: (1, {'@': 162})}, 165: {17: (0, 57), 39: (0, 47), 2: (0, 60), 25: (0, 38), 14: (0, 341), 38: (0, 85)}, 166: {0: (1, {'@': 127}), 1: (1, {'@': 127}), 2: (1, {'@': 127}), 3: (1, {'@': 127}), 4: (1, {'@': 127}), 5: (1, {'@': 127}), 6: (1, {'@': 127}), 7: (1, {'@': 127}), 8: (1, {'@': 127}), 9: (1, {'@': 127}), 10: (1, {'@': 127})}, 167: {0: (1, {'@': 156}), 1: (1, {'@': 156}), 2: (1, {'@': 156}), 3: (1, {'@': 156}), 4: (1, {'@': 156}), 5: (1, {'@': 156}), 6: (1, {'@': 156}), 7: (1, {'@': 156}), 8: (1, {'@': 156}), 9: (1, {'@': 156}), 10: (1, {'@': 156})}, 168: {0: (1, {'@': 172}), 1: (1, {'@': 172}), 2: (1, {'@': 172}), 3: (1, {'@': 172}), 4: (1, {'@': 172}), 5: (1, {'@': 172}), 6: (1, {'@': 172}), 7: (1, {'@': 172}), 8: (1, {'@': 172}), 9: (1, {'@': 172}), 10: (1, {'@': 172})}, 169: {81: (0, 7), 82: (0, 360), 2: (0, 60), 1: (0, 331), 17: (0, 374), 22: (0, 315), 7: (0, 347), 83: (0, 276), 84: (0, 368), 77: (0, 356), 24: (0, 362), 23: (0, 369), 78: (0, 337), 25: (0, 386), 14: (0, 341), 63: (0, 327)}, 170: {11: (1, {'@': 92})}, 171: {15: (0, 303), 6: (0, 313)}, 172: {15: (0, 366), 6: (0, 108)}, 173: {12: (0, 39), 13: (0, 241), 14: (0, 215), 15: (0, 41), 2: (0, 60), 6: (0, 17), 16: (0, 237), 17: (0, 221), 18: (0, 239), 19: (0, 224), 20: (0, 232)}, 174: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 324), 14: (0, 215), 52: (0, 217)}, 175: {2: (0, 60), 23: (0, 256), 14: (0, 341), 25: (0, 285)}, 176: {2: (0, 60), 14: (0, 341), 25: (0, 23)}, 177: {59: (0, 58), 57: (0, 170), 58: (0, 118), 11: (0, 294)}, 178: {39: (0, 47), 17: (0, 25), 38: (0, 72), 2: (0, 60), 25: (0, 38), 14: (0, 341)}, 179: {2: (0, 60), 14: (0, 341), 25: (0, 203)}, 180: {6: (1, {'@': 211}), 21: (1, {'@': 211})}, 181: {15: (0, 212), 6: (0, 210)}, 182: {6: (0, 78), 15: (0, 214)}, 183: {0: (1, {'@': 125}), 1: (1, {'@': 125}), 2: (1, {'@': 125}), 3: (1, {'@': 125}), 4: (1, {'@': 125}), 5: (1, {'@': 125}), 6: (1, {'@': 125}), 7: (1, {'@': 125}), 8: (1, {'@': 125}), 9: (1, {'@': 125}), 10: (1, {'@': 125})}, 184: {6: (1, {'@': 73}), 15: (1, {'@': 73}), 21: (1, {'@': 73})}, 185: {6: (0, 206)}, 186: {0: (1, {'@': 154}), 1: (1, {'@': 154}), 2: (1, {'@': 154}), 3: (1, {'@': 154}), 4: (1, {'@': 154}), 5: (1, {'@': 154}), 6: (1, {'@': 154}), 7: (1, {'@': 154}), 8: (1, {'@': 154}), 9: (1, {'@': 154}), 10: (1, {'@': 154})}, 187: {6: (1, {'@': 100}), 21: (1, {'@': 100})}, 188: {57: (0, 170), 59: (0, 141), 58: (0, 118), 11: (0, 179)}, 189: {40: (0, 305), 79: (0, 245), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 190: {40: (0, 305), 79: (0, 92), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 191: {2: (0, 60), 14: (0, 341), 25: (0, 63)}, 192: {0: (1, {'@': 120}), 1: (1, {'@': 120}), 2: (1, {'@': 120}), 3: (1, {'@': 120}), 4: (1, {'@': 120}), 5: (1, {'@': 120}), 6: (1, {'@': 120}), 7: (1, {'@': 120}), 8: (1, {'@': 120}), 9: (1, {'@': 120}), 10: (1, {'@': 120})}, 193: {6: (1, {'@': 60}), 15: (1, {'@': 60}), 21: (1, {'@': 60})}, 194: {11: (0, 227)}, 195: {2: (0, 60), 25: (0, 220), 14: (0, 341)}, 196: {0: (1, {'@': 58}), 1: (1, {'@': 58}), 2: (1, {'@': 58}), 3: (1, {'@': 58}), 4: (1, {'@': 58}), 5: (1, {'@': 58}), 6: (1, {'@': 58}), 7: (1, {'@': 58}), 8: (1, {'@': 58}), 9: (1, {'@': 58}), 10: (1, {'@': 58})}, 197: {6: (1, {'@': 72}), 15: (1, {'@': 72}), 21: (1, {'@': 72})}, 198: {6: (1, {'@': 108}), 21: (1, {'@': 108})}, 199: {0: (1, {'@': 114}), 1: (1, {'@': 114}), 2: (1, {'@': 114}), 3: (1, {'@': 114}), 4: (1, {'@': 114}), 5: (1, {'@': 114}), 6: (1, {'@': 114}), 7: (1, {'@': 114}), 8: (1, {'@': 114}), 9: (1, {'@': 114}), 10: (1, {'@': 114})}, 200: {0: (1, {'@': 122}), 1: (1, {'@': 122}), 2: (1, {'@': 122}), 3: (1, {'@': 122}), 4: (1, {'@': 122}), 5: (1, {'@': 122}), 6: (1, {'@': 122}), 7: (1, {'@': 122}), 8: (1, {'@': 122}), 9: (1, {'@': 122}), 10: (1, {'@': 122})}, 201: {6: (0, 45)}, 202: {6: (1, {'@': 208}), 21: (1, {'@': 208})}, 203: {6: (1, {'@': 67}), 15: (1, {'@': 67}), 21: (1, {'@': 67})}, 204: {6: (1, {'@': 106}), 21: (1, {'@': 106})}, 205: {6: (0, 102)}, 206: {0: (1, {'@': 157}), 1: (1, {'@': 157}), 2: (1, {'@': 157}), 3: (1, {'@': 157}), 4: (1, {'@': 157}), 5: (1, {'@': 157}), 6: (1, {'@': 157}), 7: (1, {'@': 157}), 8: (1, {'@': 157}), 9: (1, {'@': 157}), 10: (1, {'@': 157})}, 207: {0: (1, {'@': 112}), 1: (1, {'@': 112}), 2: (1, {'@': 112}), 3: (1, {'@': 112}), 4: (1, {'@': 112}), 5: (1, {'@': 112}), 6: (1, {'@': 112}), 7: (1, {'@': 112}), 8: (1, {'@': 112}), 9: (1, {'@': 112}), 10: (1, {'@': 112})}, 208: {6: (0, 129), 15: (0, 144)}, 209: {39: (0, 47), 38: (0, 128), 2: (0, 60), 25: (0, 38), 17: (0, 124), 14: (0, 341)}, 210: {0: (1, {'@': 146}), 1: (1, {'@': 146}), 2: (1, {'@': 146}), 3: (1, {'@': 146}), 4: (1, {'@': 146}), 5: (1, {'@': 146}), 6: (1, {'@': 146}), 7: (1, {'@': 146}), 8: (1, {'@': 146}), 9: (1, {'@': 146}), 10: (1, {'@': 146})}, 211: {6: (0, 116)}, 212: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 146), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 213: {0: (1, {'@': 148}), 1: (1, {'@': 148}), 2: (1, {'@': 148}), 3: (1, {'@': 148}), 4: (1, {'@': 148}), 5: (1, {'@': 148}), 6: (1, {'@': 148}), 7: (1, {'@': 148}), 8: (1, {'@': 148}), 9: (1, {'@': 148}), 10: (1, {'@': 148})}, 214: {40: (0, 305), 79: (0, 326), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 215: {6: (1, {'@': 139}), 15: (1, {'@': 139}), 21: (1, {'@': 139})}, 216: {25: (0, 387), 2: (0, 60), 14: (0, 341)}, 217: {21: (0, 316)}, 218: {0: (1, {'@': 133}), 1: (1, {'@': 133}), 2: (1, {'@': 133}), 3: (1, {'@': 133}), 4: (1, {'@': 133}), 5: (1, {'@': 133}), 6: (1, {'@': 133}), 7: (1, {'@': 133}), 8: (1, {'@': 133}), 9: (1, {'@': 133}), 10: (1, {'@': 133})}, 219: {6: (0, 244), 15: (0, 392)}, 220: {6: (1, {'@': 75}), 15: (1, {'@': 75}), 21: (1, {'@': 75})}, 221: {2: (1, {'@': 205}), 17: (1, {'@': 205})}, 222: {40: (0, 305), 79: (0, 371), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 223: {60: (0, 136), 17: (0, 99), 61: (0, 151)}, 224: {6: (1, {'@': 138}), 15: (1, {'@': 138}), 21: (1, {'@': 138})}, 225: {24: (1, {'@': 86}), 23: (1, {'@': 86}), 2: (1, {'@': 86}), 17: (1, {'@': 86})}, 226: {0: (1, {'@': 168}), 1: (1, {'@': 168}), 2: (1, {'@': 168}), 3: (1, {'@': 168}), 4: (1, {'@': 168}), 5: (1, {'@': 168}), 6: (1, {'@': 168}), 7: (1, {'@': 168}), 8: (1, {'@': 168}), 9: (1, {'@': 168}), 10: (1, {'@': 168})}, 227: {2: (0, 60), 25: (0, 304), 14: (0, 341)}, 228: {50: (0, 312), 19: (0, 325), 2: (0, 60), 14: (0, 215), 52: (0, 217), 51: (0, 384)}, 229: {0: (1, {'@': 55}), 1: (1, {'@': 55}), 2: (1, {'@': 55}), 3: (1, {'@': 55}), 4: (1, {'@': 55}), 5: (1, {'@': 55}), 6: (1, {'@': 55}), 7: (1, {'@': 55}), 8: (1, {'@': 55}), 9: (1, {'@': 55}), 10: (1, {'@': 55})}, 230: {6: (0, 226), 15: (0, 367)}, 231: {0: (1, {'@': 124}), 1: (1, {'@': 124}), 2: (1, {'@': 124}), 3: (1, {'@': 124}), 4: (1, {'@': 124}), 5: (1, {'@': 124}), 6: (1, {'@': 124}), 7: (1, {'@': 124}), 8: (1, {'@': 124}), 9: (1, {'@': 124}), 10: (1, {'@': 124})}, 232: {17: (0, 330), 2: (0, 60), 14: (0, 215), 19: (0, 97)}, 233: {21: (0, 383), 85: (0, 344), 6: (1, {'@': 198})}, 234: {81: (0, 7), 82: (0, 360), 2: (0, 60), 1: (0, 331), 17: (0, 374), 22: (0, 315), 7: (0, 347), 84: (0, 368), 77: (0, 356), 24: (0, 362), 23: (0, 369), 86: (0, 380), 83: (0, 378), 78: (0, 337), 25: (0, 386), 14: (0, 341), 63: (0, 327)}, 235: {11: (0, 301)}, 236: {0: (1, {'@': 150}), 1: (1, {'@': 150}), 2: (1, {'@': 150}), 3: (1, {'@': 150}), 4: (1, {'@': 150}), 5: (1, {'@': 150}), 6: (1, {'@': 150}), 7: (1, {'@': 150}), 8: (1, {'@': 150}), 9: (1, {'@': 150}), 10: (1, {'@': 150})}, 237: {2: (1, {'@': 177}), 17: (1, {'@': 177})}, 238: {6: (1, {'@': 66}), 15: (1, {'@': 66}), 21: (1, {'@': 66})}, 239: {2: (0, 60), 20: (0, 114), 17: (0, 221), 14: (0, 215), 19: (0, 135)}, 240: {2: (0, 60), 25: (0, 197), 14: (0, 341)}, 241: {87: (0, 133), 21: (0, 122), 6: (1, {'@': 196}), 15: (1, {'@': 196})}, 242: {40: (0, 305), 65: (0, 202), 64: (0, 110), 66: (0, 266), 63: (0, 282), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 243: {68: (0, 295), 70: (0, 73), 71: (0, 61), 64: (0, 110), 41: (0, 90), 69: (0, 318), 72: (0, 334), 40: (0, 305), 6: (0, 320), 66: (0, 348), 76: (0, 373), 63: (0, 395), 21: (1, {'@': 34})}, 244: {0: (1, {'@': 164}), 1: (1, {'@': 164}), 2: (1, {'@': 164}), 3: (1, {'@': 164}), 4: (1, {'@': 164}), 5: (1, {'@': 164}), 6: (1, {'@': 164}), 7: (1, {'@': 164}), 8: (1, {'@': 164}), 9: (1, {'@': 164}), 10: (1, {'@': 164})}, 245: {6: (0, 317)}, 246: {17: (1, {'@': 175}), 60: (1, {'@': 175})}, 247: {6: (1, {'@': 78}), 15: (1, {'@': 78}), 21: (1, {'@': 78})}, 248: {2: (0, 60), 25: (0, 38), 14: (0, 341), 39: (0, 156)}, 249: {2: (0, 60), 23: (0, 188), 14: (0, 341), 25: (0, 3)}, 250: {15: (0, 308), 6: (0, 351)}, 251: {80: (0, 358), 57: (0, 389), 11: (0, 91), 58: (0, 118)}, 252: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 205), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 253: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 354), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 254: {0: (1, {'@': 116}), 1: (1, {'@': 116}), 2: (1, {'@': 116}), 3: (1, {'@': 116}), 4: (1, {'@': 116}), 5: (1, {'@': 116}), 6: (1, {'@': 116}), 7: (1, {'@': 116}), 8: (1, {'@': 116}), 9: (1, {'@': 116}), 10: (1, {'@': 116})}, 255: {50: (0, 312), 19: (0, 325), 51: (0, 211), 2: (0, 60), 14: (0, 215), 52: (0, 217)}, 256: {57: (0, 170), 59: (0, 340), 58: (0, 118), 11: (0, 385)}, 257: {40: (0, 305), 79: (0, 138), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 258: {6: (1, {'@': 65}), 15: (1, {'@': 65}), 21: (1, {'@': 65})}, 259: {0: (1, {'@': 111}), 1: (1, {'@': 111}), 2: (1, {'@': 111}), 3: (1, {'@': 111}), 4: (1, {'@': 111}), 5: (1, {'@': 111}), 6: (1, {'@': 111}), 7: (1, {'@': 111}), 8: (1, {'@': 111}), 9: (1, {'@': 111}), 10: (1, {'@': 111})}, 260: {23: (0, 379), 2: (0, 60), 25: (0, 322), 14: (0, 341)}, 261: {88: (0, 311), 21: (0, 329), 6: (1, {'@': 190})}, 262: {0: (1, {'@': 54}), 2: (1, {'@': 54}), 3: (1, {'@': 54}), 6: (1, {'@': 54}), 7: (1, {'@': 54}), 1: (1, {'@': 54}), 4: (1, {'@': 54}), 5: (1, {'@': 54}), 8: (1, {'@': 54}), 9: (1, {'@': 54}), 10: (1, {'@': 54})}, 263: {6: (1, {'@': 207}), 21: (1, {'@': 207})}, 264: {23: (0, 139), 13: (0, 241), 12: (0, 95), 14: (0, 215), 2: (0, 60), 19: (0, 224), 20: (0, 232), 6: (0, 152), 16: (0, 237), 17: (0, 221), 18: (0, 239), 15: (0, 115)}, 265: {15: (0, 252), 6: (0, 186)}, 266: {6: (1, {'@': 94}), 21: (1, {'@': 94})}, 267: {40: (0, 305), 67: (0, 394), 64: (0, 110), 65: (0, 261), 66: (0, 266), 63: (0, 282), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 268: {0: (1, {'@': 48}), 1: (1, {'@': 48}), 2: (1, {'@': 48}), 5: (1, {'@': 48}), 3: (1, {'@': 48}), 4: (1, {'@': 48}), 6: (1, {'@': 48}), 7: (1, {'@': 48}), 8: (1, {'@': 48}), 9: (1, {'@': 48}), 10: (1, {'@': 48})}, 269: {6: (0, 127)}, 270: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 201), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 271: {6: (0, 363)}, 272: {6: (0, 199)}, 273: {0: (1, {'@': 42}), 1: (1, {'@': 42}), 2: (1, {'@': 42}), 5: (1, {'@': 42}), 3: (1, {'@': 42}), 4: (1, {'@': 42}), 6: (1, {'@': 42}), 7: (1, {'@': 42}), 8: (1, {'@': 42}), 9: (1, {'@': 42}), 10: (1, {'@': 42})}, 274: {17: (0, 51), 26: (0, 223), 2: (0, 60), 25: (0, 246), 14: (0, 341)}, 275: {0: (1, {'@': 57}), 1: (1, {'@': 57}), 2: (1, {'@': 57}), 3: (1, {'@': 57}), 4: (1, {'@': 57}), 5: (1, {'@': 57}), 6: (1, {'@': 57}), 7: (1, {'@': 57}), 8: (1, {'@': 57}), 9: (1, {'@': 57}), 10: (1, {'@': 57})}, 276: {6: (1, {'@': 209}), 15: (1, {'@': 209}), 21: (1, {'@': 209})}, 277: {81: (0, 7), 82: (0, 360), 2: (0, 60), 1: (0, 331), 17: (0, 374), 22: (0, 315), 7: (0, 347), 84: (0, 368), 77: (0, 356), 24: (0, 362), 23: (0, 369), 83: (0, 378), 78: (0, 337), 25: (0, 386), 86: (0, 355), 14: (0, 341), 63: (0, 327)}, 278: {2: (0, 60), 39: (0, 47), 25: (0, 38), 14: (0, 341), 38: (0, 208)}, 279: {43: (1, {'@': 183})}, 280: {24: (1, {'@': 84}), 23: (1, {'@': 84}), 2: (1, {'@': 84}), 17: (1, {'@': 84})}, 281: {6: (0, 200)}, 282: {40: (0, 305), 64: (0, 110), 66: (0, 377), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 283: {89: (0, 204), 64: (0, 198), 40: (0, 305)}, 284: {0: (1, {'@': 44}), 1: (1, {'@': 44}), 2: (1, {'@': 44}), 5: (1, {'@': 44}), 3: (1, {'@': 44}), 4: (1, {'@': 44}), 6: (1, {'@': 44}), 7: (1, {'@': 44}), 8: (1, {'@': 44}), 9: (1, {'@': 44}), 10: (1, {'@': 44})}, 285: {6: (1, {'@': 74}), 15: (1, {'@': 74}), 21: (1, {'@': 74})}, 286: {0: (1, {'@': 126}), 1: (1, {'@': 126}), 2: (1, {'@': 126}), 3: (1, {'@': 126}), 4: (1, {'@': 126}), 5: (1, {'@': 126}), 6: (1, {'@': 126}), 7: (1, {'@': 126}), 8: (1, {'@': 126}), 9: (1, {'@': 126}), 10: (1, {'@': 126})}, 287: {17: (0, 101), 39: (0, 47), 38: (0, 149), 2: (0, 60), 25: (0, 38), 14: (0, 341)}, 288: {2: (0, 60), 38: (0, 230), 39: (0, 47), 25: (0, 38), 14: (0, 341)}, 289: {15: (0, 350), 6: (0, 213)}, 290: {53: (1, {'@': 184})}, 291: {11: (0, 298)}, 292: {81: (0, 7), 82: (0, 360), 2: (0, 60), 1: (0, 331), 17: (0, 374), 22: (0, 315), 7: (0, 347), 84: (0, 368), 77: (0, 356), 24: (0, 362), 23: (0, 369), 83: (0, 307), 78: (0, 337), 25: (0, 386), 14: (0, 341), 63: (0, 327)}, 293: {43: (0, 8)}, 294: {25: (0, 375), 2: (0, 60), 14: (0, 341)}, 295: {40: (0, 305), 64: (0, 110), 66: (0, 187), 41: (0, 393), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 296: {2: (0, 60), 14: (0, 341), 25: (0, 130)}, 297: {0: (1, {'@': 41}), 1: (1, {'@': 41}), 2: (1, {'@': 41}), 5: (1, {'@': 41}), 3: (1, {'@': 41}), 4: (1, {'@': 41}), 6: (1, {'@': 41}), 7: (1, {'@': 41}), 8: (1, {'@': 41}), 9: (1, {'@': 41}), 10: (1, {'@': 41})}, 298: {2: (0, 60), 25: (0, 336), 14: (0, 341)}, 299: {6: (0, 207)}, 300: {6: (1, {'@': 103}), 21: (1, {'@': 103})}, 301: {2: (0, 60), 25: (0, 193), 14: (0, 341)}, 302: {6: (0, 168), 15: (0, 222)}, 303: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 281), 14: (0, 215), 52: (0, 217)}, 304: {6: (1, {'@': 63}), 15: (1, {'@': 63}), 21: (1, {'@': 63})}, 305: {6: (1, {'@': 185}), 23: (1, {'@': 185}), 21: (1, {'@': 185}), 62: (1, {'@': 185})}, 306: {15: (0, 174), 6: (0, 166)}, 307: {6: (1, {'@': 210}), 15: (1, {'@': 210}), 21: (1, {'@': 210})}, 308: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 346), 14: (0, 215), 52: (0, 217)}, 309: {6: (1, {'@': 212}), 21: (1, {'@': 212})}, 310: {6: (0, 321), 15: (0, 382)}, 311: {21: (0, 242), 6: (1, {'@': 189})}, 312: {21: (1, {'@': 141}), 6: (1, {'@': 141})}, 313: {0: (1, {'@': 123}), 1: (1, {'@': 123}), 2: (1, {'@': 123}), 3: (1, {'@': 123}), 4: (1, {'@': 123}), 5: (1, {'@': 123}), 6: (1, {'@': 123}), 7: (1, {'@': 123}), 8: (1, {'@': 123}), 9: (1, {'@': 123}), 10: (1, {'@': 123})}, 314: {13: (0, 241), 6: (0, 183), 14: (0, 215), 15: (0, 159), 12: (0, 171), 2: (0, 60), 16: (0, 237), 17: (0, 221), 18: (0, 239), 19: (0, 224), 20: (0, 232)}, 315: {25: (0, 155), 17: (0, 175), 2: (0, 60), 23: (0, 177), 14: (0, 341)}, 316: {50: (0, 312), 19: (0, 325), 2: (0, 60), 52: (0, 103), 14: (0, 215)}, 317: {0: (1, {'@': 173}), 1: (1, {'@': 173}), 2: (1, {'@': 173}), 3: (1, {'@': 173}), 4: (1, {'@': 173}), 5: (1, {'@': 173}), 6: (1, {'@': 173}), 7: (1, {'@': 173}), 8: (1, {'@': 173}), 9: (1, {'@': 173}), 10: (1, {'@': 173})}, 318: {90: (0, 388), 21: (0, 339), 6: (1, {'@': 194})}, 319: {91: (0, 87), 57: (0, 76), 58: (0, 118), 11: (0, 71)}, 320: {0: (1, {'@': 96}), 1: (1, {'@': 96}), 2: (1, {'@': 96}), 3: (1, {'@': 96}), 4: (1, {'@': 96}), 5: (1, {'@': 96}), 6: (1, {'@': 96}), 7: (1, {'@': 96}), 8: (1, {'@': 96}), 9: (1, {'@': 96}), 10: (1, {'@': 96})}, 321: {0: (1, {'@': 115}), 1: (1, {'@': 115}), 2: (1, {'@': 115}), 3: (1, {'@': 115}), 4: (1, {'@': 115}), 5: (1, {'@': 115}), 6: (1, {'@': 115}), 7: (1, {'@': 115}), 8: (1, {'@': 115}), 9: (1, {'@': 115}), 10: (1, {'@': 115})}, 322: {6: (1, {'@': 62}), 15: (1, {'@': 62}), 21: (1, {'@': 62})}, 323: {25: (0, 246), 26: (0, 56), 2: (0, 60), 14: (0, 341)}, 324: {6: (0, 286)}, 325: {21: (1, {'@': 142}), 6: (1, {'@': 142})}, 326: {6: (0, 100)}, 327: {77: (1, {'@': 90})}, 328: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 75), 14: (0, 215), 52: (0, 217)}, 329: {40: (0, 305), 65: (0, 263), 64: (0, 110), 66: (0, 266), 63: (0, 282), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 330: {2: (1, {'@': 206}), 17: (1, {'@': 206})}, 331: {77: (1, {'@': 91})}, 332: {0: (1, {'@': 98}), 1: (1, {'@': 98}), 2: (1, {'@': 98}), 3: (1, {'@': 98}), 4: (1, {'@': 98}), 5: (1, {'@': 98}), 6: (1, {'@': 98}), 7: (1, {'@': 98}), 8: (1, {'@': 98}), 9: (1, {'@': 98}), 10: (1, {'@': 98})}, 333: {62: (1, {'@': 107})}, 334: {63: (0, 395), 70: (0, 20)}, 335: {50: (0, 312), 19: (0, 325), 2: (0, 60), 14: (0, 215), 52: (0, 217), 51: (0, 271)}, 336: {6: (1, {'@': 81}), 15: (1, {'@': 81}), 21: (1, {'@': 81})}, 337: {24: (1, {'@': 87}), 23: (1, {'@': 87}), 2: (1, {'@': 87}), 17: (1, {'@': 87})}, 338: {18: (0, 239), 14: (0, 215), 2: (0, 60), 17: (0, 221), 16: (0, 237), 13: (0, 162), 19: (0, 224), 20: (0, 232)}, 339: {40: (0, 305), 68: (0, 295), 69: (0, 180), 66: (0, 348), 70: (0, 73), 71: (0, 61), 64: (0, 110), 41: (0, 90), 63: (0, 395), 72: (0, 334), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 340: {11: (0, 240)}, 341: {6: (1, {'@': 88}), 15: (1, {'@': 88}), 21: (1, {'@': 88}), 17: (1, {'@': 88}), 60: (1, {'@': 88}), 62: (1, {'@': 88})}, 342: {6: (1, {'@': 213}), 15: (1, {'@': 213}), 21: (1, {'@': 213})}, 343: {0: (1, {'@': 118}), 1: (1, {'@': 118}), 2: (1, {'@': 118}), 3: (1, {'@': 118}), 4: (1, {'@': 118}), 5: (1, {'@': 118}), 6: (1, {'@': 118}), 7: (1, {'@': 118}), 8: (1, {'@': 118}), 9: (1, {'@': 118}), 10: (1, {'@': 118})}, 344: {21: (0, 113), 6: (1, {'@': 197})}, 345: {0: (1, {'@': 129}), 1: (1, {'@': 129}), 2: (1, {'@': 129}), 3: (1, {'@': 129}), 4: (1, {'@': 129}), 5: (1, {'@': 129}), 6: (1, {'@': 129}), 7: (1, {'@': 129}), 8: (1, {'@': 129}), 9: (1, {'@': 129}), 10: (1, {'@': 129})}, 346: {6: (0, 147)}, 347: {63: (1, {'@': 89}), 1: (1, {'@': 89}), 77: (1, {'@': 89})}, 348: {6: (1, {'@': 102}), 21: (1, {'@': 102})}, 349: {62: (0, 88)}, 350: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 150), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 351: {0: (1, {'@': 131}), 1: (1, {'@': 131}), 2: (1, {'@': 131}), 3: (1, {'@': 131}), 4: (1, {'@': 131}), 5: (1, {'@': 131}), 6: (1, {'@': 131}), 7: (1, {'@': 131}), 8: (1, {'@': 131}), 9: (1, {'@': 131}), 10: (1, {'@': 131})}, 352: {11: (0, 191)}, 353: {60: (0, 136), 61: (0, 163)}, 354: {6: (0, 361)}, 355: {15: (0, 68), 6: (0, 196)}, 356: {23: (1, {'@': 178}), 2: (1, {'@': 178}), 24: (1, {'@': 178}), 17: (1, {'@': 178})}, 357: {62: (0, 283)}, 358: {11: (0, 314)}, 359: {6: (0, 231)}, 360: {77: (0, 356), 78: (0, 225)}, 361: {0: (1, {'@': 165}), 1: (1, {'@': 165}), 2: (1, {'@': 165}), 3: (1, {'@': 165}), 4: (1, {'@': 165}), 5: (1, {'@': 165}), 6: (1, {'@': 165}), 7: (1, {'@': 165}), 8: (1, {'@': 165}), 9: (1, {'@': 165}), 10: (1, {'@': 165})}, 362: {23: (1, {'@': 180}), 2: (1, {'@': 180}), 17: (1, {'@': 180})}, 363: {0: (1, {'@': 128}), 1: (1, {'@': 128}), 2: (1, {'@': 128}), 3: (1, {'@': 128}), 4: (1, {'@': 128}), 5: (1, {'@': 128}), 6: (1, {'@': 128}), 7: (1, {'@': 128}), 8: (1, {'@': 128}), 9: (1, {'@': 128}), 10: (1, {'@': 128})}, 364: {17: (0, 372), 60: (0, 136), 61: (0, 209)}, 365: {0: (1, {'@': 95}), 1: (1, {'@': 95}), 2: (1, {'@': 95}), 3: (1, {'@': 95}), 4: (1, {'@': 95}), 5: (1, {'@': 95}), 6: (1, {'@': 95}), 7: (1, {'@': 95}), 8: (1, {'@': 95}), 9: (1, {'@': 95}), 10: (1, {'@': 95})}, 366: {40: (0, 305), 79: (0, 33), 66: (0, 233), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 367: {40: (0, 305), 66: (0, 233), 79: (0, 137), 64: (0, 110), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 368: {77: (0, 356), 78: (0, 125), 1: (0, 331), 63: (0, 327), 82: (0, 131)}, 369: {59: (0, 291), 58: (0, 118), 11: (0, 157), 57: (0, 170)}, 370: {6: (0, 254)}, 371: {6: (0, 106)}, 372: {60: (0, 136), 61: (0, 178)}, 373: {6: (0, 365)}, 374: {23: (0, 140), 2: (0, 60), 25: (0, 65), 14: (0, 341)}, 375: {6: (1, {'@': 76}), 15: (1, {'@': 76}), 21: (1, {'@': 76})}, 376: {0: (1, {'@': 132}), 1: (1, {'@': 132}), 2: (1, {'@': 132}), 3: (1, {'@': 132}), 4: (1, {'@': 132}), 5: (1, {'@': 132}), 6: (1, {'@': 132}), 7: (1, {'@': 132}), 8: (1, {'@': 132}), 9: (1, {'@': 132}), 10: (1, {'@': 132})}, 377: {6: (1, {'@': 93}), 21: (1, {'@': 93})}, 378: {92: (0, 161), 21: (0, 169), 6: (1, {'@': 192}), 15: (1, {'@': 192})}, 379: {57: (0, 170), 58: (0, 118), 59: (0, 235), 11: (0, 216)}, 380: {15: (0, 267), 6: (0, 54)}, 381: {6: (1, {'@': 135}), 15: (1, {'@': 135}), 21: (1, {'@': 135})}, 382: {50: (0, 312), 19: (0, 325), 2: (0, 60), 51: (0, 272), 14: (0, 215), 52: (0, 217)}, 383: {40: (0, 305), 64: (0, 110), 66: (0, 134), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 384: {6: (0, 376)}, 385: {2: (0, 60), 14: (0, 341), 25: (0, 184)}, 386: {6: (1, {'@': 83}), 15: (1, {'@': 83}), 21: (1, {'@': 83})}, 387: {6: (1, {'@': 61}), 15: (1, {'@': 61}), 21: (1, {'@': 61})}, 388: {21: (0, 74), 6: (1, {'@': 193})}, 389: {11: (1, {'@': 134})}, 390: {6: (1, {'@': 31}), 21: (1, {'@': 31})}, 391: {62: (1, {'@': 109})}, 392: {40: (0, 305), 66: (0, 233), 64: (0, 110), 79: (0, 121), 6: (1, {'@': 34}), 21: (1, {'@': 34})}, 393: {74: (0, 107), 64: (0, 333), 75: (0, 349), 40: (0, 305)}, 394: {6: (0, 229)}, 395: {40: (1, {'@': 187}), 6: (1, {'@': 187}), 41: (1, {'@': 187}), 21: (1, {'@': 187})}}, 'start_states': {'start': 24}, 'end_states': {'start': 50}}, '__type__': 'ParsingFrontend'}, 'rules': [{'@': 31}, {'@': 32}, {'@': 33}, {'@': 34}, {'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}, {'@': 131}, {'@': 132}, {'@': 133}, {'@': 134}, {'@': 135}, {'@': 136}, {'@': 137}, {'@': 138}, {'@': 139}, {'@': 140}, {'@': 141}, {'@': 142}, {'@': 143}, {'@': 144}, {'@': 145}, {'@': 146}, {'@': 147}, {'@': 148}, {'@': 149}, {'@': 150}, {'@': 151}, {'@': 152}, {'@': 153}, {'@': 154}, {'@': 155}, {'@': 156}, {'@': 157}, {'@': 158}, {'@': 159}, {'@': 160}, {'@': 161}, {'@': 162}, {'@': 163}, {'@': 164}, {'@': 165}, {'@': 166}, {'@': 167}, {'@': 168}, {'@': 169}, {'@': 170}, {'@': 171}, {'@': 172}, {'@': 173}, {'@': 174}, {'@': 175}, {'@': 176}, {'@': 177}, {'@': 178}, {'@': 179}, {'@': 180}, {'@': 181}, {'@': 182}, {'@': 183}, {'@': 184}, {'@': 185}, {'@': 186}, {'@': 187}, {'@': 188}, {'@': 189}, {'@': 190}, {'@': 191}, {'@': 192}, {'@': 193}, {'@': 194}, {'@': 195}, {'@': 196}, {'@': 197}, {'@': 198}, {'@': 199}, {'@': 200}, {'@': 201}, {'@': 202}, {'@': 203}, {'@': 204}, {'@': 205}, {'@': 206}, {'@': 207}, {'@': 208}, {'@': 209}, {'@': 210}, {'@': 211}, {'@': 212}, {'@': 213}, {'@': 214}, {'@': 215}, {'@': 216}, {'@': 217}, {'@': 218}], 'options': {'debug': False, 'strict': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None, '_plugins': {}}, '__type__': 'Lark'}\n)\nMEMO = (\n{0: {'name': 'NUMBER', 'pattern': {'value': '(?:(?:(?:[0-9])+(?:e|E)(?:(?:\\\\+|\\\\-))?(?:[0-9])+|(?:(?:[0-9])+\\\\.(?:(?:[0-9])+)?|\\\\.(?:[0-9])+)(?:(?:e|E)(?:(?:\\\\+|\\\\-))?(?:[0-9])+)?)|(?:[0-9])+)', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 1: {'name': 'COMMA', 'pattern': {'value': '(?:[^\\\\S\\r\\n]+)?,(?:[^\\\\S\\r\\n]+)?', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 2: {'name': 'COLON', 'pattern': {'value': '(?:[^\\\\S\\r\\n]+)?:(?:[^\\\\S\\r\\n]+)?', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 3: {'name': 'NL', 'pattern': {'value': '[^\\\\S\\r\\n]*\\r?\\n', 'flags': [], 'raw': '/[^\\\\S\\\\r\\\\n]*\\\\r?\\\\n/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': -10, '__type__': 'TerminalDef'}, 4: {'name': 'SLASH', 'pattern': {'value': '/', 'flags': [], 'raw': '\"/\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 5: {'name': 'BACKSLASH', 'pattern': {'value': '(?:\\\\\\\\)+', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 6: {'name': 'CONSTRAINT_LPAREN', 'pattern': {'value': '(?:[^\\\\S\\r\\n]+)?\\\\(', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 7: {'name': 'CONSTRAINT_RPAREN', 'pattern': {'value': '\\\\)(?:[^\\\\S\\r\\n]+)?', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 8: {'name': 'LBRACKET', 'pattern': {'value': '(?:[^\\\\S\\r\\n]+)?\\\\[', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 9: {'name': 'RBRACKET', 'pattern': {'value': '\\\\](?:[^\\\\S\\r\\n]+)?', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 10: {'name': 'HASHTAG', 'pattern': {'value': '#', 'flags': [], 'raw': '\"#\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 11: {'name': 'PERCENT', 'pattern': {'value': '%', 'flags': [], 'raw': '\"%\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 12: {'name': 'SP', 'pattern': {'value': '[^\\\\S\\r\\n]+', 'flags': [], 'raw': '/[^\\\\S\\\\r\\\\n]+/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': -50, '__type__': 'TerminalDef'}, 13: {'name': 'BOX_NAME', 'pattern': {'value': '(?![\\\\W_\\\\d])[^=<>,:\\n\\\\\\\\]*[^-\\\\[\\\\\\\\\\\\]=<>,:\\\\s\\\\\\\\]', 'flags': [], 'raw': '/(?![\\\\W_\\\\d])[^=<>,:\\\\n\\\\\\\\]*[^-\\\\[\\\\\\\\\\\\]=<>,:\\\\s\\\\\\\\]/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 14: {'name': 'ATTR', 'pattern': {'value': '(?=\\\\w)(?!_)[^\\\\[\\\\]>,\\r\\n!?]*[^\\\\[\\\\]>,\\\\s]', 'flags': [], 'raw': '/(?=\\\\w)(?!_)[^\\\\[\\\\]>,\\\\r\\\\n!?]*[^\\\\[\\\\]>,\\\\s]/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 15: {'name': 'BREAK', 'pattern': {'value': '^\\n', 'flags': [], 'raw': '/^\\\\n/', '_width': [1, 1], '__type__': 'PatternRE'}, 'priority': 100, '__type__': 'TerminalDef'}, 16: {'name': 'PHANTOMS', 'pattern': {'value': '( *:)+ *[^\\\\S\\r\\n]*\\r?\\n', 'flags': [], 'raw': None, '_width': [2, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 17: {'name': 'INDENT', 'pattern': {'value': ' +|\\t+', 'flags': [], 'raw': '/ +|\\\\t+/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 10, '__type__': 'TerminalDef'}, 18: {'name': 'CARD', 'pattern': {'value': '(?![-_\\\\/])(\\\\w|\\\\?){2}(?=[ \\t]*[^\\\\w,\\r\\n:])', 'flags': [], 'raw': '/(?![-_\\\\/])(\\\\w|\\\\?){2}(?=[ \\\\t]*[^\\\\w,\\\\r\\\\n:])/', '_width': [2, 2], '__type__': 'PatternRE'}, 'priority': 2, '__type__': 'TerminalDef'}, 19: {'name': 'LEG_ARROW', 'pattern': {'value': '[<>]', 'flags': [], 'raw': '/[<>]/', '_width': [1, 1], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 20: {'name': 'ID_GROUPS', 'pattern': {'value': '\\\\d+(?=_)', 'flags': [], 'raw': '/\\\\d+(?=_)/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 10, '__type__': 'TerminalDef'}, 21: {'name': 'ID_MARK', 'pattern': {'value': '_', 'flags': [], 'raw': '\"_\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 22: {'name': 'MORETHAN', 'pattern': {'value': '(?:[^\\\\S\\r\\n]+)?>(?:[^\\\\S\\r\\n]+)?', 'flags': [], 'raw': None, '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 23: {'name': 'CONSTRAINT_NAME', 'pattern': {'value': '[^)]{1,3}', 'flags': [], 'raw': '/[^)]{1,3}/', '_width': [1, 3], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 24: {'name': 'CONSTRAINT_LEG', 'pattern': {'value': '<?(\\\\.+|-+)>?', 'flags': [], 'raw': '/<?(\\\\.+|-+)>?/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 25: {'name': 'INHERITANCE_NAME', 'pattern': {'value': '(XT\\\\d?|TX\\\\d?|X\\\\d?|T\\\\d?|\\\\d)', 'flags': [], 'raw': '/(XT\\\\d?|TX\\\\d?|X\\\\d?|T\\\\d?|\\\\d)/', '_width': [1, 3], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 26: {'name': 'INHERITANCE_ARROW', 'pattern': {'value': '<==?|<--?|--?>|==?>', 'flags': [], 'raw': '/<==?|<--?|--?>|==?>/', '_width': [2, 3], '__type__': 'PatternRE'}, 'priority': -10, '__type__': 'TerminalDef'}, 27: {'name': 'PLUS', 'pattern': {'value': '+', 'flags': [], 'raw': '\"+\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 28: {'name': 'MINUS', 'pattern': {'value': '-', 'flags': [], 'raw': '\"-\"', '__type__': 'PatternStr'}, 'priority': 0, '__type__': 'TerminalDef'}, 29: {'name': '__ANON_0', 'pattern': {'value': '[^\\r\\n\\\\]]+', 'flags': [], 'raw': '/[^\\\\r\\\\n\\\\]]+/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 30: {'name': '__ANON_1', 'pattern': {'value': '.*\\r?\\n', 'flags': [], 'raw': '/.*\\\\r?\\\\n/', '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 0, '__type__': 'TerminalDef'}, 31: {'origin': {'name': Token('RULE', 'typed_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'attr', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'datatype', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 32: {'origin': {'name': Token('RULE', 'typed_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'attr', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 33: {'origin': {'name': Token('RULE', 'typed_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'attr', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 34: {'origin': {'name': Token('RULE', 'typed_attr'), '__type__': 'NonTerminal'}, 'expansion': [], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 35: {'origin': {'name': Token('RULE', 'datatype'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'note', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 36: {'origin': {'name': Token('RULE', 'box_def_prefix'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'PLUS', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': True, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 37: {'origin': {'name': Token('RULE', 'box_def_prefix'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'MINUS', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': True, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 38: {'origin': {'name': Token('RULE', 'note'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '__ANON_0', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': True, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 39: {'origin': {'name': Token('RULE', 'start'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '__start_star_0', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 40: {'origin': {'name': Token('RULE', 'start'), '__type__': 'NonTerminal'}, 'expansion': [], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 41: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'indent', '__type__': 'NonTerminal'}, {'name': 'phantoms', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 42: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'indent', '__type__': 'NonTerminal'}, {'name': 'comment', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 43: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'indent', '__type__': 'NonTerminal'}, {'name': 'clause', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 44: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'indent', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 45: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'phantoms', '__type__': 'NonTerminal'}], 'order': 4, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 46: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'comment', '__type__': 'NonTerminal'}], 'order': 5, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 47: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'clause', '__type__': 'NonTerminal'}], 'order': 6, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 48: {'origin': {'name': Token('RULE', 'line'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 7, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 49: {'origin': {'name': Token('RULE', 'clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_clause', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': True, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 50: {'origin': {'name': Token('RULE', 'clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_clause', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': True, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 51: {'origin': {'name': Token('RULE', 'clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'constraint_clause', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': True, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 52: {'origin': {'name': Token('RULE', 'clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'inheritance_clause', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': True, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 53: {'origin': {'name': Token('RULE', 'indent'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'INDENT', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 54: {'origin': {'name': Token('RULE', 'comment'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'PERCENT', 'filter_out': False, '__type__': 'Terminal'}, {'name': '__ANON_1', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 55: {'origin': {'name': Token('RULE', 'assoc_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_def_prefix', '__type__': 'NonTerminal'}, {'name': 'assoc_name_def', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 56: {'origin': {'name': Token('RULE', 'assoc_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_def_prefix', '__type__': 'NonTerminal'}, {'name': 'assoc_name_def', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 57: {'origin': {'name': Token('RULE', 'assoc_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_name_def', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 58: {'origin': {'name': Token('RULE', 'assoc_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_name_def', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 59: {'origin': {'name': Token('RULE', 'assoc_name_def'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 60: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 61: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 62: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 63: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 64: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 4, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 65: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 5, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 66: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 6, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 67: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 7, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 68: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 8, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 69: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 9, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 70: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 10, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 71: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_assoc_card', '__type__': 'NonTerminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 11, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 72: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 12, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 73: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 13, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 74: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 14, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 75: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 15, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 76: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 16, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 77: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'leg_arrow', '__type__': 'NonTerminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 17, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 78: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 18, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 79: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 19, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 80: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 20, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 81: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'leg_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 21, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 82: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 22, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 83: {'origin': {'name': Token('RULE', 'assoc_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 23, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 84: {'origin': {'name': Token('RULE', '_assoc_card'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'card_hidden', '__type__': 'NonTerminal'}, {'name': 'card_prefix', '__type__': 'NonTerminal'}, {'name': 'card', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 85: {'origin': {'name': Token('RULE', '_assoc_card'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'card_hidden', '__type__': 'NonTerminal'}, {'name': 'card', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 86: {'origin': {'name': Token('RULE', '_assoc_card'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'card_prefix', '__type__': 'NonTerminal'}, {'name': 'card', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 87: {'origin': {'name': Token('RULE', '_assoc_card'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'card', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 88: {'origin': {'name': Token('RULE', 'entity_name_ref'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 89: {'origin': {'name': Token('RULE', 'card_hidden'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'MINUS', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': True, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 90: {'origin': {'name': Token('RULE', 'card_prefix'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'ID_MARK', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': True, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 91: {'origin': {'name': Token('RULE', 'card_prefix'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': True, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 92: {'origin': {'name': Token('RULE', 'leg_note'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'note', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 93: {'origin': {'name': Token('RULE', 'assoc_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'ID_MARK', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 94: {'origin': {'name': Token('RULE', 'assoc_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 95: {'origin': {'name': Token('RULE', 'entity_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_def_prefix', '__type__': 'NonTerminal'}, {'name': 'entity_name_def', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{entity_or_table_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 96: {'origin': {'name': Token('RULE', 'entity_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_def_prefix', '__type__': 'NonTerminal'}, {'name': 'entity_name_def', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 97: {'origin': {'name': Token('RULE', 'entity_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_def', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{entity_or_table_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 98: {'origin': {'name': Token('RULE', 'entity_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_def', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 99: {'origin': {'name': Token('RULE', 'entity_name_def'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 100: {'origin': {'name': Token('RULE', 'entity_or_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_id_symbols', '__type__': 'NonTerminal'}, {'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 101: {'origin': {'name': Token('RULE', 'entity_or_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_id_symbols', '__type__': 'NonTerminal'}, {'name': 'HASHTAG', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'foreign_reference', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 102: {'origin': {'name': Token('RULE', 'entity_or_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 103: {'origin': {'name': Token('RULE', 'entity_or_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'HASHTAG', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'foreign_reference', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 104: {'origin': {'name': Token('RULE', '_id_symbols'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'id_groups', '__type__': 'NonTerminal'}, {'name': 'id_mark', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 105: {'origin': {'name': Token('RULE', '_id_symbols'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'id_mark', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 106: {'origin': {'name': Token('RULE', 'foreign_reference'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'this_table_attr', '__type__': 'NonTerminal'}, {'name': 'MORETHAN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'that_table', '__type__': 'NonTerminal'}, {'name': 'MORETHAN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'that_table_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 107: {'origin': {'name': Token('RULE', 'this_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 108: {'origin': {'name': Token('RULE', 'that_table_attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 109: {'origin': {'name': Token('RULE', 'that_table'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 110: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 111: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 112: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 113: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 114: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 4, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 115: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 5, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 116: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 6, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 117: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 7, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 118: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 8, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 119: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 9, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 120: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 10, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 121: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_name', '__type__': 'NonTerminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 11, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 122: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 12, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 123: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 13, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 124: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 14, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 125: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_note', '__type__': 'NonTerminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 15, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 126: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 16, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 127: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 17, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 128: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 18, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 129: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'LBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'RBRACKET', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 19, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 130: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 20, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 131: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 21, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 132: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_coords', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 22, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 133: {'origin': {'name': Token('RULE', 'constraint_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'CONSTRAINT_RPAREN', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 23, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 134: {'origin': {'name': Token('RULE', 'constraint_note'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'note', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 135: {'origin': {'name': Token('RULE', 'constraint_target'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'constraint_leg', '__type__': 'NonTerminal'}, {'name': '__constraint_target_star_1', '__type__': 'NonTerminal'}, {'name': 'box_name_ref', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 136: {'origin': {'name': Token('RULE', 'constraint_target'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'constraint_leg', '__type__': 'NonTerminal'}, {'name': 'box_name_ref', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 137: {'origin': {'name': Token('RULE', 'constraint_target'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '__constraint_target_star_1', '__type__': 'NonTerminal'}, {'name': 'box_name_ref', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 138: {'origin': {'name': Token('RULE', 'constraint_target'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name_ref', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 139: {'origin': {'name': Token('RULE', 'box_name_ref'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 140: {'origin': {'name': Token('RULE', 'constraint_coords'), '__type__': 'NonTerminal'}, 'expansion': [{'name': '_constraint_coord', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': '_constraint_coord', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 141: {'origin': {'name': Token('RULE', '_constraint_coord'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'NUMBER', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 142: {'origin': {'name': Token('RULE', '_constraint_coord'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'box_name_ref', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 143: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 144: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 145: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 146: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 147: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 4, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 148: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 5, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 149: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 6, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 150: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 7, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 151: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 8, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 152: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 9, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 153: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 10, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 154: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 11, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 155: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 12, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 156: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 13, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 157: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 14, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 158: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_name', '__type__': 'NonTerminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 15, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 159: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 16, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 160: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 17, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 161: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 18, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 162: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 19, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 163: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 20, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 164: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 21, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 165: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 22, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 166: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 23, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 167: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 24, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 168: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 25, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 169: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 26, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 170: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 27, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 171: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 28, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 172: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 29, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 173: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'COLON', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 30, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 174: {'origin': {'name': Token('RULE', 'inheritance_clause'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'BACKSLASH', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_parent', '__type__': 'NonTerminal'}, {'name': 'inheritance_arrow', '__type__': 'NonTerminal'}, {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, {'name': 'NL', 'filter_out': False, '__type__': 'Terminal'}], 'order': 31, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 175: {'origin': {'name': Token('RULE', 'inheritance_parent'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 176: {'origin': {'name': Token('RULE', 'inheritance_child'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_name_ref', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 177: {'origin': {'name': Token('RULE', 'constraint_leg'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_LEG', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 178: {'origin': {'name': Token('RULE', 'card'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CARD', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 179: {'origin': {'name': Token('RULE', 'box_name'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'BOX_NAME', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 180: {'origin': {'name': Token('RULE', 'leg_arrow'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'LEG_ARROW', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 181: {'origin': {'name': Token('RULE', 'phantoms'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'PHANTOMS', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 182: {'origin': {'name': Token('RULE', 'break_'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'BREAK', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 183: {'origin': {'name': Token('RULE', 'inheritance_name'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'INHERITANCE_NAME', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 184: {'origin': {'name': Token('RULE', 'constraint_name'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'CONSTRAINT_NAME', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 185: {'origin': {'name': Token('RULE', 'attr'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'ATTR', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 186: {'origin': {'name': Token('RULE', 'inheritance_arrow'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'INHERITANCE_ARROW', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 187: {'origin': {'name': Token('RULE', 'id_mark'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'ID_MARK', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 188: {'origin': {'name': Token('RULE', 'id_groups'), '__type__': 'NonTerminal'}, 'expansion': [{'name': 'ID_GROUPS', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 189: {'origin': {'name': 'seq{assoc_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_attr', '__type__': 'NonTerminal'}, {'name': '__seq{assoc_attr}_star_2', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 190: {'origin': {'name': 'seq{assoc_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 191: {'origin': {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_leg', '__type__': 'NonTerminal'}, {'name': '__seq{assoc_leg}_star_3', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 192: {'origin': {'name': 'seq{assoc_leg}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'assoc_leg', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 193: {'origin': {'name': 'seq{entity_or_table_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_or_table_attr', '__type__': 'NonTerminal'}, {'name': '__seq{entity_or_table_attr}_star_4', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 194: {'origin': {'name': 'seq{entity_or_table_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'entity_or_table_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 195: {'origin': {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'constraint_target', '__type__': 'NonTerminal'}, {'name': '__seq{constraint_target}_star_5', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 196: {'origin': {'name': 'seq{constraint_target}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'constraint_target', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 197: {'origin': {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'typed_attr', '__type__': 'NonTerminal'}, {'name': '__seq{typed_attr}_star_6', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 198: {'origin': {'name': 'seq{typed_attr}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 199: {'origin': {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'inheritance_child', '__type__': 'NonTerminal'}, {'name': '__seq{inheritance_child}_star_7', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 200: {'origin': {'name': 'seq{inheritance_child}', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'inheritance_child', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': Token('RULE', 'seq'), 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 201: {'origin': {'name': '__start_star_0', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'break_', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 202: {'origin': {'name': '__start_star_0', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'line', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 203: {'origin': {'name': '__start_star_0', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__start_star_0', '__type__': 'NonTerminal'}, {'name': 'break_', '__type__': 'NonTerminal'}], 'order': 2, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 204: {'origin': {'name': '__start_star_0', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__start_star_0', '__type__': 'NonTerminal'}, {'name': 'line', '__type__': 'NonTerminal'}], 'order': 3, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 205: {'origin': {'name': '__constraint_target_star_1', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 206: {'origin': {'name': '__constraint_target_star_1', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__constraint_target_star_1', '__type__': 'NonTerminal'}, {'name': 'SP', 'filter_out': False, '__type__': 'Terminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 207: {'origin': {'name': '__seq{assoc_attr}_star_2', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'assoc_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 208: {'origin': {'name': '__seq{assoc_attr}_star_2', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{assoc_attr}_star_2', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'assoc_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 209: {'origin': {'name': '__seq{assoc_leg}_star_3', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'assoc_leg', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 210: {'origin': {'name': '__seq{assoc_leg}_star_3', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{assoc_leg}_star_3', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'assoc_leg', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 211: {'origin': {'name': '__seq{entity_or_table_attr}_star_4', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_or_table_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 212: {'origin': {'name': '__seq{entity_or_table_attr}_star_4', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{entity_or_table_attr}_star_4', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'entity_or_table_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 213: {'origin': {'name': '__seq{constraint_target}_star_5', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_target', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 214: {'origin': {'name': '__seq{constraint_target}_star_5', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{constraint_target}_star_5', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'constraint_target', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 215: {'origin': {'name': '__seq{typed_attr}_star_6', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 216: {'origin': {'name': '__seq{typed_attr}_star_6', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{typed_attr}_star_6', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'typed_attr', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 217: {'origin': {'name': '__seq{inheritance_child}_star_7', '__type__': 'NonTerminal'}, 'expansion': [{'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_child', '__type__': 'NonTerminal'}], 'order': 0, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}, 218: {'origin': {'name': '__seq{inheritance_child}_star_7', '__type__': 'NonTerminal'}, 'expansion': [{'name': '__seq{inheritance_child}_star_7', '__type__': 'NonTerminal'}, {'name': 'COMMA', 'filter_out': False, '__type__': 'Terminal'}, {'name': 'inheritance_child', '__type__': 'NonTerminal'}], 'order': 1, 'alias': None, 'options': {'keep_all_tokens': False, 'expand1': False, 'priority': None, 'template_source': None, 'empty_indices': (), '__type__': 'RuleOptions'}, '__type__': 'Rule'}}\n)\nShift = 0\nReduce = 1\ndef Lark_StandAlone(**kwargs):\n  return Lark._load_from_dict(DATA, MEMO, **kwargs)\n"
  },
  {
    "path": "mocodo/phantom.py",
    "content": "class Phantom:\n\n    counter = 0\n\n    @classmethod\n    def reset_counter(cls):\n        cls.counter = 0\n\n    def __init__(self):\n        self.source = \":\"\n        self.name_view = \"\"\n        Phantom.counter += 1\n        self.bid = f\"PHANTOM_#{Phantom.counter}\"\n        self.attributes = []\n        self.legs = [] # iterating over box's legs does nothing if it is not an association\n        self.kind = \"phantom\"\n        self.page = 0\n\n    def calculate_size(self, *ignored):\n        self.w = 0\n        self.h = 0\n\n    def register_center(self, geo):\n        pass\n\n    def register_boxes(self, boxes):\n        self.boxes = boxes\n"
  },
  {
    "path": "mocodo/resources/colors/blank.json",
    "content": "{\n  \"association_attribute_text_color\": null,\n  \"association_cartouche_color\": \"#FFFFFF\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#FFFFFF\",\n  \"association_stroke_color\": \"#000000\",\n  \"background_color\": null,\n  \"card_text_color\": null,\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#000000\",\n  \"constraint_text_color\": \"#000000\",\n  \"entity_attribute_text_color\": null,\n  \"entity_cartouche_color\": \"#FFFFFF\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#FFFFFF\",\n  \"entity_stroke_color\": \"#000000\",\n  \"id_gutter_color\": \"#FFFFFF\",\n  \"id_gutter_text_color\": null,\n  \"leg_stroke_color\": \"#000000\",\n  \"note_color\": \"#000000\",\n  \"note_opacity\": 0,\n  \"note_text_color\": \"#FFFFFF\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+1.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#dfc27d\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#f6e8c3\",\n  \"association_stroke_color\": \"#bf812d\",\n  \"background_color\": \"#f5f5f5\",\n  \"card_text_color\": \"#01665e\",\n  \"constraint_background_color\": \"#f5f5f5\",\n  \"constraint_stroke_color\": \"#bf812d\",\n  \"constraint_text_color\": \"#bf812d\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#80cdc1\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#c7eae5\",\n  \"entity_stroke_color\": \"#35978f\",\n  \"id_gutter_color\": \"#c7eae5\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#bf812d\",\n  \"note_color\": \"#8c510a\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f5f5f5\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+2.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#f1b6da\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fde0ef\",\n  \"association_stroke_color\": \"#de77ae\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#4d9221\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#de77ae\",\n  \"constraint_text_color\": \"#de77ae\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#b8e186\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#e6f5d0\",\n  \"entity_stroke_color\": \"#7fbc41\",\n  \"id_gutter_color\": \"#e6f5d0\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#de77ae\",\n  \"note_color\": \"#c51b7d\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+3.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#c2a5cf\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#e7d4e8\",\n  \"association_stroke_color\": \"#9970ab\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#1b7837\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#9970ab\",\n  \"constraint_text_color\": \"#9970ab\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#a6dba0\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#d9f0d3\",\n  \"entity_stroke_color\": \"#5aae61\",\n  \"id_gutter_color\": \"#d9f0d3\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#9970ab\",\n  \"note_color\": \"#762a83\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+4.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#fdb863\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fee0b6\",\n  \"association_stroke_color\": \"#e08214\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#542788\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#e08214\",\n  \"constraint_text_color\": \"#e08214\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#b2abd2\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#d8daeb\",\n  \"entity_stroke_color\": \"#8073ac\",\n  \"id_gutter_color\": \"#d8daeb\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#e08214\",\n  \"note_color\": \"#b35806\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+5.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#f4a582\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fddbc7\",\n  \"association_stroke_color\": \"#d6604d\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#2166ac\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#d6604d\",\n  \"constraint_text_color\": \"#d6604d\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#92c5de\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#d1e5f0\",\n  \"entity_stroke_color\": \"#4393c3\",\n  \"id_gutter_color\": \"#d1e5f0\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#d6604d\",\n  \"note_color\": \"#b2182b\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+6.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#f4a582\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fddbc7\",\n  \"association_stroke_color\": \"#d6604d\",\n  \"background_color\": \"#ffffff\",\n  \"card_text_color\": \"#4d4d4d\",\n  \"constraint_background_color\": \"#ffffff\",\n  \"constraint_stroke_color\": \"#d6604d\",\n  \"constraint_text_color\": \"#d6604d\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#bababa\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#e0e0e0\",\n  \"entity_stroke_color\": \"#878787\",\n  \"id_gutter_color\": \"#e0e0e0\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#d6604d\",\n  \"note_color\": \"#b2182b\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+7.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#fdae61\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fee090\",\n  \"association_stroke_color\": \"#f46d43\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#4575b4\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#f46d43\",\n  \"constraint_text_color\": \"#f46d43\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#abd9e9\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#e0f3f8\",\n  \"entity_stroke_color\": \"#74add1\",\n  \"id_gutter_color\": \"#e0f3f8\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#f46d43\",\n  \"note_color\": \"#d73027\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+8.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#fdae61\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fee08b\",\n  \"association_stroke_color\": \"#f46d43\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#1a9850\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#f46d43\",\n  \"constraint_text_color\": \"#f46d43\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#a6d96a\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#d9ef8b\",\n  \"entity_stroke_color\": \"#66bd63\",\n  \"id_gutter_color\": \"#d9ef8b\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#f46d43\",\n  \"note_color\": \"#d73027\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer+9.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#fdae61\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#fee08b\",\n  \"association_stroke_color\": \"#f46d43\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#3288bd\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#f46d43\",\n  \"constraint_text_color\": \"#f46d43\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#abdda4\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#e6f598\",\n  \"entity_stroke_color\": \"#66c2a5\",\n  \"id_gutter_color\": \"#e6f598\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#f46d43\",\n  \"note_color\": \"#d53e4f\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-1.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#80cdc1\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#c7eae5\",\n  \"association_stroke_color\": \"#35978f\",\n  \"background_color\": \"#f5f5f5\",\n  \"card_text_color\": \"#8c510a\",\n  \"constraint_background_color\": \"#f5f5f5\",\n  \"constraint_stroke_color\": \"#35978f\",\n  \"constraint_text_color\": \"#35978f\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#dfc27d\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#f6e8c3\",\n  \"entity_stroke_color\": \"#bf812d\",\n  \"id_gutter_color\": \"#f6e8c3\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#35978f\",\n  \"note_color\": \"#01665e\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f5f5f5\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-2.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#b8e186\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#e6f5d0\",\n  \"association_stroke_color\": \"#7fbc41\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#c51b7d\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#7fbc41\",\n  \"constraint_text_color\": \"#7fbc41\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#f1b6da\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fde0ef\",\n  \"entity_stroke_color\": \"#de77ae\",\n  \"id_gutter_color\": \"#fde0ef\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#7fbc41\",\n  \"note_color\": \"#4d9221\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-3.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#a6dba0\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#d9f0d3\",\n  \"association_stroke_color\": \"#5aae61\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#762a83\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#5aae61\",\n  \"constraint_text_color\": \"#5aae61\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#c2a5cf\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#e7d4e8\",\n  \"entity_stroke_color\": \"#9970ab\",\n  \"id_gutter_color\": \"#e7d4e8\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#5aae61\",\n  \"note_color\": \"#1b7837\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-4.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#b2abd2\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#d8daeb\",\n  \"association_stroke_color\": \"#8073ac\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#b35806\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#8073ac\",\n  \"constraint_text_color\": \"#8073ac\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#fdb863\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fee0b6\",\n  \"entity_stroke_color\": \"#e08214\",\n  \"id_gutter_color\": \"#fee0b6\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#8073ac\",\n  \"note_color\": \"#542788\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-5.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#92c5de\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#d1e5f0\",\n  \"association_stroke_color\": \"#4393c3\",\n  \"background_color\": \"#f7f7f7\",\n  \"card_text_color\": \"#b2182b\",\n  \"constraint_background_color\": \"#f7f7f7\",\n  \"constraint_stroke_color\": \"#4393c3\",\n  \"constraint_text_color\": \"#4393c3\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#f4a582\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fddbc7\",\n  \"entity_stroke_color\": \"#d6604d\",\n  \"id_gutter_color\": \"#fddbc7\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#4393c3\",\n  \"note_color\": \"#2166ac\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#f7f7f7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-6.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#bababa\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#e0e0e0\",\n  \"association_stroke_color\": \"#878787\",\n  \"background_color\": \"#ffffff\",\n  \"card_text_color\": \"#b2182b\",\n  \"constraint_background_color\": \"#ffffff\",\n  \"constraint_stroke_color\": \"#878787\",\n  \"constraint_text_color\": \"#878787\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#f4a582\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fddbc7\",\n  \"entity_stroke_color\": \"#d6604d\",\n  \"id_gutter_color\": \"#fddbc7\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#878787\",\n  \"note_color\": \"#4d4d4d\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-7.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#abd9e9\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#e0f3f8\",\n  \"association_stroke_color\": \"#74add1\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#d73027\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#74add1\",\n  \"constraint_text_color\": \"#74add1\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#fdae61\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fee090\",\n  \"entity_stroke_color\": \"#f46d43\",\n  \"id_gutter_color\": \"#fee090\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#74add1\",\n  \"note_color\": \"#4575b4\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-8.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#a6d96a\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#d9ef8b\",\n  \"association_stroke_color\": \"#66bd63\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#d73027\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#66bd63\",\n  \"constraint_text_color\": \"#66bd63\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#fdae61\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fee08b\",\n  \"entity_stroke_color\": \"#f46d43\",\n  \"id_gutter_color\": \"#fee08b\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#66bd63\",\n  \"note_color\": \"#1a9850\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/brewer-9.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#abdda4\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#e6f598\",\n  \"association_stroke_color\": \"#66c2a5\",\n  \"background_color\": \"#ffffbf\",\n  \"card_text_color\": \"#d53e4f\",\n  \"constraint_background_color\": \"#ffffbf\",\n  \"constraint_stroke_color\": \"#66c2a5\",\n  \"constraint_text_color\": \"#66c2a5\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#fdae61\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#fee08b\",\n  \"entity_stroke_color\": \"#f46d43\",\n  \"id_gutter_color\": \"#fee08b\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#66c2a5\",\n  \"note_color\": \"#3288bd\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#ffffbf\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/bw-alpha.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#FFFFFF\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#FFFFFF\",\n  \"association_stroke_color\": \"#000000\",\n  \"background_color\": null,\n  \"card_text_color\": \"#000000\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#000000\",\n  \"constraint_text_color\": \"#000000\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#FFFFFF\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#FFFFFF\",\n  \"entity_stroke_color\": \"#000000\",\n  \"id_gutter_color\": \"#FFFFFF\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#000000\",\n  \"note_color\": \"#000000\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFFFF\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/bw.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#FFFFFF\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#FFFFFF\",\n  \"association_stroke_color\": \"#000000\",\n  \"background_color\": \"#FFFFFF\",\n  \"card_text_color\": \"#000000\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#000000\",\n  \"constraint_text_color\": \"#000000\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#FFFFFF\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#FFFFFF\",\n  \"entity_stroke_color\": \"#000000\",\n  \"id_gutter_color\": \"#FFFFFF\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#000000\",\n  \"note_color\": \"#000000\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFFFF\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/dark-desert.json",
    "content": "{\n    \"association_attribute_text_color\": \"#D3B08C\",\n    \"association_cartouche_color\": \"#4E3925\",\n    \"association_cartouche_text_color\": \"#D3B08C\",\n    \"association_color\": \"#624A32\",\n    \"association_stroke_color\": \"#C6A664\",\n    \"background_color\": \"#2E2B22\",\n    \"card_text_color\": \"#D4C2A1\",\n    \"constraint_background_color\": \"#4E3925\",\n    \"constraint_stroke_color\": \"#C6A664\",\n    \"constraint_text_color\": \"#D3B08C\",\n    \"entity_attribute_text_color\": \"#E3D5B3\",\n    \"entity_cartouche_color\": \"#5F3C14\",\n    \"entity_cartouche_text_color\": \"#E3D5B3\",\n    \"entity_color\": \"#7C5020\",\n    \"entity_stroke_color\": \"#E5A04B\",\n    \"id_gutter_color\": \"#7C5020\",\n    \"id_gutter_text_color\": \"#E3D5B3\",\n    \"leg_stroke_color\": \"#C6A664\",\n    \"note_color\": \"#2D271E\",\n    \"note_opacity\": 0.8,\n    \"note_text_color\": \"#D4C49A\"\n  }\n"
  },
  {
    "path": "mocodo/resources/colors/dark-ocean.json",
    "content": "{\n    \"association_attribute_text_color\": \"#b4c8a1\",\n    \"association_cartouche_color\": \"#2d3b22\",\n    \"association_cartouche_text_color\": \"#d9e5c3\",\n    \"association_color\": \"#3a4a28\",\n    \"association_stroke_color\": \"#a6b792\",\n    \"background_color\": \"#1a1f1a\",\n    \"card_text_color\": \"#b0aabb\",\n    \"constraint_background_color\": \"#2d3b22\",\n    \"constraint_stroke_color\": \"#a6b792\",\n    \"constraint_text_color\": \"#d9e5c3\",\n    \"entity_attribute_text_color\": \"#e6e5ea\",\n    \"entity_cartouche_color\": \"#1a223a\",\n    \"entity_cartouche_text_color\": \"#d9e5c3\",\n    \"entity_color\": \"#2a3866\",\n    \"entity_stroke_color\": \"#83a5ff\",\n    \"id_gutter_color\": \"#2a3866\",\n    \"id_gutter_text_color\": \"#e6e5ea\",\n    \"leg_stroke_color\": \"#a6b792\",\n    \"note_color\": \"#131517\",\n    \"note_opacity\": 0.8,\n    \"note_text_color\": \"#d9e5c3\"\n  }\n"
  },
  {
    "path": "mocodo/resources/colors/dark-pond.json",
    "content": "{\n    \"association_attribute_text_color\": \"#A7BEC1\",\n    \"association_cartouche_color\": \"#31572E\",\n    \"association_cartouche_text_color\": \"#A7BEC1\",\n    \"association_color\": \"#3F5F4E\",\n    \"association_stroke_color\": \"#B4D877\",\n    \"background_color\": \"#1A2622\",\n    \"card_text_color\": \"#C1D9DC\",\n    \"constraint_background_color\": \"#31572E\",\n    \"constraint_stroke_color\": \"#B4D877\",\n    \"constraint_text_color\": \"#A7BEC1\",\n    \"entity_attribute_text_color\": \"#C4F1D8\",\n    \"entity_cartouche_color\": \"#295943\",\n    \"entity_cartouche_text_color\": \"#C4F1D8\",\n    \"entity_color\": \"#387F59\",\n    \"entity_stroke_color\": \"#6AD1A0\",\n    \"id_gutter_color\": \"#387F59\",\n    \"id_gutter_text_color\": \"#C4F1D8\",\n    \"leg_stroke_color\": \"#B4D877\",\n    \"note_color\": \"#1E3932\",\n    \"note_opacity\": 0.8,\n    \"note_text_color\": \"#C7F7E1\"\n  }\n"
  },
  {
    "path": "mocodo/resources/colors/dark.json",
    "content": "{\n    \"association_attribute_text_color\": \"#FFFFFF\",\n    \"association_cartouche_color\": \"#444444\",\n    \"association_cartouche_text_color\": \"#FFFFFF\",\n    \"association_color\": \"#333333\",\n    \"association_stroke_color\": \"#AAAAAA\",\n    \"background_color\": \"#222222\",\n    \"card_text_color\": \"#FFFFFF\",\n    \"constraint_background_color\": \"#444444\",\n    \"constraint_stroke_color\": \"#AAAAAA\",\n    \"constraint_text_color\": \"#FFFFFF\",\n    \"entity_attribute_text_color\": \"#FFFFFF\",\n    \"entity_cartouche_color\": \"#444444\",\n    \"entity_cartouche_text_color\": \"#FFFFFF\",\n    \"entity_color\": \"#333333\",\n    \"entity_stroke_color\": \"#AAAAAA\",\n    \"id_gutter_color\": \"#444444\",\n    \"id_gutter_text_color\": \"#FFFFFF\",\n    \"leg_stroke_color\": \"#AAAAAA\",\n    \"note_color\": \"#444444\",\n    \"note_opacity\": 0.8,\n    \"note_text_color\": \"#FFFFFF\"\n  }\n"
  },
  {
    "path": "mocodo/resources/colors/desert.json",
    "content": "{\n  \"association_attribute_text_color\": \"#7F5D3B\",\n  \"association_cartouche_color\": \"#CE9F6F\",\n  \"association_cartouche_text_color\": \"#7F5D3B\",\n  \"association_color\": \"#E2BE9F\",\n  \"association_stroke_color\": \"#896C39\",\n  \"background_color\": null,\n  \"card_text_color\": \"#5C4827\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#896C39\",\n  \"constraint_text_color\": \"#896C39\",\n  \"entity_attribute_text_color\": \"#645530\",\n  \"entity_cartouche_color\": \"#FAA945\",\n  \"entity_cartouche_text_color\": \"#645530\",\n  \"entity_color\": \"#FFB94E\",\n  \"entity_stroke_color\": \"#CB7E1F\",\n  \"id_gutter_color\": \"#FFB94E\",\n  \"id_gutter_text_color\": \"#645530\",\n  \"leg_stroke_color\": \"#4C3D30\",\n  \"note_color\": \"#18180B\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFFD0\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/gray.json",
    "content": "{\n  \"association_attribute_text_color\": \"#000000\",\n  \"association_cartouche_color\": \"#FFFFFF\",\n  \"association_cartouche_text_color\": \"#000000\",\n  \"association_color\": \"#FFFFFF\",\n  \"association_stroke_color\": \"#000000\",\n  \"background_color\": null,\n  \"card_text_color\": \"#000000\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#000000\",\n  \"constraint_text_color\": \"#000000\",\n  \"entity_attribute_text_color\": \"#000000\",\n  \"entity_cartouche_color\": \"#DDDDDD\",\n  \"entity_cartouche_text_color\": \"#000000\",\n  \"entity_color\": \"#EEEEEE\",\n  \"entity_stroke_color\": \"#000000\",\n  \"id_gutter_color\": \"#EEEEEE\",\n  \"id_gutter_text_color\": \"#000000\",\n  \"leg_stroke_color\": \"#000000\",\n  \"note_color\": \"#000000\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFFFF\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/keepsake.json",
    "content": "{\n  \"association_attribute_text_color\": \"#57483d\",\n  \"association_cartouche_color\": \"#c6aea5\",\n  \"association_cartouche_text_color\": \"#422f2c\",\n  \"association_color\": \"#d3b5b2\",\n  \"association_stroke_color\": \"#c6aea5\",\n  \"background_color\": null,\n  \"card_text_color\": \"#57483d\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#c6aea5\",\n  \"constraint_text_color\": \"#c6aea5\",\n  \"entity_attribute_text_color\": \"#57483d\",\n  \"entity_cartouche_color\": \"#cbcbb5\",\n  \"entity_cartouche_text_color\": \"#422f2c\",\n  \"entity_color\": \"#e4e3b4\",\n  \"entity_stroke_color\": \"#cbcbb5\",\n  \"id_gutter_color\": \"#e4e3b4\",\n  \"id_gutter_text_color\": \"#57483d\",\n  \"leg_stroke_color\": \"#57483d\",\n  \"note_color\": \"#0F0F0A\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFFD7\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/mondrian.json",
    "content": "{\n  \"association_attribute_text_color\": \"#060100\",\n  \"association_cartouche_color\": \"#081a84\",\n  \"association_cartouche_text_color\": \"#fefeec\",\n  \"association_color\": \"#fefeec\",\n  \"association_stroke_color\": \"#060100\",\n  \"background_color\": \"#fefeec\",\n  \"card_text_color\": \"#060100\",\n  \"constraint_background_color\": \"#fefeec\",\n  \"constraint_stroke_color\": \"#060100\",\n  \"constraint_text_color\": \"#060100\",\n  \"entity_attribute_text_color\": \"#060100\",\n  \"entity_cartouche_color\": \"#c6281b\",\n  \"entity_cartouche_text_color\": \"#fefeec\",\n  \"entity_color\": \"#fced5f\",\n  \"entity_stroke_color\": \"#060100\",\n  \"id_gutter_color\": \"#fced5f\",\n  \"id_gutter_text_color\": \"#060100\",\n  \"leg_stroke_color\": \"#060100\",\n  \"note_color\": \"#066A6A\",\n  \"note_opacity\": 0.85,\n  \"note_text_color\": \"#FFFF22\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/ocean.json",
    "content": "{\n  \"association_attribute_text_color\": \"#607734\",\n  \"association_cartouche_color\": \"#b2bba4\",\n  \"association_cartouche_text_color\": \"#27360c\",\n  \"association_color\": \"#ccd6ba\",\n  \"association_stroke_color\": \"#85956b\",\n  \"background_color\": null,\n  \"card_text_color\": \"#726f83\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#85956b\",\n  \"constraint_text_color\": \"#85956b\",\n  \"entity_attribute_text_color\": \"#3e3c42\",\n  \"entity_cartouche_color\": \"#97b8ff\",\n  \"entity_cartouche_text_color\": \"#131114\",\n  \"entity_color\": \"#c0d4ff\",\n  \"entity_stroke_color\": \"#578dff\",\n  \"id_gutter_color\": \"#c0d4ff\",\n  \"id_gutter_text_color\": \"#3e3c42\",\n  \"leg_stroke_color\": \"#726f83\",\n  \"note_color\": \"#060707\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#E2EED0\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/pond.json",
    "content": "{\n  \"association_attribute_text_color\": \"#3d484a\",\n  \"association_cartouche_color\": \"#9ebd6d\",\n  \"association_cartouche_text_color\": \"#3d484a\",\n  \"association_color\": \"#c3dbbb\",\n  \"association_stroke_color\": \"#8ea243\",\n  \"background_color\": null,\n  \"card_text_color\": \"#2f494e\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#8ea243\",\n  \"constraint_text_color\": \"#8ea243\",\n  \"entity_attribute_text_color\": \"#1b5343\",\n  \"entity_cartouche_color\": \"#7ecb9a\",\n  \"entity_cartouche_text_color\": \"#1b5343\",\n  \"entity_color\": \"#a6efb3\",\n  \"entity_stroke_color\": \"#387252\",\n  \"id_gutter_color\": \"#a6efb3\",\n  \"id_gutter_text_color\": \"#1b5343\",\n  \"leg_stroke_color\": \"#476062\",\n  \"note_color\": \"#0A2019\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#E3FFD9\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/wb.json",
    "content": "{\n  \"association_attribute_text_color\": \"#FFFFFF\",\n  \"association_cartouche_color\": \"#000000\",\n  \"association_cartouche_text_color\": \"#FFFFFF\",\n  \"association_color\": \"#000000\",\n  \"association_stroke_color\": \"#FFFFFF\",\n  \"background_color\": \"#FFFFFF\",\n  \"card_text_color\": \"#000000\",\n  \"constraint_background_color\": \"#FFFFFF\",\n  \"constraint_stroke_color\": \"#FFFFFF\",\n  \"constraint_text_color\": \"#FFFFFF\",\n  \"entity_attribute_text_color\": \"#FFFFFF\",\n  \"entity_cartouche_color\": \"#000000\",\n  \"entity_cartouche_text_color\": \"#FFFFFF\",\n  \"entity_color\": \"#000000\",\n  \"entity_stroke_color\": \"#FFFFFF\",\n  \"id_gutter_color\": \"#000000\",\n  \"id_gutter_text_color\": \"#FFFFFF\",\n  \"leg_stroke_color\": \"#000000\",\n  \"note_color\": \"#FFFF00\",\n  \"note_opacity\": 0.9,\n  \"note_text_color\": \"#000000\"\n}\n"
  },
  {
    "path": "mocodo/resources/colors/xinnian.json",
    "content": "{\n  \"association_attribute_text_color\": \"#ffcf00\",\n  \"association_cartouche_color\": \"#fd0400\",\n  \"association_cartouche_text_color\": \"#ffcf00\",\n  \"association_color\": \"#fd0400\",\n  \"association_stroke_color\": \"#ffcf00\",\n  \"background_color\": \"#d30300\",\n  \"card_text_color\": \"#ffcf00\",\n  \"constraint_background_color\": \"#d30300\",\n  \"constraint_stroke_color\": \"#ffcf00\",\n  \"constraint_text_color\": \"#ffcf00\",\n  \"entity_attribute_text_color\": \"#ffcf00\",\n  \"entity_cartouche_color\": \"#fd0400\",\n  \"entity_cartouche_text_color\": \"#ffcf00\",\n  \"entity_color\": \"#fd0400\",\n  \"entity_stroke_color\": \"#ffcf00\",\n  \"id_gutter_color\": \"#fd0400\",\n  \"id_gutter_text_color\": \"#ffcf00\",\n  \"leg_stroke_color\": \"#ffcf00\",\n  \"note_color\": \"#535300\",\n  \"note_opacity\": 0.7,\n  \"note_text_color\": \"#FFFF00\"\n}\n"
  },
  {
    "path": "mocodo/resources/default_datatypes_en.tsv",
    "content": "Date and Time\n\n\\bdate$\tDATE\n\\bday$\tDATE\n\\btime$\tTIME\n\\bdatetime$\tDATETIME\n\\btimestamp$\tTIMESTAMP\n\\bat$\tTIMESTAMP\n\\bbefore$\tTIMESTAMP\n\\bafter$\tTIMESTAMP\n\nIdentifying and Validating Information\n\n\\bid(entifier)?$\tVARCHAR(8)\n\\bcode$\tVARCHAR(8)\n\\bref(erence)?$\tVARCHAR(8)\n\\bnum(ber)?$\tVARCHAR(8)\n\\bnb$\tVARCHAR(8)\n\\buuid$\tVARCHAR(36)\n\\bsalt$\tBINARY(16)\n\\bhash$\tBINARY(64)\n\\btoken$\tVARCHAR(255)\n\\bpassword$\tVARCHAR(255)\n\\bpwd$\tVARCHAR(255)\n\\bdigest$\tBINARY(64)\n\\bsignature$\tBINARY(64)\n\nInternet and Computers\n\n\\burl$\tVARCHAR(2000)\n\\bip$\tVARCHAR(15)\n\\bip address$\tVARCHAR(15)\n\\bipv4$\tVARCHAR(15)\n\\bipv6$\tVARCHAR(45)\n\\bcookie$\tVARCHAR(255)\n\\bsession$\tVARCHAR(255)\n\\bmd5$\tBINARY(16)\n\\bpath$\tVARCHAR(255)\n\\bstatus$\tVARCHAR(20)\n\\bpriority$\tSMALLINT\n\\bversion$\tVARCHAR(10)\n\nPersonal information\n\n\\bname$\tVARCHAR(255)\n\\bsex$\tCHAR(1)\n\\bgender$\tVARCHAR(10)\n\\bage$\tSMALLINT\n\nAddressing\n\n\\bpost code$\tVARCHAR(20)\n\\bzip code$\tVARCHAR(20)\n\\bphone number$\tVARCHAR(20)\n\\bphone$\tVARCHAR(20)\n\\bfax number$\tVARCHAR(20)\n\\bfax$\tVARCHAR(20)\n\\bemail$\tVARCHAR(255)\n\\bcountry name$\tVARCHAR(100)\n\\bcity name$\tVARCHAR(100)\n\\bcountry code$\tCHAR(2)\n\\baddress$\tVARCHAR(30)\n\nFinancial\n\n\\b(price|amount|fees|charges|cost|bill)$\tDECIMAL(10,2)\n\\barn$\tVARCHAR(8)\t Acquirer Reference Number\n\\barn code$\tVARCHAR(8)\n\\bbic$\tVARCHAR(11)\t Bank Identifier Code\n\\bbic code$\tVARCHAR(11)\n\\biban$\tVARCHAR(34)\t Maximum value\n\nPredicate\n\n^is\\b\tBOOLEAN\n^has\\b\tBOOLEAN\n^does\\b\tBOOLEAN\n^can\\b\tBOOLEAN\n\\bflag$\tBOOLEAN\n\nText\n\n\\btag$\tVARCHAR(50)\n\\blabel$\tVARCHAR(50)\n\\bbody$\tTEXT\n\\bcomment$\tTEXT\n\\bdescription$\tTEXT\n\\bnote$\tTEXT\n\\bmessage$\tTEXT\n\\bcontent$\tTEXT\n\\binfo(rmation)?s?$\tJSON\n\nGeographical\n\n\\blat(itude)?$\tDECIMAL(9,6)\n\\blon(gitude)?$\tDECIMAL(9,6)\n\\bpos(ition)?$\tPOINT\n\nGrading\n\n\\bstars$\tDECIMAL(3,2)\n\\brating$\tDECIMAL(3,2)\n\\brating$\tDECIMAL(3,2)\n\\bgrade$\tDECIMAL(3,2)\n\nQuantity\n\n\\bquantity$\tINTEGER\n\\bcapacity$\tINTEGER\n\\border$\tINTEGER\n\\bpercent(age)?$\tDECIMAL(5,2)\n\\bratio$\tDECIMAL(5,2)\n\\bweight$\tDECIMAL(10,2)\n\\bsize$\tVARCHAR(20)\n\\blength$\tDECIMAL(10,2)\n\\bwidth$\tDECIMAL(10,2)\n\\bheight$\tDECIMAL(10,2)\n\\bvolume$\tDECIMAL(10,2)\n\\btemperature$\tDECIMAL(5,1)\n\\bhumidity$\tDECIMAL(5,2)\n\\bcolor$\tVARCHAR(50)\n\nBlobs\n\n\\bimage$\tBLOB\n\\bpicture$\tBLOB\n\\bphoto$\tBLOB\n\\blogo$\tBLOB\n\\bicon$\tBLOB\n\\bfile$\tBLOB\n\\bvideo$\tBLOB\n\\baudio$\tBLOB\n\\bbinary$\tBLOB\n\\bblob$\tBLOB\n"
  },
  {
    "path": "mocodo/resources/default_datatypes_fr.tsv",
    "content": "Date and Time\n\n^date\\b\tDATE\n^jour\\b\tDATE\n^heure\\b\tTIME\n^date et heure\\b\tDATETIME\n^horodatage\\b\tTIMESTAMP\n\\ba$\tTIMESTAMP\n\\bapres$\tTIMESTAMP\n\\bavant$\tTIMESTAMP\n\nIdentifying and Validating Information\n\n^id(entifiant)?\\b\tVARCHAR(8)\n^code\\b\tVARCHAR(8)\n^ref(erence)?\\b\tVARCHAR(8)\n^num(ero)?\\b\tVARCHAR(8)\n^uuid\\b\tVARCHAR(36)\n^sel\\b\tBINARY(16)\n^empreinte\\b\tBINARY(64)\n^token\\b\tVARCHAR(255)\n^passe\\b\tVARCHAR(255)\n^pwd\\b\tVARCHAR(255)\n^digest\\b\tBINARY(64)\n^signature\\b\tBINARY(64)\n\\bsiren\\b\tCHAR(9)\n\\bsiret\\b\tCHAR(14)\n\nInternet and Computers\n\n^url\\b\tVARCHAR(2000)\n^ip\\b\tVARCHAR(15)\n^adresse ip\\b\tVARCHAR(15)\n^ipv4\\b\tVARCHAR(15)\n^ipv6\\b\tVARCHAR(45)\n^cookie\\b\tVARCHAR(255)\n^session\\b\tVARCHAR(255)\n^md5\\b\tBINARY(16)\n^chemin\\b\tVARCHAR(255)\n^statut\\b\tVARCHAR(20)\n^priorite\\b\tSMALLINT\n^version\\b\tVARCHAR(10)\n\nPersonal information\n\n^(pre)?nom\\b\tVARCHAR(255)\n^sexe\\b\tCHAR(1)\n^genre\\b\tVARCHAR(10)\n^age\\b\tSMALLINT\n^nir\\b\tVARCHAR(15)\n^ss\\b\tVARCHAR(15)\n\\bsecu(rite sociale)?\\b\tVARCHAR(15)\n\nAddressing\n\n^code postal\\b\tVARCHAR(20)\n^tel(ephone)?\\b\tVARCHAR(20)\n^fax\\b\tVARCHAR(20)\n^e?mail\\b\tVARCHAR(255)\n^courriel\\b\tVARCHAR(255)\n^(nom )?pays\\b\tVARCHAR(100)\n^(nom )?ville\\b\tVARCHAR(100)\n^code pays\\b\tCHAR(2)\n^adresse\\b\tVARCHAR(30)\n\nFinancial\n\n^(prix|montant|frais|charges|coût)\\b\tDECIMAL(10,2)\n^code nra\\b\tVARCHAR(8)\n^nra\\b\tVARCHAR(8)\t Numéro de Référence de l'Acquéreur, pour identifier les transactions par carte bancaire\n^bic\\b\tVARCHAR(11)\t Bank Identifier Code\n^code bic\\b\tVARCHAR(11)\n^iban\\b\tVARCHAR(27)\t France, Monaco, etc.\n\nPredicate\n\n^est\\b\tBOOLEAN\n^a\\b\tBOOLEAN\n^peut\\b\tBOOLEAN\n^drapeau\\b\tBOOLEAN\n\nText\n\n^mot clef?\\b\tVARCHAR(50)\n\\blibelle$\tVARCHAR(50)\n^corps\\b\tTEXT\n^commentaire\\b\tTEXT\n^desc(r?(iption)?)\\b\tTEXT\n^descriptif\\b\tTEXT\n^notes?\\b\tTEXT\n^message\\b\tTEXT\n^avis\\b\tTEXT\n^contenu\\b\tTEXT\n\\binfo(rmation)?s?\\b\tJSON\n\nGeographical\n\n^lat(itude)?\\b\tDECIMAL(9,6)\n^lon(gitude)?\\b\tDECIMAL(9,6)\n^pos(ition)?\\b\tPOINT\n\nGrading\n\n\\bétoiles$\tDECIMAL(3,2)\n\nQuantity\n\n^(quantite|qte)\\b\tINTEGER\n^(capacite)\\b\tINTEGER\n^(nombre|nb)\\b\tINTEGER\n^ordre\\b\tINTEGER\n^pourcent(age)?\\b\tDECIMAL(5,2)\n^ratio\\b\tDECIMAL(5,2)\n^poids\\b\tDECIMAL(10,2)\n^taille\\b\tVARCHAR(20)\n^longueur\\b\tDECIMAL(10,2)\n^largeur\\b\tDECIMAL(10,2)\n^hauteur\\b\tDECIMAL(10,2)\n^vol(ume)?\\b\tDECIMAL(10,2)\n^temp(erature)?\\b\tDECIMAL(5,1)\n^humidite\\b\tDECIMAL(5,2)\n^couleur\\b\tVARCHAR(50)\n\nBlobs\n\n^image\\b\tBLOB\n^photo\\b\tBLOB\n^logo\\b\tBLOB\n^icone\\b\tBLOB\n^fichier\\b\tBLOB\n^video\\b\tBLOB\n^audio\\b\tBLOB\n^binaire\\b\tBLOB\n^blob\\b\tBLOB\n"
  },
  {
    "path": "mocodo/resources/font_metrics.json",
    "content": "{\n\"alphabet\": \" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¢£¤¥¦§©«¬®°±²³µ¶·º»¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖŒ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöœ÷øùúûüýþÿ—‘’•…′″‵‶\", \n\"fonts\": {\n\"Arial Unicode MS\": {\n\"default\": 142, \n\"widths\": \"GG[ä«1UUdGUGGGGĄ««¹¹«Ç¹G«Õ¹Ç«Ç¹«¹«ò««GGGxUG999ÕUG¹VCVUC½½fUUG^««««««Ā¹««««GGGG¹¹ÇÇÇÇÇĀÇ¹¹¹¹««äGGGGòĀ99ZĀ9_5[\", \n\"height\": 343\n}, \n\"PT Sans Caption\": {\n\"default\": 152, \n\"widths\": \"JU`Ûä>PPc8e=eFG{Ī¥¤ ·«¼fS«Þ¼¿¿§¶¡ê®VlVtM¡¡]¡¤QPVó¤¢¡ ah¥×bBbTBÞÀxpp£Jrz¥¥¥¥¥¥î ffff¹¼¿¿¿¿¿ą¿¶¶¶¶­îQQQQ¥¤¢¢¢¢¢ā¥¥¥¥¡æ88ÒSS\", \n\"height\": 332\n}, \n\"SchoolHouse Cursive B\": {\n\"default\": 146, \n\"widths\": \"?QY~{n3CWHg#g\\\"h@||urgoc<5KgKff¨¡ÔîËæºtÜÃĖÊ ®¸ð¶ÏĠß²Wdvm&£©¨ÿÇ£°~§x­Í»¦J\\u001bkQu£4ÅÅ5^^H2Tf¨¨¨¨¨¨ëººººØÊ     á ¶¶¶¶¥¹xÇ£££££Âg£Ü#;ÜĀĀĀ\", \n\"height\": 313\n}, \n\"Arial\": {\n\"default\": 142, \n\"widths\": \"GG[ä«1UUdGUGGGGĄ««¹¹«Ç¹G«Õ¹Ç«Ç¹«¹«ò««GGGxUG999ÕUG¹VCVUC½½fUUU^««««««Ā¹««««GGGG¹¹ÇÇÇÇÇĀÇ¹¹¹¹««äGGGGòĀ99ZĀ0[S\", \n\"correction\": 1.05, \n\"height\": 294\n}, \n\"Stone Sans ITC TT\": {\n\"default\": 171, \n\"widths\": \"Dv«««ĈÒS««Z]S««««««««««SS«È¼´¬Ê¿Î_^¹ïÆÌ¯Î´¿¹Ď­£¦®®d«¯WW¡Wā¯¤®°}tr®àv_u¯v««Ã«_«Éml«uu«ºSp¼¼¼¼¼¼ó¬````ÊÇÌÌÌÌÌČ«Î¿¿¿¿£­¿çWWWW¤¯¤¤¤¤¤ý«¤®®®®®ùXYsúZZ\", \n\"height\": 320\n}, \n\"HanaMinA\": {\n\"default\": 154, \n\"height\": 282\n}, \n\"Verdana\": {\n\"default\": 163, \n\"widths\": \"ZevÒ£ĔºEtt£Ò]t]t££££££££££ttÒÒÒĀ¯°³Å¢ÇÀlt±ØÀÊÊ²¯»¯ý¯¯tttÒ££  Z ¢FXFù¢  me¢Ò£t£Òe££££t£Ā¥ÒĀÒ¤£]¥¯¯¯¯¯¯ü³¢¢¢¢llllÇÀÊÊÊÊÊĒÒÊ»»»»õFFFF¢ûÒ¢¢¢¢ ĀEEÒ]S\", \n\"height\": 311\n}, \n\"Academy Engraved LET\": {\n\"default\": 116, \n\"widths\": \"UERÂ»2LL[7P9D¡bty{j>;zìÁ¥¹Ã©ÇÑ\\\\qÄûÐÄ¡ÄÉ¯ÁÁěµºLDLx<tltJuB?C×^]Gowig{3{E}°3ÃUÃfMMt9OUzÁÁÁÁÁÁČ¹©©©©\\\\\\\\\\\\\\\\¹ÐÄÄÄÄÄĎÄÁÁÁÁº{tttttt²lttttBBBBËiiė22QĀ?iS\", \n\"height\": 303\n}, \n\"Krungthep\": {\n\"default\": 171, \n\"widths\": \"?ÕëÕ@kkUU««««««««««UU««ë««««««ÀĀÀ««««««Ā«««kk««««««««U«UĀ««««««Ā«««kkk«À««kÕÀÕÕÀUÀ«««««««ë««À«««««ë«««««««««««««««Ā««««UUUU«««««««Ā««««««««ÕUUīZZ\", \n\"height\": 326\n}, \n\"Helvetica\": {\n\"default\": 142, \n\"widths\": \"GG[ä«1UUdGUGGGGĄ««¹¹«Ç¹G«Õ¹Ç«Ç¹«¹«ò««GGGxUG999ÕUG¹VCVUC½½fUUG^««««««Ā¹««««GGGG¹¹ÇÇÇÇÇĀÇ¹¹¹¹««äGGGGòĀ99ZĀUU\", \n\"height\": 293\n}, \n\"Al Bayan\": {\n\"default\": 162, \n\"widths\": \"3MU¢¢«\\u0000mm{wQwZ¢¢¢¢¢¢¢¢¢¢ZQ]w]lÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  cc)¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛcÌÛoÌll ¢Qxcl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀwÇ±±±± ÚJJJJîw¡ĀQQÖSS\", \n\"height\": 384\n}, \n\"STIXSizeFiveSym\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢̀¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 378\n}, \n\"Stone Sans Sem ITC TT\": {\n\"default\": 155, \n\"widths\": \"D\\\\}¡ïÑRiiMVMtMMÆ© ­Â¾¾OP¥ìÀËÍ·§û¦ee¤¤V¢¡MNIð¡¤¤gnbÓ}hwh\\\\£QÊmkmm¡Mi©©©©©©Ý­OOOOÈÀËËËËËýÏ····«ÙMMMM¡ñ¤ßMRsåZZ\", \n\"height\": 313\n}, \n\"PT Mono\": {\n\"default\": 154, \n\"height\": 287\n}, \n\"Corsiva Hebrew\": {\n\"default\": 177, \n\"widths\": \"@3UfO³1//OU1M3Affffffffff33^U^FÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  KAK¢¡¡^ JNJï¡¡i`ÅK9K¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡i11SS\", \n\"height\": 239\n}, \n\"Trattatello\": {\n\"default\": 157, \n\"widths\": \"FMsu¨þ@EIttBR>Z}ssvuzluvFEzzÁzd¯|°KJ§ÓÑzv~© ¯þ´¤ºKKzVbPHfIDG`>8pMrTXT\\\\F@ufsZKZ®@Z¤9ºd³¹QtNT¯ITrgèd||||KKKKúÑÌt    ¤Àbbbbbb¤HIIIIAAAAZrTTTTTz^uuuus]säFFqÚĀĀĀ\", \n\"height\": 463\n}, \n\"HanaMinB\": {\n\"default\": 154, \n\"height\": 286\n}, \n\"BlairMdITC TT\": {\n\"default\": 242, \n\"widths\": \"M[MÃóĥñ(opÀ[[ïb×ÜÐâêÄåä[\\\\ÀºÔòďČđðßĘĐ]ÊöÒĽĐęôęĂðÚčîİììãsqØêçìÑÅñíT³ÙºēíòÖòåÐÂéÔĊÑÔÄjKh[Ê¼©òçÕ¹aÕòw¹ºòòòòòòŧČðððð]]]]đĐęęęęęƈÀęččččìôƕØØØØØØĸçÑÑÑÑTTTTìíòòòòòőÕòééééÔÖÔúFFđZZ\", \n\"height\": 307\n}, \n\"Beirut\": {\n\"default\": 177, \n\"widths\": \"&UUkk«@UUnQUe=gceae`deUQkklÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  U~UU¡¡^ JNJï¡¡i`ÅU@U¢Q¢¢¢¢`¢ÛUÌÛoÌll ¢QxUl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÇ±±±± ÚJJJJî¡ĀQQÀSS\", \n\"height\": 384\n}, \n\"Hoefler Text\": {\n\"default\": 212, \n\"widths\": \"@<hºæÉ:LLcp?S?Harhir{??pZÆ¼¦¼Ó§ÒÞqaÊùÜÔ Ô»¶ÈÅĠÊÈ«VRV^zZrvxVyH?BÔ_b^t³{uuA(A]<v È(Ò[{ÑGhdV®5[[Z¼¼¼¼¼¼ċ¼§§§§qqqqÓÜÔÔÔÔÔćdÔÈÈÈÈÈ¦rrrrrr²vxxxxEEEEÕeuuú55WÅ?iS\", \n\"height\": 304\n}, \n\"Apple Color Emoji\": {\n\"default\": 154, \n\"height\": 336\n}, \n\"Sukhumvit Set\": {\n\"default\": 145, \n\"widths\": \"B?TÅ¡0LL<Q<^BB}Ñ¦¥¨>aÉª°°ªáG^GmLuV<<<Ì^oYv­{sO?O??°sZOMq<es}Ñ>>>>¦ª°°°°°þ°ªªªªÌu<<<<×ý55NµSS\", \n\"height\": 406\n}, \n\"Optima\": {\n\"default\": 142, \n\"widths\": \"GUUä¹GGGrGUGGGGdÍ««ÇÇÇGGäÇÕÕÇ«ĀUUUGGGGÕUdGÇUUUUUÀÀfUUÍGWd««««««Õ«GGGGÇÇÕÕÕÕÕĀÕÇÇÇÇÇGGGGäĀGGĀSS\", \n\"height\": 311\n}, \n\"Kannada Sangam MN\": {\n\"default\": 177, \n\"widths\": \"C3TËé½.OJ¨8Z5R58¨Ù­£ºµÂ±6~¨Î®ÆÈ¡£­î£ >O8y¡7N625ÕQLÁ|}yT2O«Q¢¢¢¢`¢ÕÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ü77ZĀSS\", \n\"height\": 416\n}, \n\"DecoType Naskh\": {\n\"default\": 162, \n\"widths\": \"6bAYY« WW{~QWm¢¢¢¢¢¢¢¢¢¢WQ]m]lÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  W>muÇ¡¡^ JNJï¡¡i`Å´,´¢Q¢¢¢¢`¢Û`ÌÛoÌll ¢Qx`l±±±±±±è±JJJJÀ½ÇÇÇÇÇĀ_Ç±±±± ÚJJJJîg¡ĀQQ¾SS\", \n\"height\": 465\n}, \n\"Chalkduster\": {\n\"default\": 184, \n\"widths\": \"[Ă«Ûë6p OW®°°ë¤«ÍTk{­|~Ö½«Ð³½¿Ĝ¨¢×¶º¶¾ÇÄ¶¾èÝË´®`±¡È¯exÇxă¼¸¥u°Ñ£¦xPªhÀ£­4û¸Đq^^ãÛa¥£«°µ«±¥Ĥ¸Ãµ°³¸¸µ³µµŋë¸»µ´ÝÁ£¨¥­£¨ñ¨«£¨kUkYÀ¼½µÅÃĠ¸Ã½Ã¸£®QR þĀĀĀ\", \n\"height\": 335\n}, \n\"Chalkboard SE\": {\n\"default\": 146, \n\"widths\": \"bAtÌÐµ2QQAzLI]m}qsÑ¥£ªqÔ¨ºÃ ¨¥ý¨¨OL|£L~o@cM½}pnuw¸X@Z¤]} £@zæßf_T©U¥¥¥¥¥¥åqqtq§ªºººººèº¨¨¨¨o Ò~DEPSvÇ}k£FCsÁĀĀĀ\", \n\"height\": 365\n}, \n\"Hannotate SC\": {\n\"default\": 155, \n\"widths\": \"UZR¦»Ð0LLsF]DDFä¢£¡¤>~½ ª¶§½¡TTsLc~EN@¬r~f|w£x`KaUZ~±¯­G¥¥ge¢¢¢¢¢¢ÓZZZZ¯ ªªªªªØ¬­ZZZZµ||||ĀAAĀR\", \n\"height\": 358\n}, \n\"Bodoni 72 Oldstyle\": {\n\"default\": 125, \n\"widths\": \"0[·»[NNBNB}Qxsxu}ly}BBjý§·ª¶PTªÁ¨¸¹ª¢é N}Nf{iznDxz@=x<´}{}wW]I}blgeNN®[ÎkÎ[[}B\\\\kjï§PPPP·¨¸¸¸¸¸ò¸ªªªªffffff¨innnn@@@@{}{{{{{¿{}}}}}gCC±Ç?iS\", \n\"height\": 308\n}, \n\"Hiragino Mincho ProN\": {\n\"default\": 204, \n\"widths\": \"UUW®¡ÔÎ0PPd®PTPdPP®Ø½ªµÃ¢ÃÌZz³îÌÌÌ®¨Å»Ā¸¸©PdPTLJLæirVË~PPU¡¦¦¡·k®·[®dd¡Pdk½½½½½½øµ¢¢¢¢ZZZZÃÌÌÌÌÌÌą®ÌÅÅÅÅ¸£ÓLLLLâ®ĀKK¡Ā7\\\\S\", \n\"height\": 397\n}, \n\"Gurmukhi MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 381\n}, \n\"Bangla MN\": {\n\"default\": 177, \n\"widths\": \"UUpûé4nnvªLWAM¨¨¨¨¨¨¨¨¨¨AO±²±ěÆÂçæ¯îØSÓ¡ĐÖû¦ù½ ¼ÖÄĐÅ¾Á\\\\M[[¬£®©s´£EHEČ£¸®®ud¦ì _1_ Q¢¢¢¢`¢éÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ìDDiĀSS\", \n\"height\": 490\n}, \n\"Devanagari Sangam MN\": {\n\"default\": 177, \n\"widths\": \"50O¾Û²+JF|5T2M25Ì·«º£B|¦À£¼À¥ Ü¢:K5r4V7-7ÍPOu°urO/J Q¢¢¢¢`¢ÈÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡¼44TĀSS\", \n\"height\": 468\n}, \n\"Baghdad\": {\n\"default\": 162, \n\"widths\": \"BDH«z#ba{{Q{R{¢¢¢¢¢¢¢¢¢¢RQ`{`lÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  ayiyÍ¡¡^ JNJï¡¡i`ÅJ.J¢Q¢¢¢¢`¢ÛtÌÛoÌll ¢Qxtl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀ{Ç±±±± ÚJJJJî{¡ĀQQSS\", \n\"height\": 371\n}, \n\"Seravek\": {\n\"default\": 140, \n\"widths\": \"7Lk¬é½>VVhC[BkZz|tBAuÐ­¯­¯C@yÙ¶½½­ò\\\\k\\\\jgr|[=<}GÜ\\\\kdxÁ~vtgDgN¢DÐfd]B|u­­­­­­áCCCC»¶½½½½½ô¿­­­­Ír||||====ÜvvÅ>>fÅSS\", \n\"height\": 314\n}, \n\"Nanum Gothic\": {\n\"default\": 155, \n\"widths\": \"HmnėºN]]§N]N`NN§ßº¬ºÌº>]¤|øºÉÉºªćªª]÷]§>|]>E>è]m]|Ùw|N>N§Mññ×ñ`YÛñññrin Jñ§±§±±±ÙJJ_cË½ÇÇ³ÇÇÝÈ¤±¤¤ ¯êJJ_cò¦Ý//ññv{JJ\", \n\"height\": 295\n}, \n\"Gurmukhi MT\": {\n\"default\": 123, \n\"widths\": \"XA\\\\¢»³5UUf{0Y0]{{{{{{{{{{<<{{{PÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  Q]Q{T¡¡^ JNJï¡¡i`ÅQIQ{Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀ{Ç±±±± ÚJJJJîÌ¡á77²SS\", \n\"height\": 334\n}, \n\"Helvetica Neue\": {\n\"default\": 142, \n\"widths\": \"GBmĀ¡GBBZGdGUGGÍ¦¯¹´Â¹B«ß¹Ã¦Ã¯¦¹í¦BUB9L999ÚUQÂ{U9UB9ÍwÍfUUGbw¦¦¦¦¦¦í¹BBBB´¹ÃÃÃÃÃēÃ¹¹¹¹¦¦ß9999äĀGGZĀUU\", \n\"height\": 306\n}, \n\"Apple Chancery\": {\n\"default\": 142, \n\"widths\": \"GBac¼ã5WWr5]5onv|55]±¸¹Ø»´ªÙutÍ¤þâ°«±ÊÃÛ±æ´¥QYQr|b_PwLDvDÊn|k[[s¡iY4YBu£4ÅÅE^^L]¸¸¸¸¸¸ö»»»»uuuuØâ°°°°°ā°ÛÛÛÛ¥®b____LLLLxnnnnnªnÜ55ÜĀĀĀ\", \n\"height\": 405\n}, \n\"Libian SC\": {\n\"default\": 128, \n\"widths\": \"@Uhà¢.UUo@@iW<@rÛ¤«¢¨¢°U­{Ó¹§¨å¹¢lxĎU}rrhvGcG±]jT¹r3ĎĀĀĀĀĀäĀ}}rrrHH¹ĀĀĀĀZĀĀĀS\", \n\"height\": 358\n}, \n\"Hiragino Kaku Gothic Pro\": {\n\"default\": 168, \n\"widths\": \"UP[¨¦áÌ2[[Y¨=\\\\=y¨¨¨¨©¨¨¨¨¨==¨èÀ¶ÂÂ¥ÁÇ@µòÆÌ©Ìº«¦Æ¸Ă¹°«YyY¥¥k¤=D;î ¦¥ndÅY`YP¨±_¤w¨M¨ee=nwÀÀÀÀÀÀďÂ¥¥¥¥@@@@ÄÆÌÌÌÌÌĊ¨ÌÆÆÆÆ°¥¡øONNF¥     ą¨ ¦Ā=={Ā7_S\", \n\"height\": 409\n}, \n\"Apple Braille\": {\n\"default\": 162, \n\"widths\": \"XQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 285\n}, \n\"GungSeo\": {\n\"default\": 256, \n\"widths\": \"Ef¤zø°@EERæEPEuuuuuuuuuuEEÀhýª z ­RkØ­  u  ízEEĀ@mhhMp@@@ºuzzZZMºzmUEUýĀĀĀĀĀ4ĀĀĀĀÅĀĀĀĀĀĀĀĀĀ¸¸¸¸¸¸Ā»»»»uuuuĀâ°°°°°ĀĀĀÛÛÛÛ¥ĀĀĀb____LLLLxnnnnnĀĀĀĀĀĀĀĀĀĀĀĀ\", \n\"height\": 258\n}, \n\"Silom\": {\n\"default\": 171, \n\"widths\": \"@ÕëÕ@kkUU««««««««««UU««ë««««««ÀĀÀ««««««Ā«««kk««««««««U«UĀ««««««Ā«««kkk«À««kÕÀÕÕÀUÀ«««««««ë««À«««««ë«««««««««««««««Ā««««UUUU«««««««Ā««««««««ÕUUīZZ\", \n\"height\": 327\n}, \n\"Kokonor\": {\n\"default\": 142, \n\"widths\": \"OBac¼ã5WWr5]5onv|55]±¸¹Ø»´ªÙutÍ¤þâ°«±ÊÃÛ±æ´¥QYQr|b_PwLDvDÊn|k[[s¡iY4YBu£4ÅÅE^^L]¸¸¸¸¸¸ö»»»»uuuuØâ°°°°°ā°ÛÛÛÛ¥®b____LLLLxnnnnnªnÜ55ÜĀĀĀ\", \n\"height\": 527\n}, \n\"Nanum Pen Script\": {\n\"default\": 177, \n\"widths\": \"HFC¡ls?OHhn<_3Q\\\\1dMwbLWS\\\\NNsfsZ}vjX]idt6Mrpvphwsf~oj¥vmWZ_{>\\\\V][Z_Wj>Ih6mgbg\\\\Whigbhw\\\\>\\\\Mññ×ñ`YÛñññrpii Jñ±±±±±±è±JJJJË½ÇÇÇÇÇĀ`È±±±± ¯ÚJJJJî|Ý@@ññv{JJ\", \n\"height\": 295\n}, \n\"Thonburi\": {\n\"default\": 171, \n\"widths\": \"UN««èºNrr«NaN««««««««««NN«««ßº£§³­±>~ªÊµ¼¼¤«ºòrr««d<G<åcrÈs?s«N««««?«á«áW«gg««_ººººººþ§>>>>³¶¼¼¼¼¼ė«¼««««î<<<<ÿ«ĈNN«ĈSS\", \n\"height\": 352\n}, \n\"Zapfino\": {\n\"default\": 256, \n\"widths\": \"ÑÓîƌȵêĄ£ĀÊìę­ċàĎ¾ÜÜ×ÜĀĀĀ®ŴŔĸŊůİàŬŮÐŁĚǠşŹčŞňÓÿƋĚǣŗāĘØìáĀŀ¶£­ªt}Àá§ ¤}s¤ñ ªªĀëĳùęÁƚÖĀĀĀ  Āŀç¦ŔŔŔŔŔŔǱŊİİİİŨşŹŹŹŹŹțĀŹƋƋƋƋāċ¶¶¶¶¶¶Ätttt¨     äĀ¤¤¤¤ʀŀųĀĀĀ\", \n\"height\": 865\n}, \n\"Kaiti SC\": {\n\"default\": 131, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxzxxxxx88«««]ë¯ ¥Æ©ÅÈ[U¾âÇÇÄ¤|·°å´ª©EEUlnV{=;}EÈXbWy«uoo{{«8i©­ĀÃ]«Ã]­PTsJU]]¯¯¯¯¯¯ö£©©©©[[[[ÆÇÇÇÇÇÇð®Ç····ªlnnnn====³ÄooĀ?C[ĀĀĀĀ\", \n\"height\": 358\n}, \n\"Bank Gothic\": {\n\"default\": 198, \n\"widths\": \"cbMÅÆÍÓ(UUÕUTUGÆÆÆÆÆÆÆÆÆÆUUÕÕÕ©ĀÅËÍÙÁ¬Ûáb«Ë¯íÞá¾áÍÏ Ù®í¸¬¯UGUĀ¥¨¥²±¸JÄ¶·¡·¦ª°¢Ê£ÕbÆÆÆÕÕÕTÕUy©ÅÅÅÅÅÅĒÍÁÁÁÁbbbbÙÞáááááěÕáÙÙÙÙ¬¾œ¥¥¥¥¥¥æ¥JJJJ²¶·····èÕ·°°°°¡ĀUUĀZZ\", \n\"height\": 265\n}, \n\"Latin Modern Roman Slanted\": {\n\"default\": 128, \n\"widths\": \"UG`ÕÕÇGddÇGUGGGÇÇÇyÇÀµ¹Ä®§ÉÀ\\\\Ç ëÀÇ®Ç¼¹ÀÀćÀÀGGÀrrNGNGÕded¹rGGrÀÇÀG|¯Ç¯`Ç\\\\\\\\ÇkyÀÀÀÀÀÀç¹®®®®\\\\\\\\\\\\\\\\ÄÀÇÇÇÇÇĄÇÇÀÀÀÀÀ ¹rrrrrGGGGÇÇĀGGÇ¬SS\", \n\"height\": 363\n}, \n\"Arial Narrow\": {\n\"default\": 117, \n\"widths\": \"::Kuu»(FFR{:F::uuuuuuuuuu::{{{uÕ£:iu¯££Æ:::cuFuuiuu:uu//i/¯uuuuFi:uiiiiF7F{Fuuuu7uu{fFFqFMuÒ::::£££££Ò{£uuuuuu»iuuuu::::uuuuuuuÆuuuuiuiÒ//JÒ(KS\", \n\"height\": 294\n}, \n\"Gujarati Sangam MN\": {\n\"default\": 143, \n\"widths\": \"M/N¼Ø°*JEz4S1L14Êµ©·¡A{¤¾¡º½£Ú 9J4p3U6,6ÊO~Ns®tqN.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 396\n}, \n\"Wingdings\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 284\n}, \n\"Latin Modern Mono Light Cond\": {\n\"default\": 90, \n\"height\": 336\n}, \n\"Gill Sans\": {\n\"default\": 128, \n\"widths\": \"GE[­ 0SSk8S8H8;Uă«µÀx¾»@@¨~ÈÈÓÓuµċµ¥UHUxUmp{@m88{8ÅecUp¸pkUCUEpCh¾~¾eSSU^~U««««««åµ@@@@ÀÈÓÓÓÓÓëÓµµµµmmmmmm«p{{{{8888ÕppĀ88[ĀSS\", \n\"correction\": 1.02, \n\"height\": 294\n}, \n\"Malayalam MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 361\n}, \n\"ForMateKonaVe\": {\n\"default\": 154, \n\"height\": 349\n}, \n\"Khmer Sangam MN\": {\n\"default\": 143, \n\"widths\": \"M/N¼Ø°*IEz4S1L14Éµ©·¡A{¤¾¡º½£Ú 9J4p3U6,6ÊO~Ns®tqN.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 524\n}, \n\"Kohinoor Devanagari\": {\n\"default\": 135, \n\"widths\": \"JJS«Ô®-QQg=V9Why{m9=}ê¥~£°Jc~Ú³ª¬z®íOWO|y\\\\JAJÜ\\\\yb|Â{sTETHyFÕ~YYZ;x~gÚJJJJ§³¬¬¬¬¬÷¬®®®®ÙyJJJJê¬CCsÈSS\", \n\"height\": 384\n}, \n\"JiaguRic A\": {\n\"default\": 128, \n\"widths\": \"@UiÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĀ?iS\", \n\"height\": 306\n}, \n\"STIXVariants\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`SRS¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀWW\", \n\"height\": 386\n}, \n\"Athelas\": {\n\"default\": 126, \n\"widths\": \"6=GÈ´&IIa~8P7LSpj{i{g{{7;~~~aÐ°«Â¶¿WYªæ¹ÀÀ¦¦Ã®ý¦NOK~gyowO|FEHÕacOz¹|mQAQ=Az±j~pO~WWr6aja°°°°°°é«WWWWÆ¹ÀÀÀÀÀö~ÀÃÃÃÃyyyyyy¸owwwwFFFF~Î~||Ā9:~Ç?iS\", \n\"height\": 286\n}, \n\"Osaka\": {\n\"default\": 171, \n\"widths\": \"GN««èºNrr«NaN««««««««««NN«««ßº£§³­°>~ªÊµ¼¼¤«ºòrr««d<G<åcqÈs?s«Q´¢«`áìÛdÄll Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀºÇ±±±± ÚJJJJîÖ¡ĀĀT~S\", \n\"height\": 363\n}, \n\"Noteworthy\": {\n\"default\": 166, \n\"widths\": \"DCAÍÅ$>BR¦6[+²7§¶È¬¬ª->s~s¢Ċ£¢ ±7yÐ· ·°À³µ<<\\\\?tmtul]si-9z(£uupqWrWjq£vo\\\\$\\\\C­¨¼$rôj¦_¦gqj-af¢¦¦¦¦¦¦Ē??\\\\M¥±±±±±Ď¦± pppppp¾qnnnn/)/+urrrrrrÁ¦rggggvpsþ99K·ĀĀĀ\", \n\"height\": 414\n}, \n\"Courier New\": {\n\"default\": 154, \n\"height\": 290\n}, \n\"Bodoni 72 Smallcaps\": {\n\"default\": 136, \n\"widths\": \"03·[NNBNB}Qxsxu}ly}BBJý§·ª¶PTªÁ¨¸¹ª¢é N}Npkukgx=?|jzcp]m{u¨sphNN®3ÎkÎ[[}B\\\\kJï§PPPP·¨¸¸¸¸¸ò¸ªªªª¹pppppp¬ukkkk====z¯{{{{cpCC±Ç?iS\", \n\"height\": 307\n}, \n\"Marker Felt\": {\n\"default\": 146, \n\"widths\": \"@3O³)CCwq1_1;1adaiè}s}nl}=nlîs}{óddM}6vnana\\\\lx36{3¸}inna_\\\\iq¸ix{d4dT3`£¡t_qz;qgnx1sqi~½t\\\\\\\\]]65J?}ppqprÅoqpostttttt©`aaaa46XPk~jijjj¬_ljjjjxnxĀ:A¥ĀĀĀ\", \n\"height\": 278\n}, \n\"STIXIntegralsUpSm\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 386\n}, \n\"Trebuchet MS\": {\n\"default\": 134, \n\"widths\": \"M^Sµ)^^^^^^^^^Å­¨Gz¶£­­{¦Ú^[^_I^LÕdhf}¿~z^^^t··tt^^^ÞGGGG£­­­­­þ¨¦¦¦¦àIIIIí~~¼^^¼)WS\", \n\"correction\": 1.025, \n\"height\": 297\n}, \n\"Marion\": {\n\"default\": 119, \n\"widths\": \"MMP{ÃÀ'HHsAN<]e}v}w~k<=iia¶¨­§Â¥ºÑcq¹ä¾¿¡ÂªÁ§ê° 6p8lrKq~gnLsK=KÍw~b]Ls©yoe>L>Cm®LaÂÂSSP¢<[_¨¨¨¨¨¨ê§¥¥¥¥ccccÂ¾¿¿¿¿¿ď¿ÁÁÁÁ qqqqqq±gnnnnKKKKwwwwwwÂwoo¿77JÙSS\", \n\"height\": 306\n}, \n\"TeX Gyre Heros\": {\n\"default\": 142, \n\"widths\": \"GG[ä«1UUdGUGGGGĄ««¹¹«Ç¹G«Õ¹Ç«Ç¹«¹«ò««GGGxUG999ÕUG¹VCVGC½½fUUG]««««««Ā¹««««GGGG¹¹ÇÇÇÇÇĀÇ¹¹¹¹««äGGGGòĀ99ZĀSS\", \n\"height\": 367\n}, \n\"Skia\": {\n\"default\": 177, \n\"widths\": \"@w_±lý»6jj]±CWCUbv{|RR±±±æª¤»°ÈO`¢òÊÂÂ¢ÁªČjUj±dt^DEDàchdÎzjKj±wu|Ktñ±ñi±iiCiªªªªªªéOOOO»ÊÂÂÂÂÂþ±ÂÁÁÁÁÏtDDDDç±Ā66ĀSS\", \n\"height\": 256\n}, \n\"Nadeem\": {\n\"default\": 162, \n\"widths\": \"B>:do«z#JJ{oQo>o¢¢¢¢¢¢¢¢¢¢>QHoHlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  JoJbÃ¡¡^ JNJï¡¡i`ÅJ>J¢Q¢¢¢¢`¢ÛJÌÛoÌll ¢QxJl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀoÇ±±±± ÚJJJJîo¡ĀQQtSS\", \n\"height\": 372\n}, \n\"Kaiti TC\": {\n\"default\": 131, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxzxxxxx88«««]ë¯ ¥Æ©ÅÈ[U¾âÇÇÄ¤|·°å´ª©EEUlnV{=;}EÈXbWy«uoo{{«8i©­ĀÃ]«Ã]­PTsJU]]¯¯¯¯¯¯ö£©©©©[[[[ÆÇÇÇÇÇÇð®Ç····ªlnnnn====³ÄooĀ>C[ĀĀĀĀ\", \n\"height\": 358\n}, \n\"STIXNonUnicode\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 521\n}, \n\"Impact\": {\n\"default\": 140, \n\"widths\": \"-E_ ±/PPH+K/ebd44ÆjfJUa¸vÑ|yfHeH|UJFHzFÅ\\\\yNp«osZ_E_EyE|É_ÉYQTyUT_·jjjjJJJJ°yÁFFFFÄssĀ++Y/cZ\", \n\"height\": 312\n}, \n\"Snell Roundhand\": {\n\"default\": 114, \n\"widths\": \"@UUÇ9ddU@U@G_@@rÍòä«ä«ÇÕäĀ¹ÇÇ¹äÇÕ¹òÕÇ«d9d9rrUrU9rr99r9«rrrrUUGrr«rdd9dU¾9ÍrÍfMMr@DrròòòòòòĀ«««««ä¹ÇÇÇÇÇĀ¾ÕÕÕÕÇÇrrrrrrUUUUU9999rrrrrrrrrrrrrrrĀ99ĀĀĀĀ\", \n\"height\": 312\n}, \n\"Lao Sangam MN\": {\n\"default\": 143, \n\"widths\": \"M/N¼Ø°*IEz4S1L14Éµ©·¡A{¤¾¡º½£Ú 9J4p3U6,6ÊO~Ns®tqN.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 356\n}, \n\"STFangsong\": {\n\"default\": 256, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxxxxxxx88«««]ë­£Å¨ÅÃ[U½ÕÅÈÅ {µ²çµ­¨EEUrkk]u;;x;Å}U]K}|°umm{{«8kĀ­ĀÃ]«ÃĀĀPPsĀU]]­­­­­­æ£¨¨¨¨[[[[ÅÅÈÈÈÈÈðĀÈµµµµ®rrrrrrkllll;;GB³Ā}}}}mmĀĀĀ[ĀĀĀĀ\", \n\"height\": 256\n}, \n\"PT Sans Narrow\": {\n\"default\": 115, \n\"widths\": \"6?Iss£¨.<<Jj)J(Lssssssssss17jjj[Ûyyunj~<>~j£s{nrw¬tp?Q@iVAfo[ojBoq87c<§poooFWFoci`\\\\H1Hj?ssss0h±cjXjTTsg7Sc[yyyyyy¯unnnn<<<<¿jtt}ffffff¤[jjjj8888spooooo±jpoooo`o`©))]¨SS\", \n\"height\": 332\n}, \n\"Latin Modern Sans Quotation\": {\n\"default\": 160, \n\"widths\": \"k[ċ ċðY|| ùYkY           YYÓùÓÕÎÒÍäÇ¾ÕÐR×µąÐ÷É÷Ñ²åÏÎħÎÎÄZZÎ   b  GPGù    k{s ÕL[ÎùÎL­¯ ù¯xùqs ¦ù ÎÎÎÎÎÎĐÍÇÇÇÇRRRRäÐ÷÷÷÷÷ĳùùÏÏÏÏÎ·çGGGG       ùù      ŀYYùÅSS\", \n\"height\": 357\n}, \n\"Zapf Dingbats\": {\n\"default\": 162, \n\"widths\": \"GQ`¢¢«³;dd{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅV`V¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 253\n}, \n\"Al Nile\": {\n\"default\": 177, \n\"widths\": \"66/¢«z#QQ{lQlhZuOseuimmgmhQllÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡¡^ JNJï¡¡i`ÅSHS¢Q¢¢¢¢`¢ÛQÌÛoÌll ¢QxQl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀlÇ±±±± ÚJJJJîl¡ĀQQSS\", \n\"height\": 452\n}, \n\"RicpyHum\": {\n\"default\": 150, \n\"widths\": \"JgMÅÞ²(SSÕJWJGJJÕÕÕĀ©°z¶®E\\\\wêµ¼¼±¢ò¢TGTĀwZ@@@â\\\\l^zÐvzxÕg¢`ÕÕÕTÕaaJq©©©©©©çEEEEÀµ¼¼¼¼¼îÌ¼±±±± Õw@@@@êÕ¡zĀJJĀSS\", \n\"height\": 316\n}, \n\"Damascus\": {\n\"default\": 162, \n\"widths\": \"BQ`¢¢«³;SS{ÌQ>¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 389\n}, \n\"Arial Black\": {\n\"default\": 171, \n\"widths\": \"UU©«ĀäGdd©UUUG««««««««««UU©©©¾ÇÇÇÇ¹«ÕÕd«Õ«òÕÕ¹ÕÇ¹¹ÕÇĀÇÇ¹dGd©U«««««d««UU«UĀ««««rr«ò«dGd©U««©«G«Í«©Íf©ff«ÚUf«ÇÇÇÇÇÇĀÇ¹¹¹¹ddddÇÕÕÕÕÕÕĀ©ÕÕÕÕÕÇ¹«««««««Ā«««««UUUU«««««««Ā©««««««ĀGGĀNZ\", \n\"height\": 361\n}, \n\"Hiragino Kaku Gothic StdN\": {\n\"default\": 198, \n\"widths\": \"U]uÉÇþîNrrl·NyNÆÆÆÆÆÆÆÆÆÆNN·­ùßÌØÛ»°×àX°Ü°ćàâÃãÒÄÆãÜĜéÖ¿ww¦³Å­Å°¾¼Q^»PĘ¼·ÆÆ§{¼´ïµ¶xyx­]ºÐ¢ÚxĀ±·ĀĀuu¼ĀN±­ßßßßßßłØ»»»»XXXXÝàâââââĳĀâããããÖÂ±³³³³³³Ĝ­°°°°__fiÃ¼·····ĤĀ·¼¼¼¼¶Æ¶ĀNNĀĀĀZ\", \n\"height\": 434\n}, \n\"Bangla Sangam MN\": {\n\"default\": 177, \n\"widths\": \"W6YÖ¤öÈ0TN±;_8W££££££££££8;¦±¦å²°ÎÀª¡Ð·JºØ·Ô§×°²¹´¤ø¦¶AT;ª:¥¡a>2>æ£ZYÆX5S´Q¢¢¢¢`¢áÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡è::_ĀSS\", \n\"height\": 383\n}, \n\"Palatino\": {\n\"default\": 128, \n\"widths\": \"@G_×Ç5UUd@U@@@r¿Ç¶ÆÃÕVUºòÕÉÉ«Ç¹Ā«««UUUr{UK<KâemTÖUUG¿¿fMM¡@UrÇÇÇÇÇÇò¶VVVVÆÕÉÉÉÉÉĀÕÇÇÇÇ«Âr{{{{JJJJÔĀGGĀ8kS\", \n\"height\": 301\n}, \n\"AppleGothic\": {\n\"default\": 256, \n\"widths\": \"R`f®®ĀÑfw¯HX®®®®®®®®®®ÅĀº¥¯¯¾´7¥éºÇÉ¤¢©¼¶Ć·²¨@W)G+åZXÖ»U¢¶Ü¯`|÷ĀĀÛĀĀZZ Ā:tĀt±±±±²±©±JJJJ½ÇÇÇÇÅ©Ā±±±Á \\\\JJJJĀsUĀ44ĀĀĀĀĀ\", \n\"height\": 463\n}, \n\"Arial Rounded MT Bold\": {\n\"default\": 152, \n\"widths\": \"@U{ÛÃ>[[pPUPHPPû¸¸¾¾«ËÃP¾ÕÃË«Ë¸« Ã°ð ¥[H[U  U EEEã  p[ÐcHcU H¾¾e[[Qc¸¸¸¸¸¸þ¾««««PPPP¾ÃËËËËËĈËÃÃÃÃ «íEEEEõ ĀPP[ĀSS\", \n\"height\": 296\n}, \n\"Lantinghei SC\": {\n\"default\": 256, \n\"widths\": \"GNV¢ùÅ.]]r¨JJK|IJ§¤¦ĝ¼»ËÊ»«ÚÉAºëÊÛ»ÚÊº¬Ì¾ĉ¼»«MLM¦YJ372è]MÊ]@]¤Q¢¢Ā¢`ĀÛÌÛĀĀll ¢Āxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀîĀĀĀĀ¡ĀĀĀĀĀĀĀ\", \n\"height\": 356\n}, \n\"Myanmar Sangam MN\": {\n\"default\": 143, \n\"widths\": \"M/N¼Ø°*IEz4S1L14Éµ©·¡A{¤¾¡º½£Ú 9J4p3U6,6ÊO~Ns®tqN.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 403\n}, \n\"Latin Modern Sans Demi Cond\": {\n\"default\": 122, \n\"widths\": \"QN}Ëzá¸D^^z½DQDzzzzzzzzzzzDDÇ½Çs¢££°¢®HsªÖ®²²¥¨£æ££KK£zt|l|pJ||8?u8¿|z||R]Y|n¤nniGNl£½£G~²z½²[½VW|´½fzs££££££ÒHHHH°®²²²²²í½½¨¨¨¨£xtttttt°lpppp8888z|zzzzz½½z||||n|nóDD½¥ZZ\", \n\"height\": 361\n}, \n\"Kefa\": {\n\"default\": 154, \n\"widths\": \"BWkď¶<QQ a_abaaðª ¬¢¼YXª×¼°±§ª¦ê®¥kbk/xaLKLÛktdÌxmJmW¢Jç±¸X°'d±ªªªªªªâUYU[®¼°°°°°ã°ªªªª¦ÅxLLL^ÕĀEEýSS\", \n\"height\": 297\n}, \n\"FZYingBiXingShu-S16T\": {\n\"default\": 228, \n\"height\": 282\n}, \n\"Diwan Kufi\": {\n\"default\": 177, \n\"widths\": \"\\u0018<V¢«z>^^{Q5smmmmmmmmmmMQjjlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢ā¡¡^ JNJï¡¡i`ÅqHq¢Q¢¢¢¢`¢ÛVÌÛoÌll ¢QxLl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÇ±±±± ÚJJJJî^¡ĀQQ¥SS\", \n\"height\": 481\n}, \n\"FZYingBiXingShu-S16S\": {\n\"default\": 228, \n\"height\": 282\n}, \n\"Xingkai SC\": {\n\"default\": 128, \n\"widths\": \">kM½±8aV\\\\«UUH|OoUU«ª«găÒ«¯±¬£«ËuxÀ´öª¬±Ä´ª½¤Õ«¤¨HªxUniMO^keJknPdUdRVWk^Seckk«ĀĀĀĀĀäĀmmOOPFJTT¹ĀgfjĀĀĀZĀĀĀS\", \n\"height\": 358\n}, \n\"Songti SC\": {\n\"default\": 256, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxxxxxxx88«««]ë®£Å¨ÅÄ[U¾ÙÆÈÅ£z¶®ã³©§EEUinTxE9yFÉ]]Sx«ulm{{«8kĀ±ĀÃ]«ÃĀĀPPsĀU]]®®®®®®æ£¨¨¨¨[[[[ÅÆÈÈÈÈÈðĀÈ¶¶¶¶©uuuuioook;;<<³Ā~nlĀ<E[ĀĀĀĀ\", \n\"height\": 358\n}, \n\"Webdings\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 256\n}, \n\"Sinhala Sangam MN\": {\n\"default\": 157, \n\"widths\": \"A4UÍìÀ.PKª9[6S69ªÜ®¥Ã¸Æ²4ªÐ°È¡Ìª§¥®£ò¦¢?Q9{£8Z323ÚTWÂU3P­Q¢¢¢¢`¢ØÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ß88[ĀSS\", \n\"height\": 377\n}, \n\"Raanana\": {\n\"default\": 177, \n\"widths\": \"DIa©k³³3@@^s3R3knnnnnnnnnn66ppSÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  DkD¢¡¡^ JNJï¡¡i`ÅBDB¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Â66·SS\", \n\"height\": 287\n}, \n\"STIXIntegralsUp\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 394\n}, \n\"Euphemia UCAS\": {\n\"default\": 149, \n\"widths\": \":aäì¾<QP{?^5@@||zĎ ªªª±;Ç±ÎÎ¸ß HH£\\u0000P>;?Ø^|Ww¬u{UU>v«à¬àQop9s}      òª;;;;ª±ÍÍÍÍÍùÏ¸¸¸¸Ð><<;óà33hÇSS\", \n\"height\": 348\n}, \n\"Latin Modern Roman Demi\": {\n\"default\": 128, \n\"widths\": \"UNqÕÕÇGddÇGUGGGåÇåyÇÂ¶¹Ä¨¡ÉÈfÈóÈÀ¯ÀÃ²ÅÂĈÂÂHHÂ|rxNGNGÕned¹rRNrÂÇÂR°Ç°`Ç\\\\\\\\´ÇkyÂÂÂÂÂÂè¹¨¨¨¨ffffÄÈÀÀÀÀÀĄÇÇÅÅÅÅÂ¡||||||¹rxxxxGGGGÇÇĀGGÇÅZZ\", \n\"height\": 367\n}, \n\"Cochin\": {\n\"default\": 128, \n\"widths\": \"@dUÕ¾9dd@U@G@@Í´¯´Õ¯¡ÇÕd¡¾¦÷ÑÕ¡Õ¹¦Ì´Ā¾¹´dGdBwrrQBBBÇddQ¾rd9cd9ÍrÍfMM@Mr´´´´´´÷´¯¯¯¯ddddÕÑÕÕÕÕÕĀÕÌÌÌÌ¹¡wwwwww¯rrrrrBBBBÂĀ99Ā?iS\", \n\"height\": 294\n}, \n\"Hiragino Mincho Pro\": {\n\"default\": 204, \n\"widths\": \"UUW®¡ÔÎ0PPd®PTPdPP®Ø½ªµÃ¢ÃÌZz³îÌÌÌ®¨Å»Ā¸¸©PdPTLJLæirVË~PPU¡¦¦¡·k®·[®dd¡Pdk½½½½½½øµ¢¢¢¢ZZZZÃÌÌÌÌÌÌą®ÌÅÅÅÅ¸£ÓLLLLâ®ĀKK¡Ā7\\\\S\", \n\"height\": 397\n}, \n\"Latin Modern Mono\": {\n\"default\": 134, \n\"height\": 341\n}, \n\"Braille\": {\n\"default\": 213, \n\"height\": 270\n}, \n\"Lucida Grande\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 302\n}, \n\"Capitals\": {\n\"default\": 171, \n\"widths\": \"UÕëÕ@kkUU««««««««««UU««ë«°«°«¶f|ÅöË«ª«°¶«û««¢kk¤««¯¯«¶a|°ö¶«¨«°¶«û««¢kkk««««kÕ«Õ««U««««««««ì«ffff°Ë«««««ì««¶¶¶¶«ª°««««««õaaaa¯¶«««««í«¶¶¶¶«ª«ÕUUĀ?iZ\", \n\"height\": 341\n}, \n\"Big Caslon\": {\n\"default\": 134, \n\"widths\": \"6N[À{¦Û9PPc³>B>PQpeer|CC«³«bÞ´¿ÇÚ¶¨ÓæffÄµþàÏ¨ÏÃ½Ö«þµ¦²IPIAsooEA?}?Ë[bSq½ujoI?IN®©>xĀe³h«D>¡CHeb´´´´´´ĄÇ¶¶¶¶ffffÚàÏÏÏÏÏû³ÏÖÖÖÖ¦¨ssssss°oooooAAAAË³jjä  Á\\u001a?\\u001a?\", \n\"height\": 310\n}, \n\"Papyrus\": {\n\"default\": 233, \n\"widths\": \":CSÃÈ3oo`GvGªAz©~vGGv{¼¹¾Ô¹¼Ä>·Ý§é¦é¯§²ÍÉ§ ªooIe658µcy]q¤}rA8ACx» ©8uééP\\\\WsAz{¼¼¼¼¼¼Ģ¾¹¹¹¹>>>>Þ§éééééūéÍÍÍÍ ¦è6666ĀđGGYĀSS\", \n\"height\": 395\n}, \n\"Latin Modern Roman Unslanted\": {\n\"default\": 142, \n\"widths\": \"dUrääÕUrrÕUdUUUÖÕÖÕÎÄÇÒ¼µ×ÎkÕ®ùÎÕ¼ÕËÇÎÎĕÎÎ«UUÎUUUGäur\\\\¹rMU²ÕÎM±Õ±kÕkd¨ÕwÎÎÎÎÎÎõÇ¼¼¼¼kkkkÒÎÕÕÕÕÕĒÕÕÎÎÎÎÎ®ÇUUUUÇÕĜUUÕ¾SS\", \n\"height\": 363\n}, \n\"TeX Gyre Chorus\": {\n\"default\": 113, \n\"widths\": \"8H8qq®È)C8l8H8WqqqqqqqqqqC=a³³®af©×³v½¤á={RMllWqWRfq=8q=vfqfMRRvq®lfq==Hqqqql½W½fDDv8Caa½aaaa³³Ò©½½½½lllllllWWWWW====fvfffffqvvvvfqfĀ==ĀZZ\", \n\"height\": 337\n}, \n\"Latin Modern Roman Dunhill\": {\n\"default\": 128, \n\"widths\": \"UGÕÕÇGddÇGUGGGÇÇÇyÇÀµ¹Ä®§ÉÀ\\\\Ç ëÀÇ®Ç¼¹ÀÀćÀÀGGÀrrNGNGÕded¹rGGr¤½À+|Ĝ«ĜUÇrrGryÀÀÀÀÀÀç¹®®®®\\\\\\\\\\\\\\\\ÄÀÇÇÇÇÇĄÇÇÀÀÀÀÀ ¹rrrrrGGGGÇÇĀGGīSS\", \n\"height\": 529\n}, \n\"Sana\": {\n\"default\": 177, \n\"widths\": \"&=9¢«z$MM{sQs/C^.]^q___^_;QÌsÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢ÿ¡¡^ JNJï¡¡i`ÅSHS¢Q¢¢¢¢`¢ÛMÌÛoÌll ¢QxMl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀsÇ±±±± ÚJJJJîS¡ĀQQåSS\", \n\"height\": 384\n}, \n\"Latin Modern Mono Prop\": {\n\"default\": 135, \n\"widths\": \"ZKoààÒKiiÒKZKKKÒ´Â»ÂÊ´¬ÒÂZÊ¥ïÂÒ´ÒÂÂÂÂčÂÂ¥LLÂxxSKSKàijiÂxKxÂÒÂÒeÒaaÒqÂÂÂÂÂÂïÂ´´´´ZZZZÊÂÒÒÒÒÒčÒÒÂÂÂÂÂ¥ÂxxxxxKKKKÒÒčKKÒ®\", \n\"height\": 336\n}, \n\"Monaco\": {\n\"default\": 154, \n\"height\": 341\n}, \n\"QXyingbixing\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 295\n}, \n\"STIXIntegralsD\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 677\n}, \n\"Mona Lisa Solid ITC TT\": {\n\"default\": 119, \n\"widths\": \".QwwwwQ>>ww/U/owQmhwrwZmw//w{¡«{w¡LLrÇ««{d¡òGoG_dLhU>hh99r9h_hhLG>hZZhZUUÊQwwwwwìwìwwMMg/<w{¡¡¡¡¡¡Ú{{{{LLLL««««««Úw«¡¡¡¡d______LUUUU9999_h_____w_hhhhhhh//Ê?iZ\", \n\"height\": 304\n}, \n\"DIN Condensed\": {\n\"default\": 95, \n\"widths\": \"0=G__Z{099_0d09__________00_Íhmhm__mm4Um_rmhmmhUmhdcU9990_d_d_9dd00d0d_ddGZ4dZUZQ999=____9_ÍmÍC>>dr0=m_hhhhhhh____4444mrmmmmmmmmmmchd___________0000_d______ddddZdZĀ00ĀZZ\", \n\"height\": 307\n}, \n\"TeX Gyre Pagella\": {\n\"default\": 128, \n\"widths\": \"@G_×Ç5UUd@U@@@r¿Ç¶ÆÃÕVUºòÕÉÉ«Ç¹Ā«««UUUr{UJ<JâemSÖUUG¿¿fMM¡@UrÇÇÇÇÇÇò¶VVVVÆÕÉÉÉÉÉÿÕÇÇÇÇ«Âr{{{{IIIIÔĀGGĀSS\", \n\"height\": 353\n}, \n\"Yuppy SC\": {\n\"default\": 256, \n\"widths\": \"GG[Ñ©1UUdGUGMGGò°¡´¯¤º©G~¤É«Ã¤Â¥¥¡¬­ó­« GMGxUT9E{9ÎX|NÅVCVQ¢¢Ā`ĀÛÌÛĀĀll ¢Āxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀîĀĀĀĀ¡ĀĀĀĀĀĀS\", \n\"height\": 358\n}, \n\"Latin Modern Mono Slanted\": {\n\"default\": 134, \n\"height\": 341\n}, \n\"STIXSizeThreeSym\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;ÀÀ{ÌQQĚ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  Ě¢Ȁ¡¡^ JNJï¡¡i`Åè`è¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 805\n}, \n\"Wawati SC\": {\n\"default\": 85, \n\"widths\": \"UUV¸Å+UUqq1U4G³³³³³³³³³³67qqqº¸¥¦¬ ¯¦n¥¤Á´Á§½¨®¿¾Ó§¨UGU[Uq}h=M{2´|vgi]~|scQ,QUUy¨³,z£qPqfh]£······ÿ§¢¢¢¢llll°´ÁÁÁÁÁüqÁÄÄÄÄ¨»Ïu}}}}<<PUÜqĀUUĀĀĀĀ\", \n\"height\": 358\n}, \n\"Latin Modern Sans\": {\n\"default\": 128, \n\"widths\": \"URoÕÕÂGddÇGUGGGÇÇÇy«««¤¹«µGy²àµ¼¤¼¥®°«ò««JJ«{rrN=D}=ËXb\\\\v¯vvoGRr«Ç«G²Ç²`Ç[\\\\Çky««««««Ü¤GGGG¹µ¼¼¼¼¼ùÇÇ°°°°«{{{{{{{¹rrrrr====ÇÇvvĀGGÇ SS\", \n\"height\": 374\n}, \n\"Jazz LET\": {\n\"default\": 206, \n\"widths\": \"ac`ăé8ijbQYQ½t¦²¨°QQî§À©ÅÀÈadÂÖ°Î¾ÎÀ ©­Ý±¬eee¦¨­fªTTTû«¤¬©rp«½e8ed¬8¿v¿vMMUUw§§§§§§ë©aaaa¹°ÎÎÎÎÎāÎ­­­­¬°¦¦¦¦¦¦ïTTTT«¤¤¤¤¤ð¤««««ĜQQeĀ?iZ\", \n\"height\": 362\n}, \n\"HeadLineA\": {\n\"default\": 104, \n\"widths\": \";k `°0CCSþ0M0hhhhhhhhhh00Àkþvupx]]x{=ku` ~{p~vhg{m«sp`KKmç0eh`hc?ee8;e8eehhK`He```IUFUþP©©©©c©ĀÌ×oÌ{{±©¤{½½½½½½õ¶UUUUËÅÓÓÓÓÓďÌÓ½½½½°©âSSSS¤¨¤¤¤¤¤öÌ¤¨¨¨¨ªĀ?? çZZ\", \n\"height\": 258\n}, \n\"STIXSizeOneSym\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;xx{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  bb¢Ā¡¡^ JNJï¡¡i`Å`¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 510\n}, \n\"GB18030 Bitmap\": {\n\"default\": 162, \n\"widths\": \"ĀQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 320\n}, \n\"Herculanum\": {\n\"default\": 161, \n\"widths\": \"GQMÕÕ\\u0014UUhGUG_Uw{wGG{«¦{¡´UUÌīí¡¯dèÚò¡Ú¯U_UGG¾¦{¡´UU÷¾¡¯Ìd´¡ò¡¡U3UíQùrÍ{ÍfVM´Ga{{««««««¹{{{{UUUU¦í¡¡¡¡¡Ú¡¡èèèèÚÇ¾¾¾¾¾¾¹{{{{UUUU¦¾¡¡¡¡¡Ú¡´´´´ĀGGfĀĀĀĀ\", \n\"height\": 256\n}, \n\"Latin Modern Mono Prop Light\": {\n\"default\": 135, \n\"widths\": \"ZKoààÒKiiÒKZKKKÒ´Â»ÂÊ´¬ÒÂZÊ¥ïÂÒ´ÒÂÂÂÂčÂÂ¥LLÂxxSKSKàijiÂxKxÂÒÂÒeÒaaÒqÂÂÂÂÂÂïÂ´´´´ZZZZÊÂÒÒÒÒÒčÒÒÂÂÂÂÂ¥ÂxxxxxKKKKÒÒčKKÒ®\", \n\"height\": 331\n}, \n\"TextMateJ\": {\n\"default\": 154, \n\"height\": 298\n}, \n\"Apple Symbols\": {\n\"default\": 121, \n\"widths\": \"U7[yy¥7QQ\\\\y7E7byyyyyyyyyy77yyygtvie{},Zyjjnnty¬ooiQbQyykeocmiGoj+2b+£jnmmF]Qjg`heR-Ry7yyyy-y ay >yIIky<Dag±±±±±±è±JJJJÀ½ÇÇÇÇÇĀyÇ±±±± ÚJJJJîy¡×f>aíT[EW\", \n\"height\": 336\n}, \n\"Kailasa\": {\n\"default\": 162, \n\"widths\": \"Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 558\n}, \n\"Apple SD Gothic Neo\": {\n\"default\": 177, \n\"widths\": \"CBUÔ 4QQ_:o:W¡[}IIsâ¦¢«BlÌª¯¯§ÚWWWvVysS::z:ÎYjZ~ºz{s]H]Ho¹`~ÉÝÝÛMVU NzÝj±±±±ß±JJJB£½ÇÇÇÇ¯ê¬±±±§ yyÅJJJJÜ{Ð00ÝÝnsEF\", \n\"height\": 307\n}, \n\"New Peninim MT\": {\n\"default\": 177, \n\"widths\": \"@:^e³5FF[j8T0Rjjjjjjjjjj:Bjjj`Ü±±À¹¼JP§Ý½ÇÇ¢¢±§Û  BRB¢¡¡^ JNJï¡¡i`ÅB3B¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡88µSS\", \n\"height\": 262\n}, \n\"DIN Alternate\": {\n\"default\": 128, \n\"widths\": \"=BU{{¦=GGZ=h=U{{{{{{{{{{==wÍ¡¦B{¡Â¯¡ÕGUG=rG=BBÚd{Gr¹{rrG9GB{{{{9{Í{ÍfPP¤S{wèBBBB¡¯í¡¡¡¡Çr====ÑrrĀ==ĀZZ\", \n\"height\": 298\n}, \n\"Wawati TC\": {\n\"default\": 85, \n\"widths\": \"UUV¸Å+UUqq1U4G³³³³³³³³³³67qqqº¸¥¦¬ ¯¦n¥¤Á´Á§½¨®¿¾Ó§¨UGU[Uq}h=M{2´|vgi]~|scQ,QUUy¨³,z£qPqfh]£······ÿ§¢¢¢¢llll°´ÁÁÁÁÁüqÁÄÄÄÄ¨»Ïu}}}}<<PUÜqĀUUĀĀĀĀ\", \n\"height\": 358\n}, \n\"Tamil MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 343\n}, \n\"Superclarendon\": {\n\"default\": 225, \n\"widths\": \"X^dÎî3__¢WVTn´§¥­©§ª§TWzyýáÔÊÖÅ¼áæmªïÁĎãÕÁÙ×¶ÒßáķáÓº^n`gY®¬·{ÂÃcjÅcĕÅ¡¯­o½³ć¹®hEd^ÈÄÒ@ì´wnk½EqááááááĵÊÅÅÅÅmmmmÖãÕÕÕÕÕļÕßßßßÓ»¶®®®®®®ùcccc¡Å¡¡¡¡¡ą¡½½½½®«®Ă@@iĚ?iS\", \n\"height\": 325\n}, \n\"Mshtakan\": {\n\"default\": 128, \n\"widths\": \"UiÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĎ?iS\", \n\"height\": 306\n}, \n\"Ayuthaya\": {\n\"default\": 154, \n\"height\": 355\n}, \n\"Kannada MN\": {\n\"default\": 128, \n\"widths\": \"DCYv|Ç¹)WW]<E4=4?mà·¶|¼«Bn§×©ÇÅ©ØI=Ho~Hy[69w6Ô]mOy»p|L'K~U3¸ÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹º66SĀ?iS\", \n\"height\": 405\n}, \n\"Waseem\": {\n\"default\": 177, \n\"widths\": \"\\u0013:`i«;^^pQh$_QFTRVWQJST@Q_r_lÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  a_a¢d¡¡^ JNJï¡¡i`ÅS1S¢Q¢¢¢¢`¢Û]ÌÛoÌll ¢Qx]l±±±±±±è±JJJJÀ½ÇÇÇÇÇĀXÇ±±±± ÚJJJJîn¡ĀQQĀSS\", \n\"height\": 369\n}, \n\"Farah\": {\n\"default\": 177, \n\"widths\": \"\\u0018<\\u0000¢«z(@@{Qo5RW:___XYZ_`dQÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢ā¡¡^ JNJï¡¡i`Å2H0¢Q¢¢¢¢`¢ÛVÌÛoÌll ¢QxLl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÇ±±±± ÚJJJJî^¡ĀQQ¥SS\", \n\"height\": 385\n}, \n\"Hiragino Kaku Gothic Std\": {\n\"default\": 198, \n\"widths\": \"U]uÉÇþîNrrl·NyNÆÆÆÆÆÆÆÆÆÆNN·­ùßÌØÛ»°×àX°Ü°ćàâÃãÒÄÆãÜĜéÖ¿ww¦³Å­Å°¾¼Q^»PĘ¼·ÆÆ§{¼´ïµ¶xyx­]ºÐ¢ÚxÈ±·a·uu¼¬N±­ßßßßßßłØ»»»»XXXXÝàâââââĳ·âããããÖÂ±³³³³³³Ĝ­°°°°__fiÃ¼·····Ĥ··¼¼¼¼¶Æ¶ĀNNĀĀĀS\", \n\"height\": 434\n}, \n\"TeX Gyre Schola\": {\n\"default\": 142, \n\"widths\": \"GLdÕÑ4UUGUGGGGr½¹¹¹Ç¹«ÇÕhÇ«òÑÇ«Ç¹¡«Ñ¹û´´UUUrUQLQärwdÇ{UUL½m½fUUGMmr¹¹¹¹¹¹Ā¹¹¹¹¹hhhhÇÑÇÇÇÇÇĀÇÑÑÑÑ´«ÌrQQQQÕĀ44ĀSS\", \n\"height\": 376\n}, \n\"Santa Fe LET\": {\n\"default\": 142, \n\"widths\": \"8UAo­#ff^UjU~>uixfqfoqUU±´©ºÇ«kl°¡Î³µ©§«O¢Ð¾¤¤f~fG^]PaHQ[[.-Z.[T^^HS?\\\\Wb[WY4YUV£{4ÅsÅE^^>Ls´´´´´´ökkkkØ³µµµµµā°¢¢¢¢¤i^^^^^^~PHHHH....x[TTTTTT\\\\\\\\\\\\\\\\[[ĳUUZĀĀĀĀ\", \n\"height\": 299\n}, \n\"ITF Devanagari\": {\n\"default\": 185, \n\"widths\": \"Efu¥\\u0000ÍÇTVV~9cLy}Wli|mv`sFGì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹Xy\\\\\\u0000|UrrrUGGGÇUdG¹r_P_U\\u0000\\u0000\\u00003\\u0000^\\u0000\\u0000t`Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ÙIIj½?iS\", \n\"height\": 434\n}, \n\"JiaguRic B\": {\n\"default\": 128, \n\"widths\": \"@UiÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĀ?iS\", \n\"height\": 287\n}, \n\"Mishafi\": {\n\"default\": 177, \n\"widths\": \"\\r)`Q«N;<<{RQD\\\"?Q6QFRJLLGL'QNDNlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  2?3¢E¡¡^ JNJï¡¡i`Å6%<¢Q¢¢¢¢`¢Û2ÌÛoÌll ¢Qx2l±±±±±±è±JJJJÀ½ÇÇÇÇÇĀAÇ±±±± ÚJJJJîD¡ĀQQĀSS\", \n\"height\": 371\n}, \n\"FZHuangCao-S09S\": {\n\"default\": 256, \n\"widths\": \"10@e]V VSCW8Y/gggggggggg87GEGj}®}u ¦}cq¬zvs´u|4CvFhlscSci?OkT­ubhifRmeXU`k@8@Q¢¢Ā¢`ĀÛÌÛĀĀll ¢Āxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀîĀĀĀĀ¡ĀĀĀĀĀĀS\", \n\"height\": 312\n}, \n\"TeX Gyre Cursor\": {\n\"default\": 154, \n\"height\": 307\n}, \n\"Songti TC\": {\n\"default\": 256, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxxxxxxx88«««]ë®£Å¨ÅÄ[U¾ÙÆÈÅ£z¶®ã³©§EEUinTxE9yFÉ]]Sx«ulm{{«8kĀ±ĀÃ]«ÃĀĀPPsĀU]]®®®®®®æ£¨¨¨¨[[[[ÅÆÈÈÈÈÈðĀÈ¶¶¶¶©uuuuioook;;<<³Ā~nlĀ@C[ĀĀĀĀ\", \n\"height\": 358\n}, \n\"Hiragino Sans GB\": {\n\"default\": 256, \n\"widths\": \"UP[¨¦áÌ2[[Y¨=\\\\=y¨¨¨¨©¨¨¨¨¨==¨èÀ¶ÂÂ¥ÁÇ@µòÆÌ©Ìº«¦Æ¸Ă¹°«YyY¥¥k¤=D;î ¦¥ndÅY`YQ¢¢Ā±`ĀÌÛĀĀll ¢Āxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀĀÇ±±±± ¥¥ÚONJJ  îĀ¡ĀĀĀĀĀĀĀĀ\", \n\"height\": 415\n}, \n\"Bodoni 72\": {\n\"default\": 136, \n\"widths\": \"0[·»[NNBNB}BBjý§·ª¶PTªÁ¨¸¹ª¢é N}Nf{iznDxz@=x<´}{}wW]I}blgeNN®[ÎkÎ[[}B\\\\kjï§PPPP·¨¸¸¸¸¸ò¸ªªªªffffff¨innnn@@@@{}{{{{{¿{}}}}g}gCC±Ç?iS\", \n\"height\": 308\n}, \n\"QXyingbikai\": {\n\"default\": 162, \n\"widths\": \"AQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 287\n}, \n\"Sathu\": {\n\"default\": 171, \n\"widths\": \"1N««èºNrr«NaN««««««««««NN«««ßº£§³­°>~ªÊµ¼¼¤«ºòrr««d<G<åcrÈs?s«N««««?«á«áW«gg««_ººººººþ§>>>>³µ¼¼¼¼¼ė«¼««««î<<<<ÿ«ĈNN«ĈSS\", \n\"height\": 312\n}, \n\"TeX Gyre Adventor\": {\n\"default\": 142, \n\"widths\": \"GLOÆÂ3^^mGUGpGGÞ½Ð¾|ß¯:{vë½Þßm¨´ö{ZZ`¯¯¦¯¦P¬343ð¨¯¯McWÕ{mZ¬ZL¬¿m¿fUUG^m½½½½½½þÐ::::Ê½ÞÞÞÞÞĲÞ¨¨¨¨¯¯¯¯¯¯Ĩ¦¦¦¦¦3333¨¨¨¨¨¨ģ§¯ĀZZĀSS\", \n\"height\": 372\n}, \n\"Courier\": {\n\"default\": 154, \n\"height\": 268\n}, \n\"Brush Script MT\": {\n\"default\": 104, \n\"widths\": \"HXMx°~8UUS«UUHpEpmmkpsuUU«««Să£¥¥p`¨Õ ¥¨¥ m³KH^xUhSKkKEc^;H^;^Ph`KP@cS~K`Mkk«X[­« ¾h«¾e«hh¥U@hS££££££ópppp¥Û«     hhhhhhhKKKKK;;;;P^PPPPP{«Pcccc`h`ĀUU[ĀĀĀĀ\", \n\"height\": 315\n}, \n\"Arial Hebrew Scholar\": {\n\"default\": 177, \n\"widths\": \"G@kvµ³<>>W}7Y5P}}}}}}}}}}=>}}}qÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  GPG¢¡¡^ JNJï¡¡i`ÅMFM¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡66ĀSS\", \n\"height\": 290\n}, \n\"Symbol\": {\n\"default\": 177, \n\"widths\": \"@U`¢ÕÇ;UU{@@GGGrÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  UU¢¡¡^ JNJï¡¡i`Å{3{¢Q¢¢¢¢`¢Ê·Êfll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÇ±±±± ÚJJJJî¡ĀQQvĀ?iS\", \n\"height\": 289\n}, \n\"Plantagenet Cherokee\": {\n\"default\": 192, \n\"widths\": \"C7FÕ»%WWw7C/Falltnz}=Buufå¼°½ÀÔaa»çÉÀÀ¬¥Ê®ï³¦EFEM_<~u}YIIRêfeT¶kG;G7u;|¾i¾9yRRt/kif¼¼¼¼¼¼ó°aaaa½ÉÀÀÀÀÀúÆÊÊÊÊ¦~~~~~~·u}}}}IIIIÐĀ33UĀ?iS\", \n\"height\": 304\n}, \n\"Avenir Next Condensed\": {\n\"default\": 120, \n\"widths\": \"/KXax¢8@@lª8:8AxxxxxxxxxxCCªªª^¤w|{ke;a{[·vzoXuºtlf@A@ª:gwVwl=wx89f8·xqwwFW@x`a`U@9@ªKxxxx9{¤Yª{RªPP8MY^wwwwww¡{kkkk;;;;¬ªl|tgggggg¦Vllll8888qxqqqqq²ªqxxxx`w`v00æSS\", \n\"height\": 350\n}, \n\"STIXIntegralsSm\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 386\n}, \n\"Lao MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 376\n}, \n\"TeX Gyre Heros Cn\": {\n\"default\": 117, \n\"widths\": \"::Juu»(FFR{:F::uuuuuuuuuu::{{{uÕ£:iu¯££Æ:::cuFuuiuu:uu//i/¯uuuuFi:uiiiiF7F{:uuuu7uu{T{FFuq:MuuÒ::::£££££Ò{£uuuuuu»iuuuu::::uuuuuuuÆ{uuuuuiuiÒ//IÒSS\", \n\"height\": 351\n}, \n\"Wingdings 3\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 292\n}, \n\"Microsoft Sans Serif\": {\n\"default\": 142, \n\"widths\": \"DG[ä«1UUdGUGGGGĄ««¹¹«Ç¹G«Õ¹Ç«Ç¹«¹«ò««GGGxUG:::ÕUG¹VCVGC½½fUUG^««««««Ā¹««««GGGG¹¹ÇÇÇÇÇĀÇ¹¹¹¹««ä::::ò99ZUUS\", \n\"height\": 290\n}, \n\"OpenDyslexic\": {\n\"default\": 157, \n\"widths\": \"QN½þÊYST{¡Dj]¯¯¨¢«¯¬eEÄåÄxĄ¼»ÆÔ°ÓÓTgÈñÑÙ×À³©ËÀĖÍ­ÍbQa±ÊHª£ ¹¬a±PQRđ¹­¸¥oiµåº¦©u<rÍ`{¤Â¦YâÅây±~~ ±^v¯¯¯¯¯ÀĐ³¢¢¢¢KKKKÝ¿ÉÉÉÉÉĤ¶Ý»»»»²ĕGGGG¤¢Ġª°©¢¢¢ ŅFEtėSS\", \n\"height\": 316\n}, \n\"Wingdings 2\": {\n\"default\": 162, \n\"widths\": \"QQ`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 270\n}, \n\"SignPainter\": {\n\"default\": 103, \n\"widths\": \"8QQZ>:?^P=S9e}8lnmjgVcjADJ\\\\Jcqtv|^]}/pfZvmurgtg¡faqQ[RD^\\u0014hZPgR?ga3.^;bUd_TM7gM}d`Z19NQZ[\\\\[9zKYMP^^gy\\\"L[^qqqqqq§v^^^^////|v¿FttttavihhhhhhORRRR3333ZbUUUUUPTgggg`d`yB;'}ĀĀĀ\", \n\"height\": 248\n}, \n\"Simsun (Founder Extended)\": {\n\"default\": 256, \n\"widths\": \"GCh«u¸»-MM«C«Cu}}}}}}}}}}CC«««[ë­£»Ã½ËUM³ëÐÓÓÍ}­Ë°ĀÀµ­MuMUUempExC@=ËUMK{½}xh{{CmÃĀĀĀ[«ĀUĀMMsĀX[[­­­­­­à»UUUUÃÐÓÓÓÓÓýĀÓËËËËµĀĀeeee mĀpĀpĀCCCĀ½ĀĀĀxxĀĀĀ[ĀĀĀĀ\", \n\"height\": 288\n}, \n\"Party LET\": {\n\"default\": 70, \n\"widths\": \",J9wQ§!CCJa*E*QLsvkho**adì·É£¿¡«ÄTµ£é¾¸£¬®¦«à²´CQCx<BLDZ:1JJ0&K2_F?SHEJ1FB]ZCE{Q{Jo3ÃFÃc:;t%OFd······Ą£¡¡¡¡TTTT¿¾¸¸¸¸¸ða¸¦¦¦¦£OBBBBBBiD::::0000JF?????gJFFFFCSCħ**FĀ?iS\", \n\"height\": 299\n}, \n\"Georgia\": {\n\"default\": 165, \n\"widths\": \">Ui¥Ñ¶7``y¥E`ExnPP¥¥¥{î¬§¤À§ºÑd²íÄ¿¿´Â«ú¶`x`¥¥t|SKKIâioX½~rn`n¥U`ñ¥ñk¥H{¬¬¬¬¬¬ù¤§§§§ddddÀÄ¿¿¿¿¿Ā¥¿ÂÂÂÂ½t||||KKKKÑ¥~~Û::eÏRS\", \n\"correction\": 1.0, \n\"height\": 291\n}, \n\"American Typewriter\": {\n\"default\": 163, \n\"widths\": \"@kT£ÍÒ0tt£FOFf££££££££££FF±¿±£º¬¶ÈbÈ£òÄ¨£¨º£¶ºîÈºpp~Y£OJOî£~~fÍ£«k£º«¶£ÊYll#mY¿¿¿¿¿¿ą£¬¬¬¬bbbbºÄ¨¨¨¨¨Ċ¨¶¶¶¶º££ÖOOOO£äÄAB«Ñ?iS\", \n\"height\": 295\n}, \n\"Yuppy TC\": {\n\"default\": 256, \n\"widths\": \"GG[Ñ©1UUdGUGMGGò°¡´¯¤º©G~¤É«Ã¤Â¥¥¡¬­ó­« GMGxUT9E{9ÎX|NÅVCVQĀĀ¢Ā`ĀÛĀÛĀĀll ¢ĀxlĀĀ±±±±è±ĀĀĀJJJJÀ½ĀĀÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀĀĀĀĀĀĀ¡ĀĀĀĀĀĀĀ\", \n\"height\": 358\n}, \n\"Weibei TC\": {\n\"default\": 136, \n\"widths\": \"=X¹ ­0JJ>|>R>>xÿ§«£®LN¤xÓª®°ª£îGRG³~jENEÐckhÆ}w¥=~|ÕcÓÕWVV>dcx§§§§§§àOOb`°ª®®®®®ÛÓ®ªªªª¹~JJb`ÛÕĀ>>hĀĀiĀ\", \n\"height\": 358\n}, \n\"Tamil Sangam MN\": {\n\"default\": 143, \n\"widths\": \"@/N¼Ø°*IEz4S1L14É¡­©´¥2u¿ ¶ºÝ9J4p3Q0/x/ÈNyNz³wx}N.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 276\n}, \n\"Notera Personal Use Only\": {\n\"default\": 222, \n\"widths\": \"K\\u001d+Pye\\\\\\u0001*2BV'W(bÞÞÞÞÞÞÞÞÞÞ((JQNA~»©¬}d­j£Ä¥ý¾r£Ã}n¾s©¿¤¾697:F2q_[g[GUvNAsKtdiUaQLxefip-L5K\\u001d[l?L?}eW}/VPGxL(dgP»»»»»»Ö}}}}jjjj¬¾rrrrrÁ?r¾¾¾¾¤sqqqqqq[[[[[NNNNdtdddddIdxxxxihi++BySS\", \n\"height\": 256\n}, \n\"Khmer MN\": {\n\"default\": 128, \n\"widths\": \"@?Tpu»®'RRX9A19}}}}}}}}}}1;gÓ­¬u²¡>hxË ¼|ºx ÌD:DhwDrz~Vz36p3ÈzWgK|r°jxuG%GwU3®ÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹°33NĀ?iS\", \n\"height\": 472\n}, \n\"Telugu Sangam MN\": {\n\"default\": 139, \n\"widths\": \"S3TËé½.OJ¨8Z5R58¨Ù©§Ã¶¡Æ­F°Í®ÉÌ§©°ªë¬>O8y¡7\\\\:/:ÚVT|»}zT2O«Q¢¢¢¢`¢ÕÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ü77ZĀSS\", \n\"height\": 461\n}, \n\"HanWangShinSuMedium\": {\n\"default\": 256, \n\"widths\": \"5V _¡5u]mB<cK|r{mrn{j68lâyvxu}h]~mH@r}Sb^[bZaUmiQdYlij_aT_msagjC=B|PĀ©©cĀ×Ì×ĀĀ{{±©Ā{½½½½½½õ¶UUUUËÅÓÓÓÓÓďĀÓ½½½½°©âSSSS¤¨¤¤¤¤¤öĀ¤¨¨¨¨ªĀĀĀĀĀĀĀ\", \n\"height\": 314\n}, \n\"Phosphate\": {\n\"default\": 189, \n\"widths\": \"3Jaxs¸©/GGbvFPFpQngxhtFFxvxbà £vs²La£qÅ£½½sw§ÞLpLpD £vs²La£qÅ£½½sw§ÞY7YJb~7s½Xv;7}¥Fb      ávvvvLLLL££½½½½½ău½å      ávvvvLLLL££½½½½½ăv½½GG`ÒSS\", \n\"height\": 320\n}, \n\"Malayalam Sangam MN\": {\n\"default\": 143, \n\"widths\": \"M/N¼Ø°*JEz4S1L14Êµ©·¡A{¤¾¡º½£Ú 9J4p3U6,6ÊO~Ns®tqN.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 348\n}, \n\"Baoli SC\": {\n\"default\": 128, \n\"widths\": \"GU\\\\£Ô¬GUU@@ÍUU¥¥rÏ¢£§ºd¯Õ¾  ¢«¬¥ìÁ¨ÍpĀU|{oViS¹|f}dµ|8ÍĀĀĀĀĀäĀxx{[Yxy¹Ā|}ĀĀĀZĀĀĀS\", \n\"height\": 358\n}, \n\"Mishafi Gold\": {\n\"default\": 177, \n\"widths\": \"\\u0015)`Q«N;<<ZRQD\\\"?Q6QFRJLLGL'QNDNlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  2?3¢E¡¡^ JNJï¡¡i`Å6%<¢Q¢¢¢¢`¢Û2ÌÛoÌll ¢Qx2l±±±±±±è±JJJJÀ½ÇÇÇÇÇĀAÇ±±±± ÚJJJJîD¡ĀQQĀSS\", \n\"height\": 371\n}, \n\"STHeiti\": {\n\"default\": 256, \n\"widths\": \"@LO¸ÆÂ3^^mGUGpGGÞ½Ð¾|ß¯:{vë½Þßm¨´ö{ZZ¬a¯¯¦¯¦P¬343ð¨¯¯McWÕ{mZ¬ZLĀ¬ĀÄmÄĀĀUXĀ^m½½½½½½þÐ;;[LÊ½ÞÞÞÞÞĀĀÞ¨¨¨¨¯¯¯¯¯¯Ā¦¦¦¦¦;;[L¨¨¨¨¨¨ĀĀ§¯ĀĀĀĀĀĀĀ\", \n\"height\": 256\n}, \n\"HanziPen SC\": {\n\"default\": 148, \n\"widths\": \"X_gÅµ©7XX|DpFCNzq×­¢¥ItÈ³¬n¦ÓWWzXr|aqtwkuDcw@ÀuhqtdX_|v¶vrXLXZ_d º­Nr³³Pb­­­­­­ëOOOO¡³³³³³Ĉ³rrrrrr«attttFFFFouhhhhh¤|||||r}rĈJJĈFn\", \n\"height\": 358\n}, \n\"Bordeaux Roman Bold LET\": {\n\"default\": 59, \n\"widths\": \"\\u001f03<AR 00#5%%%V<.63:4:/99%%5=îEB5D?;?K)6E:TDA?AF<;CGeID80V0=;;0;3+8>##<#W>6<;/0&>;Q87-e/e0:@K8¿+¿55MM\\\"6+=EEEEEE^5????))))¹DAAAAAZ5ACCCCD;;;;;;;M03333####>66666QA6>>>>77Ď%%7Ā=O=O\", \n\"height\": 326\n}, \n\"Hiragino Kaku Gothic ProN\": {\n\"default\": 168, \n\"widths\": \"UP[¨¦áÌ2[[Y¨=\\\\=y¨¨¨¨©¨¨¨¨¨==¨èÀ¶ÂÂ¥ÁÇ@µòÆÌ©Ìº«¦Æ¸Ă¹°«YyY¥¥k¤=D;î ¦¥ndÅY`YP¨±_¤w¨M¨ee=nwÀÀÀÀÀÀďÂ¥¥¥¥@@@@ÄÆÌÌÌÌÌĊ¨ÌÆÆÆÆ°¥¡øONNF¥     ą¨ ¦Ā=={Ā7_S\", \n\"height\": 409\n}, \n\"PT Serif Caption\": {\n\"default\": 154, \n\"widths\": \"F^nèú@ddRzPc^_ĜÁ±³È¥ÆÒfa¶üÒÔ«Ôµ³ÃÅĎÂº¬YnYvX c©WSWù¬£o|k¦ÒdDd^DèÉy{{§E}ÁÁÁÁÁÁć³¥¥¥¥ffffÈÒÔÔÔÔÔĐÔÃÃÃÃºª¸àWWWW¬ü¦¦¦¦£þTTÿ?iS\", \n\"height\": 332\n}, \n\"Charter\": {\n\"default\": 142, \n\"widths\": \"GWU¿Ú´,kkÕGRG{RRÕÕÕ|ñ¤¢±²½SrÞ·»»¥²îl{lĀr~RHDHØbfVÅx||ÕWæqÕæTÕ^^|Ggq|¤¤¤¤¤¤Þ¢SSSS±·»»»»»þÕ»²²²²ºr~~~~HHHHÑÕĀ44Ā?iS\", \n\"height\": 313\n}, \n\"Hiragino Maru Gothic Pro\": {\n\"default\": 147, \n\"widths\": \"UM`¥¤äÅJ^^g«MrMy§§§§§§§§§§NN«èÃº¾Å¦§ÄËE±¡ôÇÎ³Î¸¬­ÆºĈ¸µ®byb  f<H<á  ogÏe_f¦M¥¬_{«G«ggMp{ÃÃÃÃÃÃĔ¾¦¦¦¦EEOLÈÇÎÎÎÎÎĕ«ÎÆÆÆÆµ²¢ï<<GJý« ĀLL~ĀAmS\", \n\"height\": 416\n}, \n\"Hiragino Maru Gothic ProN\": {\n\"default\": 147, \n\"widths\": \"UM`¥¤äÅJ^^g«MrMy§§§§§§§§§§NN«èÃº¾Å¦§ÄËE±¡ôÇÎ³Î¸¬­ÆºĈ¸µ®byb  f<H<á  ogÏe_f¦M¥¬_{«G«ggMp{ÃÃÃÃÃÃĔ¾¦¦¦¦EEOLÈÇÎÎÎÎÎĕ«ÎÆÆÆÆµ²¢ï<<GJý« ĀLL~ĀAmS\", \n\"height\": 416\n}, \n\"STIXGeneral\": {\n\"default\": 128, \n\"widths\": \"@Uh¿Ç.UU¯@U@GGG¯¯¯rì¹««¹¹¹U_¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{T3ÃÃf¯MM@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¤¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUĀJmJm\", \n\"height\": 386\n}, \n\"FZYingBiKaiShu-S15S\": {\n\"default\": 228, \n\"height\": 282\n}, \n\"TeX Gyre Termes\": {\n\"default\": 128, \n\"widths\": \"@UhÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĀSS\", \n\"height\": 342\n}, \n\"Luminari\": {\n\"default\": 208, \n\"widths\": \":EU~·É7NN[7i6Q`z?H{d¬£¼¥Ì©Ä¼d]½ĚÐÐ­ÊÁÄÐÄĀ¼¼²U~StuQrwUF@Fî rwx¿lTFTEl¤¶FóW\\\\ob6kWd££££££Ăª§§§§mmmmÌíÐÐÐÐÐŋÐÌÌÌÌ»¶µÉwsusuEHBFÝ¯}À77e£ĀĀĀ\", \n\"height\": 343\n}, \n\"FZYingBiKaiShu-S15T\": {\n\"default\": 228, \n\"height\": 282\n}, \n\"LiHei Pro\": {\n\"default\": 256, \n\"widths\": \"UUV¦â¸NUU©·[U[x¦¦¦¦¦¦¦¦¦¦[[···Ó¼¬¼¼¢¢»´D»°×¸ÁªÁ©«¨µ±ð»·¨UxUmUc<U<Ü\\\\dÞ}I4IQĀĀ¢Ā`ĀÀÌÛĀĀllĀ¢ĀxlĀĀ±±±±è±ĀĀĀJJJJÀ½ĀĀÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀĀĀĀĀĀĀ¡ĀĀĀĀĀĀ\", \n\"height\": 264\n}, \n\"KufiStandardGK\": {\n\"default\": 162, \n\"widths\": \"@Mf¦s«@ZZ{Qf¢¢¢¢¢¢¢¢¢¢MQfflÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  @s@y¡¡^ JNJï¡¡i`ÅM3M¢Q¢¢¢¢`¢ÛtÌÛoÌll ¢Qxsl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÇ±±±± ÚJJJJî¡ĀQQÍSS\", \n\"height\": 367\n}, \n\"Weibei SC\": {\n\"default\": 136, \n\"widths\": \"=X¹ ­0JJ>|>R>>xÿ§«£®LN¤xÓª®°ª£îGRG³~jENEÐckhÆ}w¥=~|ÕcÓÕWVV>dcx§§§§§§àOOb`°ª®®®®®ÛÓ®ªªªª¹~JJb`ÛÕĀ>>hĀĀĀĀ\", \n\"height\": 358\n}, \n\"PT Serif\": {\n\"default\": 136, \n\"widths\": \">TaÏÞ9XXwHmGXTUyĐ¯¥µ°ºZW¥Þ»½½£¬¯ï¬¥ObOiTwXMJMÝbo_º}Y=YT=Ïy³mnn=oyy¯¯¯¯¯¯ì¥ZZZZ¶»½½½½½ô½¬¬¬¬¥£ÇwMMMMàãKKtâ?iS\", \n\"height\": 332\n}, \n\"STIXSizeTwoSym\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;{ÌQQÎ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  vÎv¢ƀ¡¡^ JNJï¡¡i`Å¸`¸¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 647\n}, \n\"Tahoma\": {\n\"default\": 140, \n\"widths\": \"PUgºú­6bbºN]Nb[[ºººyé®«­`kÅ«µµ¨çbbbºvR;H;×\\\\rV¾r{b{ºUbîºîyº~~[~yê````³«µµµµµúºµ¨¨¨¨áv;;;;éºé66tÑKzS\", \n\"height\": 309\n}, \n\"RicAldi\": {\n\"default\": 128, \n\"widths\": \"@VUÅÆÆ,UUÕ@U@GVVÕÕÕrü¸ª«Ï©©ÀÔdgÕ¸ñÍÄ Ä³¸Æ¶üÆ¸ªWGWĀrrrQOHLÙddVµrÕV¶3ÒoÕÒTÕTT@bor¸¸¸¸¸¸þ«©©©©dddd¹ÍÄÄÄÄÄďÄÆÆÆÆ¹rrrrrrªrrrrrOOOOÉÕĀ@@Ā?iS\", \n\"height\": 314\n}, \n\"HAN NOM B\": {\n\"default\": 128, \n\"height\": 281\n}, \n\"HAN NOM A\": {\n\"default\": 128, \n\"height\": 281\n}, \n\"Telugu MN\": {\n\"default\": 128, \n\"widths\": \"GF]{ÏÁ+[[a?H6@6Brê¤ ¿¾Å²Es¯à±ÐÍ±¢á£L@LsK~_9<|9ÝarR~ÃuO)OU3ÁÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ã88WĀ?iS\", \n\"height\": 431\n}, \n\"InaiMathi\": {\n\"default\": 116, \n\"widths\": \"M?Rt¯+DDb|?L?9tttttttttt??|||sÒz 6grªz¼8B8}h)~~y~C~/0t.Á~IqB~t§rqtF4FQ¢¢¢¢`¢ÉÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ą88XĀSS\", \n\"height\": 322\n}, \n\"Blackmoor LET\": {\n\"default\": 101, \n\"widths\": \"3JW®5RRG<^<e`shea<<bîÃª£h¨à§¥¥¥ ¦ß±`e`Lik[i^Pik??m?memmWfKmkko]e;eJª8¿S¿kRJ<HSbÃÃÃÃÃÃòhhhh¹§¥¥¥¥¥ß¥iiiiiii[^^^^????meeeeeemmmmooĕ<<qĀ?iZ\", \n\"height\": 324\n}, \n\"Synchro LET\": {\n\"default\": 155, \n\"widths\": \"GAS©¤¤,ZZ^@c@M@@ÌcÌÜ£Y££ ~ZZ©Y£Y££ ~_H_ÌA©c©×Ì×SÌ{{±©A{×YYYY«£Ù¤ĩ×YYYY«£ÙÌ¤ĕ@@YĀZZ\", \n\"height\": 325\n}, \n\"Myanmar MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 411\n}, \n\"STIXSizeFourSym\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;ÏÏ{ÌQQŏ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  ©ŏ©¢ʀ¡¡^ JNJï¡¡i`Åē`ē¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 805\n}, \n\"Gurmukhi Sangam MN\": {\n\"default\": 143, \n\"widths\": \"@/N¼Ø°*IEz4S1L14É¡­©´¥2u¿ ¶ºÝ9J4p3Q0/x/ÈNyNz³wx}N.IQ¢¢¢¢`¢ÅÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡Ì33SĀSS\", \n\"height\": 373\n}, \n\"Farisi\": {\n\"default\": 177, \n\"widths\": \"\\r<`rg«t;LLhUQT<^fCquxxnfon3QJUJlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  K^K¢Ç¡¡^ JNJï¡¡i`ÅI¢Q¢¢¢¢`¢ÛWÌÛoÌll ¢QxWl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀGÇ±±±± ÚJJJJîW¡ĀQQĀSS\", \n\"height\": 542\n}, \n\"Avenir\": {\n\"default\": 142, \n\"widths\": \"GGÕ´CCCrªGUG_GGªªª{Í°¡´¾Ç¹D{¡äÇÖÖ°ò¡C_Cª={L=={=ÚUmU{¹{{mC9CªG9Í{ªÍfª\\\\\\\\Gc{{°°°°°°ò´DDDD¾ÇÖÖÖÖÖòªÖ°°°°Ú{====ìª{{ĀCCĀSS\", \n\"height\": 350\n}, \n\"Heiti SC\": {\n\"default\": 142, \n\"widths\": \"@LO¸ÆÂ3^^mGUGpGGÞ½Ð¾|ß¯:{vë½Þßm¨´ö{ZZ¬a¯¯¦¯¦P¬343ð¨¯¯McWÕ{mZzZLÍaÕmÓĀ¶UXĀ^m½½½½½½þÐ::::Ê½ÞÞÞÞÞĐ·Þ¨¨¨¨¯¯¯¯¯¯¯Ċ¦¦¦¦¦3333¨ ¡¨¨¨ċÆ§ĀĀĀĀĀĀĀ\", \n\"height\": 264\n}, \n\"Chalkboard\": {\n\"default\": 137, \n\"widths\": \"bAtÌÐµ2QQAzL_I]m}qsÑ¥£ªqÔ¨ºÃ ¨¥ý¨¨OL|£L~o@cM½}pnuw¸X@Z¤]} £4zæßf^^©U¥¥¥¥¥¥åqqtqØªºººººèº¨¨¨¨ Ò~DEPSxÇ}£FCsÁĀĀĀ\", \n\"height\": 326\n}, \n\"Baskerville\": {\n\"default\": 128, \n\"widths\": \"@@h«}à³-==k«@P@@@«««eë­¸Ã ÅÍ[[ÈíÀÓÓ»³Å»óÅ­£XXxUxmpEx@@u=Í]UKu­{um{{«@mµ«eÃx«Ãe«MMsUSxe­­­­­­ã¸    [[[[ÃÀÓÓÓÓÓð«ÓÅÅÅÅ­xxxxxx mpppp@@@@Å«uuĀ@@[Ā----\", \n\"height\": 293\n}, \n\"Latin Modern Roman Caps\": {\n\"default\": 216, \n\"widths\": \"aRjççØRppØRaRRRØØØØÐÅÉÔ¾·ÚÐhØ¯ýÐØ¾ØÍÉÐÐěÐÐ«RRÐ ¤Mm£¿££uÖGRÐØÐG¯Ø¯jØffØÐÐÐÐÐÐúÉ¾¾¾¾hhhhÔÐØØØØØĘØØÐÐÐÐÐ¯ê¼MMMM £££££ÓØ£ěRRØ¸SS\", \n\"height\": 356\n}, \n\"Bodoni Ornaments\": {\n\"default\": 256, \n\"widths\": \"@ĬsÉėĀů;×ÈÌĀþô¿ĀĀĀĀġĀÆćvyÁVVYYWWAA::ZYTP^QX^¥¤ {{ĳĳơơóóGmÓŷėƦšļƖħÎĎƕĬŴĢ¡ěÒçķÜĀòúćƙ¾¢Qǽį¢ƕ`{ȏÌÏZllƔČQxl±±±±±±÷±JJJJÀ½ÇÇÇÇÇĀÌh±±±± ȴÚJJJJîÌ¡ĀQÅĩĀSS\", \n\"height\": 256\n}, \n\"Al Tarikh\": {\n\"default\": 177, \n\"widths\": \"(Y/¢«z#LL{rQrrruOseuimmgmrQ`r`lÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢å¡¡^ JNJï¡¡i`ÅSGS¢Q¢¢¢¢`¢ÛMÌÛoÌll ¢QxMl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀrÇ±±±± ÚJJJJîr¡ĀQQåSS\", \n\"height\": 406\n}, \n\"YuGothic\": {\n\"default\": 142, \n\"widths\": \"IViÎ¸9aa{¹BnB{HH¹¹¹Ü¦®¯¾º¿Lf±ëÀ»©»¬¡ ½¦î¦¦a{aXDLDÜ^Z}Æ}}taaa´VaĀãv¹ĀĀ\\\\\\\\ĀBbv¦¦¦¦¦¦ă¯LLLL¾À»»»»»ČĀ»½½½½¦ªáDDDDéĀ}}ĀBBeĀĀĀZ\", \n\"height\": 537\n}, \n\"Didot\": {\n\"default\": 152, \n\"widths\": \"GPr«ÇÇGGGrG_GLGGhÕ¾«¹Ñ´«ÌÑcw¾¯ß¹Õ¦Õ¹«¯Â¹ēÂ´¦GLGG{{ULLLßhmU{¾{{mU9UP¡9Õh}fUUG\\\\hh¾¾¾¾¾¾ò¹´´´´ccccÑ¹ÕÕÕÕÕēÕÂÂÂÂ´¦{{{{{{¹{LLLLÚ{{ĀGGĀ?iS\", \n\"height\": 324\n}, \n\"Geneva\": {\n\"default\": 171, \n\"widths\": \"UN««èºNrr«NaN««««««««««NN«««ßº£§³­±>~ªÊµ¼¼¤«ºòrr««d<G<åcrÈs?s«N««««?«á«áW«gg««_ººººººþ§>>>>³µ¼¼¼¼¼ė«¼««««î<<<<ÿ«ĈNN«Ĉ¨¨\", \n\"height\": 341\n}, \n\"Sinhala MN\": {\n\"default\": 128, \n\"widths\": \"54E\\\\` DCHh/6(/gggggggggg(1mmmU®zwl`3Vc§ftcty¨yuw808Vb8^jekhGoe*,\\\\*¥dqkkHU=f^Wc`;\\u001f;bU3ÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹**AĀ?iS\", \n\"height\": 300\n}, \n\"Andale Mono\": {\n\"default\": 154, \n\"height\": 288\n}, \n\"Latin Modern Roman\": {\n\"default\": 128, \n\"widths\": \"UG`ÕÕÇGddÇGUGGGÇÇÇyÇÀµ¹Ä®§ÉÀ\\\\Ç ëÀÇ®Ç¼¹ÀÀćÀÀGGÀrrNGNGÕded¹rGGrÀÇÀG|¯Ç¯`Ç\\\\\\\\ÇkyÀÀÀÀÀÀç¹®®®®\\\\\\\\\\\\\\\\ÄÀÇÇÇÇÇĄÇÇÀÀÀÀÀ ¹rrrrrGGGGÇÇĀGGÇ¬SS\", \n\"height\": 363\n}, \n\"Muna\": {\n\"default\": 177, \n\"widths\": \"AA;¢«z\\\"JP{nQnGnyRxiymqqjqAQÌnÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢ø¡¡^ JNJï¡¡i`ÅSGS¢Q¢¢¢¢`¢ÛJÌÛoÌll ¢QxJl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀnÇ±±±± ÚJJJJîn¡ĀQQtSS\", \n\"height\": 399\n}, \n\"Avenir Next\": {\n\"default\": 148, \n\"widths\": \"@ThÕ´CMMrªCRC_MMªªª{Í³£¸ÂÇ¸C~¡ãÄÚØ¶ù¦M_Mª=££L¢@@Aâ££\\\\rQ}¿|}qM9MªT9Í{ªfª__C\\\\{{³³³³³³ý¸CCCCÂÄÚÚÚÚÚþªÚ¶¶¶¶ß@@@@þª}¢}99ĀSS\", \n\"height\": 350\n}, \n\"STKaiti\": {\n\"default\": 131, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxzxxxxx88«««]ë¯ ¥Æ©ÅÈ[U¾âÇÇÄ¤|·°å´ª©EEUlnV{=;}EÈXbWy«uoo{{«8i©­ĀÃ]«Ã]­PTsJU]]¯¯¯¯¯¯ö£©©©©[[[[ÆÇÇÇÇÇÇð®Ç····ªlnnnn====³ÄooĀ?C[ĀĀĀĀ\", \n\"height\": 261\n}, \n\"Latin Modern Mono Caps\": {\n\"default\": 134, \n\"height\": 333\n}, \n\"Nanum Myeongjo\": {\n\"default\": 243, \n\"widths\": \"M_RáÜ-^^¤¤F¤Foii¤ÛººÊÊÙRaºąØØØº«º»ąÊºº^Ā^8wrTEEEØccTÌr^^¸óó3óóóóóóóóóJóóó¹¹¹¹¹¹ó«UUUUó¹¹¹¹¹¹óóó¹¹¹¹¹óórrrrrrórrrrrGGGGóóóóóóóJJóóóóóó\", \n\"height\": 305\n}, \n\"Times New Roman\": {\n\"default\": 128, \n\"widths\": \"@UiÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMtUOr¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĀ8kS\", \n\"correction\": 1.04, \n\"height\": 294\n}, \n\"Shree Devanagari 714\": {\n\"default\": 151, \n\"widths\": \"f9ZØ´ã¡8Y[ ;;<>Ěª¨±±º´5|¥Ú¹¼½ª®ë YuYG>555ÛQ}<z¼}|rs5s;É«Æ5ê¦ê[vyµQyªªªªªªþ±5555²¹¼¼¼¼¼ĉ¾®®®® é5555Ā||þ;;p¯SS\", \n\"height\": 380\n}, \n\"YuMincho\": {\n\"default\": 128, \n\"widths\": \"UFfå¼;cch­CZCkHH­­­|Ú²±¸Õ¦ÍÖ^`·¥ùÏ×ª×²¸Ð¶ú©¦§ckcxszUGFCÙahW|¹y}tcZc¤F§ZĀÙl­ĀĀ]]ĀC`l|²²²²²²ă¸¦¦¦¦^^^^ÕÏ×××××ėĀ×ÐÐÐÐ¦©xxxxxx¸szzzzGGGGÓĀ}}ĀCCjĀĀĀZ\", \n\"height\": 524\n}, \n\"TeX Gyre Bonum\": {\n\"default\": 159, \n\"widths\": \"RMaæÍ8MMqRfRRRÒ®½½Í¸¤ÍÍW¸ì½ÍÒ¸©È³ö¸¤¤MMWR©MMMñ©qa®È{HHM½\\\\½f__®Rl\\\\®®®®®®Ń½¸¸¸¸WWWWÍ½ÍÍÍÍÍĽÍÈÈÈÈ¤©ÜMMMM©æ®®®®Ā88vĀSS\", \n\"height\": 343\n}, \n\"Bradley Hand\": {\n\"default\": 213, \n\"widths\": \"APS¡¬¶7kkÕD\\\\Do¡£¯DDÕÕÕd¯º¯¡¥ÀÂGGÁ£áÈ¸½Ã¾½§ü§®èkokĀi|naiTF Tç¬mxdtZ~®{©iiÕP¬vEkÕE<Õif©yCDkdººººººě¡GGGG£È¸¸¸¸¸ĨÕ¸½½½½®×naaaaTTTTj¬mmmmm¤Õ©v©è==HÐĀĀĀ\", \n\"height\": 320\n}, \n\"Princetown LET\": {\n\"default\": 140, \n\"widths\": \"YG\\\\Â1]\\\\RBN?hv?Avî§¡Z¤Á«ªä®]]D§¡Z¤Á«ªä®e8eG{8¿t¿fMM?Utv§§§§§§êZZZZ¹«Ï¹§§§§§§êZZZZ«ÏĐ77mĀ?iZ\", \n\"height\": 287\n}, \n\"AppleMyungjo\": {\n\"default\": 256, \n\"widths\": \"ff¤¤ÂÉf¨ff¤¤¤¤¤¤¤¤¤¤X^¥wÔÂ±¥»§£»Æ^È«ñÌ·¤µµ¤ÍÄþ¶Á@luYwLHLÕxnf_Àm§ĀªµĀÄ3ĀËĀĀÃĀĀĀĀĀĀĀĀĀ¹¹¹¹¹¹Ā«UUUUĀ¹¹¹¹¹¹ĀĀĀ¹¹¹¹¹ĀĀrrrrrrĀrrrrrGGGGĀĀĀĀĀĀĀĀĀĀĀĀ\", \n\"height\": 438\n}, \n\"LiSong Pro\": {\n\"default\": 256, \n\"widths\": \"UUG¤Ñ½>UU²WUWpWW|||v·¹ ¢­¡º·U»Ì¼°°®¡ÁºÝ¼·UpUZUsycJNH×yhf[¼fB#BUĀĀĀ3ĀÀÃĀĀMMĀtĀOrĀĀ¹¹¹¹ä«ĀĀĀUUUU¹¹ĀĀ¹¹¹äĀ¹¹¹¹¹¹ĀĀrrrr«rĀĀĀrĀĀGGĀĀĀĀĀĀĀĀĀĀĀĀĀiĀ\", \n\"height\": 264\n}, \n\"Type Embellishments One LET\": {\n\"default\": 177, \n\"widths\": \"8ÂµÀßġÂįǹŚÊőƥÏƥĺĺËÚěěƋĽǹƔÕĭÊ¤įĴÂŁĶĩ¤¤Ĵĵ¥¥¬¬~~ĽŜǑǘÚ××××ÎĦĦĺŁŚĬĴrįŐÆǸńƏŇŇƪãŉŋÅ«ľľìÎÀĶě¬ÂĽƅßŷÞQ¢¢¢¢`¢ġÌÛoÌll ¢Qxl±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ĽÚÂJJJJîÌ¡ĀQQĀSS\", \n\"height\": 316\n}, \n\"Lantinghei TC\": {\n\"default\": 256, \n\"widths\": \"GNV¢ùÅ.]]r¨JJK|IJ§¤¦ĝ¼»ËÊ»«ÚÉAºëÊÛ»ÚÊº¬Ì¾ĉ¼»«MLM¦YJ372è]MÊ]@]¤QĀĀ¢¢`ĀÛÌÛĀĀll ¢ĀxlĀĀ±±±±è±ĀĀĀJJJJÀ½ĀĀÇÇÇĀĀÇ±±±± ĀĀÚĀĀĀĀĀJJĀĀĀĀĀĀĀĀ¡ĀĀĀĀĀĀĀ\", \n\"height\": 356\n}, \n\"pangzhonghua\": {\n\"default\": 128, \n\"height\": 256\n}, \n\"PT Sans\": {\n\"default\": 140, \n\"widths\": \"DNVÆÐ8HHZ2\\\\7[8BpĐ§¬JJÊ¬¯¯§ÔNaNhHsRED{KÐWlW{¼wrY=YN=Îz³mee~DfzpÙJJJJ¨¬¯¯¯¯¯ï¯§§§§ÌsEEEEÜwwÒ22tÂSS\", \n\"height\": 332\n}, \n\"Devanagari MT\": {\n\"default\": 128, \n\"widths\": \"RUo¿ÇAooCmDTXXxì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹hThXUrrrUGGGÇUdG¹rkNkU3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹õDDZõ?iS\", \n\"height\": 412\n}, \n\"Menlo\": {\n\"default\": 154, \n\"height\": 298\n}, \n\"Futura\": {\n\"default\": 106, \n\"widths\": \"5Gajj4KKjj5.5sjjjjjjjjjj55j_¾hibw]Zwx8KlUxzfzl`Tw_`caZsZeeIe^?eh33d3hceeDK9hW`^VMMÁGjjÁjjÛ^ÛnjIIhj5M^_hhhhhhb]]]]8888wxzzzzz£jzwwwwcfjeeeeeeI^^^^3333chcccccjchhhh^e^;;Á¢SS\", \n\"correction\": 1.5, \n\"height\": 331\n}, \n\"Yuanti SC\": {\n\"default\": 62, \n\"widths\": \"@>n¤íª\\\\\\\\\\\\k0AvSHHÝ£ ³­>esÍª²»~¦ÍHvHn\\\\}i>Z;âbtj|½|vg;gØ>}È6xØ«Ø<^^4iØ£>>>> ª²²²²²ï²¦¦¦¦}>>>>¹Ā>>[ĀĀĀĀ\", \n\"height\": 358\n}, \n\"Latin Modern Mono Light\": {\n\"default\": 134, \n\"height\": 336\n}, \n\"Diwan Thuluth\": {\n\"default\": 177, \n\"widths\": \"\\u0001)`Q«K;ZRQD\\\"?O4NDOGJJEJ'QNDNlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  2?3¢E¡¡^ JNJï¡¡i`Å6%<¢Q¢¢¢¢`¢Û2ÌÛoÌll ¢Qx2l±±±±±±è±JJJJÀ½ÇÇÇÇÇĀAÇ±±±± ÚJJJJîD¡ĀQQĀSS\", \n\"height\": 439\n}, \n\"PilGi\": {\n\"default\": 256, \n\"widths\": \"Mg¤vÒ¨Cmmx«CUCxxxxxxxxxxCPøXþ¸w«w ÅÜµ{{PĀC~ee~i_v~COyZ±}|reJ~q±wjPFPýĀĀĀĀĀ4ĀĀĀĀÅĀĀĀĀĀĀĀĀĀ¸¸¸¸¸¸Ā»»»»uuuuĀâ°°°°°ĀĀĀÛÛÛÛ¥ĀĀĀb____LLLLxnnnnnĀĀĀĀĀĀĀĀĀĀĀĀ\", \n\"height\": 259\n}, \n\"Hannotate TC\": {\n\"default\": 155, \n\"widths\": \"UZR¦»Ð0LLsF]DDFä¢£¡¤>~½ ª¶§½¡TTsLc~EN@¬r~f|w£x`KaUZ~±¯­G¥¥ge¢¢¢¢¢¢ÓZZZZ¯ ªªªªªØ¬­ZZZZµ||||ĀAAĀRĀ\", \n\"height\": 358\n}, \n\"Oriya Sangam MN\": {\n\"default\": 177, \n\"widths\": \"8*F©Ã&B>n/K,E,/tµ£¥:oy«¨ªÄ~4B/e.yyyM|t1(t1¶t||GrFthhftF*BQ¢¢¢¢`¢²ÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡¸..KĀSS\", \n\"height\": 376\n}, \n\"PCMyungjo\": {\n\"default\": 128, \n\"height\": 270\n}, \n\"STSong\": {\n\"default\": 256, \n\"widths\": \"@8h«sÓ»-KKm«8P8xxxxxxxxxx88«««]ë­£Å¨ÅÃ[U½ÕÅÈÅ {µ²çµ­¨EEUio]zE9xFÉ\\\\]Rx«ukm{{«8kĀ­ĀÃ]«ÃĀĀPPsĀU]]­­­­­­æ£¨¨¨¨[[[[ÅÅÈÈÈÈÈðĀÈµµµµ®koooo;;GB³ĀmmĀ>B[ĀĀĀĀ\", \n\"height\": 271\n}, \n\"SchoolHouse Printed A\": {\n\"default\": 91, \n\"widths\": \"?!9aYh%]]2h)^\\u001d^~$ngzrltjw$*gafI[¿¢²¡MÆ ®®{ß>`A`VC[[N[WG[X!$S$XU[[RJ?XMSQUN$B!u£4ÅgÅ.^^?2LfI¿¿¿¿¿¿á¢MMMMØ ®®®®®ýh®¥[[[[[[ NXXXX!!!!xXUUUUU]UXYXXQÜ%2ÜĀĀĀ\", \n\"height\": 319\n}, \n\"Heiti TC\": {\n\"default\": 142, \n\"widths\": \"@LO¸ÆÂ3^^mGUGpGGÞ½Ð¾|ß¯:{vë½Þßm¨´ö{ZZ¬a¯¯¦¯¦P¬343ð¨¯¯McWÕ{mZzZLÍaÕmÓĀ¶UXĀ^m½½½½½½þÐ::::Ê½ÞÞÞÞÞĐ·Þ¨¨¨¨¯¯¯¯¯¯¯Ċ¦¦¦¦¦3333¨ ¡¨¨¨ċÆ§ĀĀĀĀĀĀĀ\", \n\"height\": 264\n}, \n\"HanziPen TC\": {\n\"default\": 148, \n\"widths\": \"X_gÅµ©7XX|DpFCNzq×­¢¥ItÈ³¬n¦ÓWWzXr|aqtwkuDcw@ÀuhqtdX_|v¶vrXLXZ_d º­Nr³³Pb­­­­­­ëOOOO¡³³³³³Ĉ³rrrrrr«attttFFFFouhhhhh¤|||||r}rĈJJĈFĀ\", \n\"height\": 358\n}, \n\"Copperplate\": {\n\"default\": 156, \n\"widths\": \"NUUä¹9ddNUNGNNr«¹¹¹«¹ÇU«ÕÇÇ«Ç¹«¹«ò«dGdU«Ur¹««Çd9dU9f^^«N^r««««««Ā¹««««UUUU¹ÇÇÇÇÇÇĀÇ¹¹¹¹«ĝäUUUU«ò««««ĀGGĀ?iS\", \n\"height\": 263\n}, \n\"Geeza Pro\": {\n\"default\": 162, \n\"widths\": \"PQ`¢¢«³;SS{ÌQK¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQ¸SS\", \n\"height\": 465\n}, \n\"CNstrokeorder\": {\n\"default\": 128, \n\"height\": 284\n}, \n\"Comic Sans MS\": {\n\"default\": 204, \n\"widths\": \"M=mØ²Ò¨c^^{Gk@sMMbbî»¡¹ ®ÅªâÌÌà¡²®½¦Ċ¹£²``¡HgFÇ{}y}¯^l^= Ë£h£Ì{Ìi{§§²@s»»»»»»Ė    ¹ÌÌÌÌÌÌĲ{Ì½½½½£réHHHHæ{nâ..c­.UĀ\", \n\"height\": 357\n}, \n\"Arial Hebrew\": {\n\"default\": 177, \n\"widths\": \"G@kvµ³<>>W}7Y5P}}}}}}}}}}=>}}}qÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  GPG¢¡¡^ JNJï¡¡i`ÅMFM¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡66ĀSS\", \n\"height\": 290\n}, \n\"STIXIntegralsUpD\": {\n\"default\": 162, \n\"widths\": \"@Q`¢¢«³;SS{ÌQQ¢¢¢¢¢¢¢¢¢¢QQÌÌÌlÜ±±À¹¼JP§Ý½ÇÇ¢¢±§Û  SS¢¡¡^ JNJï¡¡i`ÅS`S¢Q¢¢¢¢`¢ÛÌÛoÌll ¢Qxl±±±±±±è±JJJJÀ½ÇÇÇÇÇĀÌÇ±±±± ÚJJJJîÌ¡ĀQQĀSS\", \n\"height\": 677\n}, \n\"Nanum Brush Script\": {\n\"default\": 74, \n\"widths\": \"HCH½¦?ZZa;3W_>a^a\\\\xT_NNssfviavnsBn{isnx}sd¯{_Ï_f@\\\\OORTWR]6Bi9gJZW\\\\WiWHaTn]>VMu×`YÛñññrif Jñ±±±±±±è±JJJJË½ÇÇÇÇÇĀhÈ±±±± ¯ÚJJJJîÝHHññv{JJ\", \n\"height\": 295\n}, \n\"Iowan Old Style\": {\n\"default\": 142, \n\"widths\": \"GVUáÕ,kktÕGZGvGGÕÕÕxĀ¹µÈ¢¾ËWU±éÏÍÍ´¢Ê¸Ċ¶©«kvkĀ{r}RLFKádq\\\\~Æ|ykkÕVÒkÕÒTÕ^^Gjkx¹¹¹¹¹¹čµ¢¢¢¢WWWWÊÏÍÍÍÍÍĖÕÍÊÊÊÊ©{{{{{{Âr}}}}LLLLáÕ||ĀGGĀ$JS\", \n\"height\": 349\n}, \n\"Savoye LET\": {\n\"default\": 128, \n\"widths\": \",D\\u001f¼IoÀ\\u0013UU<N;=;aW1LONIP=SN;;8N8V¶§{µy°mo´²zwyÂUaU<1SP=Q>)NP%\\\"J%ySKQM77.MAd=K;f<fGDALR<ÃC·ÃlN&(*KC[§§§§§§Ą{%%%%µòNMSSSSSSj=>>>>%%%%SKKKKKoNKMMMMKKĝ;;@Ā?iS\", \n\"height\": 304\n}, \n\"Gujarati MT\": {\n\"default\": 128, \n\"widths\": \"fHo¿ÇASSs;d;TMMhì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹kTkXUrrrUGGGÇUdG¹rkNkU3ÃÃf``t@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹õ;;Zâ?iS\", \n\"height\": 395\n}, \n\"PortagoITC TT\": {\n\"default\": 100, \n\"widths\": \"#;Tu^:88mÌ/@*>dG[\\\\W_`R^_+.ÌÌÌS»rpjr_Wot7`lV¡pgqof_skªkj`;N;©db\\\\dSMae2T_Mob\\\\caYSd]\\\\\\\\T=c=Ì;V]©ogÎdÌcÕ??v7>dSrrrrrrj____7777spppppÌpssssjg±dddddc\\\\SSSS2222dobbbbbÕhddddZ\\\\²%%lĀZZ\", \n\"height\": 312\n}, \n\"Times\": {\n\"default\": 128, \n\"widths\": \"@UiÕÇ.UU@U@GGGrì¹««¹¹¹Ud¹ä¹¹¹«¹¹ò¹¹UGUxUrrrUGGGÇUdG¹r{3{U3ÃÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹ĀUUZĀ?iS\", \n\"height\": 292\n}, \n\"Oriya MN\": {\n\"default\": 128, \n\"widths\": \"KKcÝÍ.``gCM9D9Fyø®ªËÊÑ¾Izºï¼ÝÛ¦¥¼­ð­§ªQDP{Pe<?<ë¢gyXÐ|T,TU3ÍÃfMMt@Or¹¹¹¹¹¹ä«UUUU¹¹¹¹¹¹¹ä¹¹¹¹¹¹rrrrrr«rrrrrGGGG¹Ï<<\\\\Ā?iS\", \n\"height\": 382\n}\n}, \n\"size\": 256\n}"
  },
  {
    "path": "mocodo/resources/grammar.lark",
    "content": "// NOTE: add a newline at the beginning and at the end of the input before parsing it.\n// https://github.com/lark-parser/lark/discussions/1041\n\n%import common.NUMBER\nseq{item}: item (COMMA item)*\n\nCOMMA: SP? \",\" SP?\nCOLON: SP? \":\" SP?\nNL.-10: /[^\\S\\r\\n]*\\r?\\n/\nSLASH: \"/\"\nBACKSLASH: \"\\\\\"+\nLPAREN: SP? \"(\" SP?\nRPAREN: SP? \")\" SP?\nCONSTRAINT_LPAREN: SP? \"(\"\nCONSTRAINT_RPAREN: \")\" SP?\nLBRACKET: SP? \"[\"\nRBRACKET: \"]\" SP?\nHASHTAG: \"#\"\nPERCENT: \"%\"\nSP.-50: /[^\\S\\r\\n]+/\n\nBOX_NAME: /(?![\\W_\\d])[^=<>,:\\n\\\\]*[^-\\[\\\\\\]=<>,:\\s\\\\]/\ntyped_attr: (attr (LBRACKET datatype? RBRACKET)?)?\ndatatype: note\n!box_def_prefix: \"+\" | \"-\"\n\nATTR: /(?=\\w)(?!_)[^\\[\\]>,\\r\\n!?]*[^\\[\\]>,\\s]/\n?note: /[^\\r\\n\\]]+/\n\nstart: (break_ | line)*\nBREAK.100: /^\\n/\nline: indent? (phantoms | comment | clause | NL)\n?clause: assoc_clause\n        | entity_clause\n        | constraint_clause\n        | inheritance_clause\n\nPHANTOMS: /( *:)+ */ NL\nindent: INDENT\nINDENT.10: / +|\\t+/\ncomment: PERCENT /.*\\r?\\n/\n\n// Associations\n\nassoc_clause: box_def_prefix? assoc_name_def COMMA seq{assoc_leg} (COLON seq{assoc_attr})? NL\nassoc_name_def: box_name\nassoc_leg: _assoc_card? leg_arrow? SP? (LBRACKET leg_note? RBRACKET)? entity_name_ref\n_assoc_card: card_hidden? card_prefix? card\nentity_name_ref: box_name\n!card_hidden: \"-\"\n!card_prefix: \"_\" | \"/\"\nCARD.2: /(?![-_\\/])(\\w|\\?){2}(?=[ \\t]*[^\\w,\\r\\n:])/\nLEG_ARROW: /[<>]/\nleg_note: note\nassoc_attr: id_mark? typed_attr\n\n// Entities\n\nentity_clause: box_def_prefix? entity_name_def COLON seq{entity_or_table_attr}? NL\nentity_name_def: box_name\nentity_or_table_attr: _id_symbols? (typed_attr | HASHTAG foreign_reference)\n_id_symbols: id_groups? id_mark\nID_GROUPS.10: /\\d+(?=_)/\nID_MARK: \"_\"\nforeign_reference: this_table_attr MORETHAN that_table MORETHAN that_table_attr\nthis_table_attr: attr\nthat_table_attr: attr\nthat_table: entity_name_ref\nMORETHAN: SP? \">\" SP?\n\n// Constraints\n\nconstraint_clause: CONSTRAINT_LPAREN constraint_name? CONSTRAINT_RPAREN (LBRACKET constraint_note? RBRACKET)? seq{constraint_target}? (COLON constraint_coords)? NL\nCONSTRAINT_NAME: /[^)]{1,3}/\nconstraint_note: note\nconstraint_target: constraint_leg? SP* box_name_ref\nbox_name_ref: box_name\nCONSTRAINT_LEG: /<?(\\.+|-+)>?/\nconstraint_coords: _constraint_coord COMMA _constraint_coord\n_constraint_coord: NUMBER | box_name_ref\n\n// Inheritance\n\ninheritance_clause: SLASH inheritance_name? BACKSLASH SP? inheritance_parent SP? inheritance_arrow SP? seq{inheritance_child} (COLON seq{typed_attr})? NL\nINHERITANCE_NAME: /(XT\\d?|TX\\d?|X\\d?|T\\d?|\\d)/\ninheritance_parent: entity_name_ref\ninheritance_child: entity_name_ref\nINHERITANCE_ARROW.-10: /<==?|<--?|--?>|==?>/\n\n// Avoid anonymous tokens for some terminals\n\nconstraint_leg: CONSTRAINT_LEG\ncard: CARD\nbox_name: BOX_NAME\nleg_arrow: LEG_ARROW\nphantoms: PHANTOMS\nbreak_: BREAK\ninheritance_name: INHERITANCE_NAME\nconstraint_name: CONSTRAINT_NAME\nattr: ATTR\ninheritance_arrow: INHERITANCE_ARROW\nid_mark: ID_MARK\nid_groups: ID_GROUPS\n"
  },
  {
    "path": "mocodo/resources/i18n/messages_fr.po",
    "content": "# MOCODO\n# Copyright (C) 2023 Aristide Grange\n# \n# Translators:\n# Aristide Grange, 2023\nmsgid \"\"\nmsgstr \"Project-Id-Version: mocodo\\nPOT-Creation-Date: 2023-09-23 13:41+0200\\nPO-Revision-Date: 2015-08-16 07:00+0000\\nLast-Translator: Aristide Grange <chewingword@wingi.net>, 2015-2016,2022-2023\\nLanguage-Team: French (http://app.transifex.com/aristide/mocodo/language/fr/)\\nMIME-Version: 1.0\\nContent-Type: text/plain; charset=UTF-8\\nContent-Transfer-Encoding: 8bit\\nGenerated-By: pygettext.py 1.5\\nLanguage: fr\\nPlural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\n#: mocodo/__main__.py:103\nmsgid \"Unknown argument \\\"{k}\\\" for option --select.\"\nmsgstr \"Argument « {k} » inconnu pour l'option --select.\"\n\n#: mocodo/__main__.py:227\nmsgid \"The file \\\"{path}\\\" is missing.\"\nmsgstr \"Le fichier « {path} » est manquant.\"\n\n#: mocodo/__main__.py:229\nmsgid \"The file \\\"{path}\\\" is not a valid JSON file.\"\nmsgstr \"Le fichier « {path} » n'est pas un fichier JSON valide.\"\n\n#: mocodo/__main__.py:231\nmsgid \"The file \\\"{path}\\\" could not be read:\\n{err}\"\nmsgstr \"Le fichier « {path} » n'a pas pu être lu :\\n{err}\"\n\n#: mocodo/__main__.py:235\nmsgid \"No third-party rendering service for extension \\\"{extension}\\\". You may want to add one in \\\"{path}\\\".\"\nmsgstr \"Aucun service de rendu tiers pour l'extension « {extension} ». Vous pouvez en ajouter un dans « {path} ».\"\n\n#: mocodo/__main__.py:255\nmsgid \"The HTTP status code {code} was returned by:\\n{url}\"\nmsgstr \"Le code HTTP {code} a été retourné par :\\n{url}\"\n\n#: mocodo/__main__.py:257\nmsgid \"Error while trying to retrieve the URL:\\n{url}\\n{e}\"\nmsgstr \"Erreur lors de la tentative de récupération de l'URL :\\n{url}\\n{e}\"\n\n#: mocodo/__main__.py:285\nmsgid \"  - Leg \\\"{b1} — {b2}\\\" overlaps \\\"{b3}\\\".\"\nmsgstr \"  - La patte « {b1} — {b2} » chevauche « {b3} ».\"\n\n#: mocodo/__main__.py:287\nmsgid \"  - Legs \\\"{b1} — {b2}\\\" and \\\"{b3} — {b4}\\\" overlap.\"\nmsgstr \"  - Les pattes  « {b1} — {b2} » et « {b3} — {b4} » se chevauchent.\"\n\n#: mocodo/__main__.py:289\nmsgid \"Bad layout of boxes:\\n{details}\\nTo fix the problem, reorder and/or skip lines in the source text, either manually, or with the option -t arrange (chocolate bar under Mocodo online).\"\nmsgstr \"Mauvaise disposition des boîtes :\\n{details}\\nPour corriger cela, réordonnez et/ou sautez des lignes dans le texte-source, soit à la main, soit à l'aide de l'option -t arrange (tablette de chocolat sous Mocodo online).\"\n\n#: mocodo/argument_parser.py:401\nmsgid \"OPTIONS ON MOCODO ITSELF\"\nmsgstr \"OPTIONS SUR MOCODO LUI-MÊME \"\n\n#: mocodo/argument_parser.py:402\nmsgid \"INPUT/OUTPUT\"\nmsgstr \"ENTRÉE/SORTIE \"\n\n#: mocodo/argument_parser.py:404\nmsgid \"ASPECT OF THE GRAPHICAL OUTPUT\"\nmsgstr \"ASPECT DE LA SORTIE GRAPHIQUE \"\n\n#: mocodo/argument_parser.py:406\nmsgid \"\"\n\"\\n\"\n\"        NAME:\\n\"\n\"        Mocodo - An Entity-Relation Diagram Generator.\\n\"\n\"\\n\"\n\"        DESCRIPTION:\\n\"\n\"        Mocodo is an open-source tool for designing and teaching relational databases.\\n\"\n\"        It takes as an input a textual description of both entities and associations\\n\"\n\"        of an entity-relationship diagram (ERD). It outputs a vectorial drawing in SVG\\n\"\n\"        and a relational schema in various formats (SQL, LaTeX, Markdown, etc.).\\n\"\n\"\\n\"\n\"        NOTE:\\n\"\n\"        Each one of the following values is:\\n\"\n\"        - explicitely specified by the user as a command line option;\\n\"\n\"        - otherwise, retrieved from a file located at --params_path;\\n\"\n\"        - otherwise, retrieved from a file named 'params.json' in the input directory;\\n\"\n\"        - otherwise, calculated from a default value, possibly dependant of your system.\\n\"\n\"    \"\nmsgstr \"\"\n\"\\n\"\n\"        NOM :\\n\"\n\"        Mocodo - Un générateur de diagrammes entité-association.\\n\"\n\"\\n\"\n\"        DESCRIPTION :\\n\"\n\"        Mocodo est un outil libre destiné à l'enseignement des bases de données relationnelles.\\n\"\n\"        Il prend en entrée une description textuelle des entités et associations d'un diagramme\\n\"\n\"        entité-association (MCD). Il produit en sortie un dessin vectoriel en SVG et un schéma\\n\"\n\"        relationnel dans divers formats (SQL, LaTeX, Markdown, etc.).\\n\"\n\"\\n\"\n\"        NOTE :\\n\"\n\"        Chacune des valeurs suivantes est :\\n\"\n\"        - spécifiée explicitement par l'utilisateur comme option de ligne de commande ;\\n\"\n\"        - sinon, récupérée depuis un fichier de chemin --params_path ;\\n\"\n\"        - sinon, récupérée depuis un fichier nommé « params.json » dans le répertoire d'entrée ;\\n\"\n\"        - sinon, calculée à partir d'une valeur par défaut, éventuellement dépendante de votre système.\\n\"\n\"    \"\n\n#: mocodo/argument_parser.py:424\nmsgid \"\"\n\"\\n\"\n\"        SEE ALSO:\\n\"\n\"          Online version        https://mocodo.net\\n\"\n\"          Source code           https://github.com/laowantong/mocodo\\n\"\n\"          Documentation         https://laowantong.github.io/mocodo/doc/fr_refman.html\\n\"\n\"          Cheat sheet for -t    https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md\\n\"\n\"\\n\"\n\"        LICENSE:                MIT\\n\"\n\"\\n\"\n\"        CONTACT:\\n\"\n\"          Author                Aristide Grange\\n\"\n\"          Address               Université de Lorraine\\n\"\n\"                                Laboratoire LCOMS - UFR MIM\\n\"\n\"                                3 rue Augustin Fresnel\\n\"\n\"                                57070 METZ Technopôle\\n\"\n\"                                France\\n\"\n\"          Mail                  <author.full.name>@univ-lorraine.fr\\n\"\n\"    \"\nmsgstr \"\"\n\"\\n\"\n\"        VOIR AUSSI :\\n\"\n\"          Version en ligne      https://mocodo.net\\n\"\n\"          Code source           https://github.com/laowantong/mocodo\\n\"\n\"          Documentation         https://laowantong.github.io/mocodo/doc/fr_refman.html\\n\"\n\"          Aide-mémoire pour -t  https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md\\n\"\n\"\\n\"\n\"        LICENCE :               MIT\\n\"\n\"\\n\"\n\"        CONTACT :\\n\"\n\"          Auteur                Aristide Grange\\n\"\n\"          Adresse               Université de Lorraine\\n\"\n\"                                Laboratoire LCOMS - UFR MIM\\n\"\n\"                                3 rue Augustin Fresnel\\n\"\n\"                                57070 METZ Technopôle\\n\"\n\"                                France\\n\"\n\"          Courriel              <prénom.nom>@univ-lorraine.fr\\n\"\n\"    \"\n\n#: mocodo/argument_parser.py:93\nmsgid \"rearrange the layout with either a Branch & Bound or a Genetic Algorithm\"\nmsgstr \"réarrange la disposition, soit par Branch & Bound, soit avec un algorithme génétique\"\n\n#: mocodo/argument_parser.py:98\nmsgid \"rewrite the given elements in ASCII\"\nmsgstr \"réécrit les éléments donnés en ASCII\"\n\n#: mocodo/argument_parser.py:104\nmsgid \"dump the abstract syntax tree of the source text (for debugging purposes)\"\nmsgstr \"crée l'arbre de syntaxe abstraite du texte source (pour le débogage)\"\n\n#: mocodo/argument_parser.py:109\nmsgid \"rewrite the given elements in camelCase\"\nmsgstr \"réécrit les éléments donnés en camelCase\"\n\n#: mocodo/argument_parser.py:115\nmsgid \"rewrite the given elements by capitalizing the first letter of each word\"\nmsgstr \"réécrit les éléments donnés en capitalisant la première lettre de chaque mot\"\n\n#: mocodo/argument_parser.py:121\nmsgid \"rewrite the given elements in lowercase, but more aggressively than 'lower'\"\nmsgstr \"réécrit les éléments donnés en minuscules, mais plus agressivement que « lower »\"\n\n#: mocodo/argument_parser.py:127\nmsgid \"convert the conceptual model into a Chen's ERD\"\nmsgstr \"convertit le modèle conceptuel dans la notation de Chen\"\n\n#: mocodo/argument_parser.py:132\nmsgid \"try to infer types, entities, CIFs or DF arrows from the existing elements\"\nmsgstr \"essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants\"\n\n#: mocodo/argument_parser.py:138\nmsgid \"convert the conceptual model into a crow's foot ERD\"\nmsgstr \"convertit le modèle conceptuel dans la notation crow's foot\"\n\n#: mocodo/argument_parser.py:143\nmsgid \"collect all the attributes of the MCD in a table\"\nmsgstr \"extrait tous les attributs du MCD dans une table\"\n\n#: mocodo/argument_parser.py:148\nmsgid \"suppress the given elements whenever possible\"\nmsgstr \"supprime les éléments donnés quand c'est possible\"\n\n#: mocodo/argument_parser.py:154\nmsgid \"move any (1,1) association attribute to the appropriate entity\"\nmsgstr \"déplace tout attribut d'association (1,1) vers l'entité appropriée\"\n\n#: mocodo/argument_parser.py:159\nmsgid \"replace all element names by a numbered generic label\"\nmsgstr \"remplace tous les noms d'éléments par un libellé générique numéroté\"\n\n#: mocodo/argument_parser.py:164\nmsgid \"rewrite the source text as is\"\nmsgstr \"réécrit le texte source tel quel\"\n\n#: mocodo/argument_parser.py:169\nmsgid \"decompose any n-ary (*,N) associations into n binary ones\"\nmsgstr \"décompose toute association n-aire (*,N) en n associations binaires\"\n\n#: mocodo/argument_parser.py:174\nmsgid \"try to fix common errors in the given elements\"\nmsgstr \"essaie de corriger les erreurs courantes dans les éléments donnés\"\n\n#: mocodo/argument_parser.py:180\nmsgid \"apply a vertical, horizontal or diagonal symmetry to the diagram\"\nmsgstr \"applique au diagramme une symétrie verticale, horizontale ou diagonale\"\n\n#: mocodo/argument_parser.py:185\nmsgid \"add random entities and associations (default: 10 new associations)\"\nmsgstr \"ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations)\"\n\n#: mocodo/argument_parser.py:190\nmsgid \"rewrite the given elements in lowercase\"\nmsgstr \"réécrit les éléments donnés en minuscules\"\n\n#: mocodo/argument_parser.py:196\nmsgid \"prefix the given elements with the given string\"\nmsgstr \"préfixe les éléments donnés avec la chaîne donnée\"\n\n#: mocodo/argument_parser.py:202\nmsgid \"keep the stucture, but replace the given elements with random ones whenever possible\"\nmsgstr \"garde la structure, mais randomise les éléments donnés quand c'est possible\"\n\n#: mocodo/argument_parser.py:208\nmsgid \"convert the conceptual model into a relational schema with the given template path\"\nmsgstr \"convertit le modèle conceptuel en schéma relationnel avec le gabarit donné\"\n\n#: mocodo/argument_parser.py:213\nmsgid \"rewrite the given elements by applying the given 'search/repl' pattern\"\nmsgstr \"réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné\"\n\n#: mocodo/argument_parser.py:219\nmsgid \"rewrite the given elements in snake_case\"\nmsgstr \"réécrit les éléments donnés en snake_case\"\n\n#: mocodo/argument_parser.py:225\nmsgid \"decompose any n-ary (*,1) associations into n-1 binary ones\"\nmsgstr \"décompose toute association n-aire (*,1) en n-1 associations binaires\"\n\n#: mocodo/argument_parser.py:230\nmsgid \"suffix the given elements with the given string\"\nmsgstr \"suffixe les éléments donnés avec la chaîne donnée\"\n\n#: mocodo/argument_parser.py:236\nmsgid \"rewrite the given elements by swapping the case of each letter\"\nmsgstr \"réécrit les éléments donnés en inversant la casse de chaque lettre\"\n\n#: mocodo/argument_parser.py:238\nmsgid \"The template '{stem}' doesn't have a help message in language of code '{language}' or 'en'.\"\nmsgstr \"Le gabarit « {stem} » n'a pas de message d'aide dans la langue de code « {language} » ou « en ».\"\n\n#: mocodo/argument_parser.py:242\nmsgid \"rewrite the given elements in Title Case\"\nmsgstr \"réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule\"\n\n#: mocodo/argument_parser.py:254\nmsgid \"convert the conceptual model into a UML class diagram\"\nmsgstr \"convertit le modèle conceptuel en diagramme de classes UML\"\n\n#: mocodo/argument_parser.py:259\nmsgid \"encode the MCD into a URL for Mocodo online\"\nmsgstr \"encode le MCD dans une URL pour Mocodo online\"\n\n#: mocodo/argument_parser.py:264\nmsgid \"rewrite the given elements in UPPERCASE\"\nmsgstr \"réécrit les éléments donnés en majuscules\"\n\n#: mocodo/argument_parser.py:288\nmsgid \"The transformation '{subopt}' is not among the possible ones:\\n{valid}.\"\nmsgstr \"La transformation « {subopt} » n'est pas parmi celles qui sont possibles :\\n{valid}.\"\n\n#: mocodo/argument_parser.py:291\nmsgid \"rewrite the given elements by keeping only a given slice\"\nmsgstr \"réécrit les éléments donnés en n'en gardant qu'une tranche donnée\"\n\n#: mocodo/argument_parser.py:324\nmsgid \"truncate the given elements to the given length (default: {n})\"\nmsgstr \"tronque les éléments donnés à la longueur donnée (par défaut : {n})\"\n\n#: mocodo/argument_parser.py:412\nmsgid \"override the automatic localization of the messages with the given language code (e.g., 'fr', 'en', ...)\"\nmsgstr \"force la localisation des messages avec le code de langue donné (par exemple, « fr », « en », ...)\"\n\n#: mocodo/argument_parser.py:417\nmsgid \"the path of the parameter file. If omitted, use 'params.json' in the input directory. If non existent, use default parameters.\"\nmsgstr \"le chemin du fichier de paramètres. S'il est omis, utilise « params.json » dans le répertoire d'entrée. S'il n'existe pas, utilise les paramètres par défaut.\"\n\n#: mocodo/argument_parser.py:421\nmsgid \"the path of the input file. By default, the output files will be generated in the same directory\"\nmsgstr \"le chemin du fichier d'entrée. Par défaut, les fichiers de sortie seront générés dans le même répertoire\"\n\n#: mocodo/argument_parser.py:443\nmsgid \"show this help message, then exit\"\nmsgstr \"affiche ce message d'aide, puis termine\"\n\n#: mocodo/argument_parser.py:448\nmsgid \"display the version number, then exit\"\nmsgstr \"affiche le numéro de version, puis termine\"\n\n#: mocodo/argument_parser.py:452\nmsgid \"recreate a pristine version of the files 'sandbox.mcd' and 'params.json' in the input directory, then exit\"\nmsgstr \"recrée une version vierge des fichiers « sandbox.mcd » et « params.json » dans le répertoire d'entrée, puis termine\"\n\n#: mocodo/argument_parser.py:457\nmsgid \"the directory of the output files\"\nmsgstr \"le répertoire des fichiers de sortie\"\n\n#: mocodo/argument_parser.py:462\nmsgid \"one or several encodings to be tried successively when reading the input file\"\nmsgstr \"un ou plusieurs encodages à essayer successivement lors de la lecture du fichier d'entrée\"\n\n#: mocodo/argument_parser.py:468\nmsgid \"generate a PNG or a PDF version of the SVG output (requires CairoSVG)\"\nmsgstr \"génère une version PNG ou PDF de la sortie SVG (requiert CairoSVG)\"\n\n#: mocodo/argument_parser.py:472\nmsgid \"display the contents of the parameter file, then exit\"\nmsgstr \"affiche le contenu du fichier de paramètres, puis termine\"\n\n#: mocodo/argument_parser.py:476\nmsgid \"reuse the geometry file of the previous execution\"\nmsgstr \"réutilise le fichier de géométrie de l'exécution précédente\"\n\n#: mocodo/argument_parser.py:482\nmsgid \"discriminate between multiple SVG of the same interactive diagram\"\nmsgstr \"ajoute un discriminateur à un SVG interactif\"\n\n#: mocodo/argument_parser.py:488\nmsgid \"under Jupyter Notebook, explicitely state the categories of results to display\"\nmsgstr \"sous Jupyter Notebook, spécifie explicitement les catégories de résultats à afficher\"\n\n#: mocodo/argument_parser.py:494\nmsgid \"use an external web-service to further convert the conversion results into the given graphical formats\"\nmsgstr \"utilise un service web externe pour convertir les résultats de la conversion dans les formats graphiques donnés\"\n\n#: mocodo/argument_parser.py:498\nmsgid \"backward compatibility alias for '-t' (with no arguments). Same as '-t markdown' but, under Jupyter Notebook, does not prevent the rendering of the conceptual diagram in the cell output\"\nmsgstr \"alias de compatibilité ascendante pour « -t » (sans arguments). Équivalent à « -t markdown » mais, sous Jupyter Notebook, n'empêche pas le rendu du diagramme conceptuel dans la sortie de la cellule\"\n\n#: mocodo/argument_parser.py:519\nmsgid \"make a new version of the MCD by applying sequentially the given rewriting operations, and/or convert it into the given formats or languages. Under Jupyter Notebook, '-T' respectively replaces the current cell by the textual result, or copies it into the clipboard (pip3 install pyperclip)\"\nmsgstr \"crée une nouvelle version du MCD en appliquant séquentiellement les opérations de réécriture données, et/ou le convertit dans les formats ou langages donnés. Sous Jupyter Notebook, « -T » remplace respectivement la cellule courante par le résultat textuel, ou le copie dans le presse-papier (pip3 install pyperclip)\"\n\n#: mocodo/argument_parser.py:521\nmsgid \"initial value for the random number generator\"\nmsgstr \"valeur initiale pour le générateur de nombres aléatoires\"\n\n#: mocodo/argument_parser.py:525\nmsgid \"Untitled\"\nmsgstr \"MCD\"\n\n#: mocodo/argument_parser.py:527\nmsgid \"name of the model, used at various places (file system, database, etc.)\"\nmsgstr \"nom du modèle, utilisé à divers endroits (système de fichiers, base de données, etc.)\"\n\n#: mocodo/argument_parser.py:534\nmsgid \"the acronym to be circled in a functional dependency\"\nmsgstr \"l'acronyme à entourer dans une dépendance fonctionnelle\"\n\n#: mocodo/argument_parser.py:541\nmsgid \"format string for minimal and maximal cardinalities\"\nmsgstr \"chaîne de formatage pour les cardinalités minimales et maximales\"\n\n#: mocodo/argument_parser.py:370\nmsgid \"format string for foreign keys in relational diagram\"\nmsgstr \"chaîne de formatage pour les clés étrangères dans le diagramme relationnel\"\n\n#: mocodo/argument_parser.py:548\nmsgid \"string for relative cardinalities\"\nmsgstr \"chaîne pour les cardinalités relatives\"\n\n#: mocodo/argument_parser.py:554\nmsgid \"flex straight legs whose cardinalities may collide\"\nmsgstr \"incurve les pattes rectilignes dont les cardinalités peuvent se chevaucher\"\n\n#: mocodo/argument_parser.py:559\nmsgid \"the color palette to use when generating the drawing. Name (without extension) of a file located in the directory 'colors', or path to a personal file\"\nmsgstr \"la palette de couleurs à utiliser lors de la génération du dessin. Nom (sans extension) d'un fichier situé dans le répertoire « colors », ou chemin vers un fichier personnel\"\n\n#: mocodo/argument_parser.py:563\nmsgid \"specification of the fonts, dimensions, etc. Name (without extension) of a file located in the directory 'shapes', or path to a personal file\"\nmsgstr \"spécification des polices, dimensions, etc. Nom (sans extension) d'un fichier situé dans le répertoire « shapes », ou chemin vers un fichier personnel\"\n\n#: mocodo/argument_parser.py:569\nmsgid \"scale the diagram by the given factor\"\nmsgstr \"applique au diagramme le facteur de mise à l'échelle donné\"\n\n#: mocodo/argument_parser.py:575\nmsgid \"scale all calculated text widths by the given factor\"\nmsgstr \"applique à tous les textes calculés le facteur de mise à l'échelle donné\"\n\n#: mocodo/argument_parser.py:579\nmsgid \"raise an error when horizontal or vertical legs overlap\"\nmsgstr \"lève une erreur quand des pattes horizontales ou verticales se chevauchent\"\n\n#: mocodo/argument_parser.py:424\nmsgid \"forbid the use of identifiers in associations (according to the Merise standard)\"\nmsgstr \"interdit l'utilisation d'identifiants dans les associations (conformément au standard Merise)\"\n\n#: mocodo/argument_parser.py:586\nmsgid \"set the visibility and the contents of the lateral gutters\"\nmsgstr \"définit la visibilité et le contenu des gouttières latérales\"\n\n#: mocodo/association.py:40\nmsgid \"The association \\\"{name}\\\" cannot have an identifier.\"\nmsgstr \"L'association « {name} » ne peut pas avoir d'identifiant.\"\n\n#: mocodo/association.py:50\nmsgid \"The association \\\"{name}\\\" should have at least 3 legs to become a cluster.\"\nmsgstr \"L'association « {name} » devrait avoir au moins 3 pattes pour devenir un agrégat.\"\n\n#: mocodo/association.py:77\nmsgid \"An association named \\\"{df_label}\\\" must have at least one leg with a maximal cardinality of 1.\"\nmsgstr \"Une association nommée « {df_label} » doit avoir au moins une patte avec une cardinalité maximale de 1.\"\n\n#: mocodo/common.py:29\nmsgid \"Output file \\\"{filename}\\\" successfully generated.\"\nmsgstr \"Fichier de sortie « {filename} » généré avec succès.\"\n\n#: mocodo/common.py:34\nmsgid \"Source file \\\"{filename}\\\" successfully updated.\"\nmsgstr \"Fichier source « {filename} » mis à jour avec succès.\"\n\n#: mocodo/common.py:44\nmsgid \"Unable to read \\\"{filename}\\\" with any of the following encodings: \\\"{encodings}\\\".\"\nmsgstr \"Impossible de lire « {filename} » dans aucun des encodages suivants : \\\\\\\"{encodings}\\\\\\\".\"\n\n#: mocodo/common.py:50\nmsgid \"The file \\\"{input}\\\" doesn't exist.\"\nmsgstr \"Le fichier « {input} » n'existe pas.\"\n\n#: mocodo/common.py:60 mocodo/common.py:65\nmsgid \"Problem with \\\"{name}\\\" file \\\"{path}\\\".\"\nmsgstr \"Problème lors du chargement de « {name} » au bout du chemin « {path} ».\"\n\n#: mocodo/convert/_uml.py:22\nmsgid \"{complete, disjoint}\"\nmsgstr \"{complet, disjoint}\"\n\n#: mocodo/convert/_uml.py:23\nmsgid \"{incomplete, disjoint}\"\nmsgstr \"{incomplet, disjoint}\"\n\n#: mocodo/convert/_uml.py:24\nmsgid \"{complete, overlapping}\"\nmsgstr \"{complet, non disjoint}\"\n\n#: mocodo/convert/_uml.py:25\nmsgid \"{incomplete, overlapping}\"\nmsgstr \"{incomplet, non disjoint}\"\n\n#: mocodo/convert/read_template.py:16\nmsgid \"Circular inheritance in template \\\"{name}.yaml\\\" of \\\"{folder}.\"\nmsgstr \"Héritage circulaire dans le gabarit « {name}.yaml » de « {folder} ».\"\n\n#: mocodo/convert/read_template.py:19\nmsgid \"Template \\\"{name}.yaml\\\" not found in \\\"{folder}\\\".\"\nmsgstr \"Gabarit « {name}.yaml » introuvable dans « {folder} ».\"\n\n#: mocodo/convert/read_template.py:23\nmsgid \"Unable to decode template \\\"{name}.yaml\\\" of \\\"{folder}\\\".\"\nmsgstr \"Impossible de décoder le gabarit « {name}.yaml » de « {folder} ».\"\n\n#: mocodo/convert/read_template.py:26\nmsgid \"Template \\\"{name}.yaml\\\" of \\\"{folder}\\\" contains a YAML object as value of key \\\"{key}\\\".\"\nmsgstr \"Le gabarit « {name}.yaml » de « {folder} » contient un objet YAML comme valeur de la clé « {key} ».\"\n\n#: mocodo/convert/read_template.py:32\nmsgid \"Template \\\"{name}.yaml\\\" of \\\"{folder}\\\" contains a YAML array as value of key \\\"{key}\\\" which does not contain only YAML objects.\"\nmsgstr \"Le gabarit « {name}.yaml » de « {folder} » contient un tableau YAML comme valeur de la clé « {key} » qui ne contient pas uniquement des objets YAML.\"\n\n#: mocodo/convert/read_template.py:34\nmsgid \"Template \\\"{name}.yaml\\\" of \\\"{folder}\\\" contains a YAML array as value of key \\\"{key}\\\" which does not contain only objects having an \\\"order\\\" key.\"\nmsgstr \"Le gabarit « {name}.yaml » de « {folder} » contient un tableau YAML comme valeur de la clé « {key} » qui ne contient pas uniquement des objets ayant une clé « order ».\"\n\n#: mocodo/convert/read_template.py:37\nmsgid \"Template \\\"{name}.yaml\\\" of \\\"{folder}\\\" contains a YAML array as value of key \\\"{key}\\\" where the \\\"order\\\" key is not associated to a number.\"\nmsgstr \"Le gabarit « {name}.yaml » de « {folder} » contient un tableau YAML comme valeur de la clé « {key} » où la clé « order » n'est pas associée à un nombre.\"\n\n#: mocodo/convert/read_template.py:39\nmsgid \"Template \\\"{name}.yaml\\\" of \\\"{folder}\\\" contains a YAML array as value of key \\\"{key}\\\" where the \\\"order\\\" keys are not sorted in ascending order.\"\nmsgstr \"Le gabarit « {name}.yaml » de « {folder} » contient un tableau YAML comme valeur de la clé « {key} » où les clés « order » ne sont pas triées par ordre croissant.\"\n\n#: mocodo/convert/relations.py:121\nmsgid \"Cannot compile the regular expression \\\"{regex}\\\" or the remplacement string \\\"{replace}\\\" in a relation template producing \\\"*{stem_suffix}.{extension}\\\" files.\"\nmsgstr \"Impossible de compiler l'expression régulière « {regex} » ou la chaîne de remplacement « {replace} » dans un gabarit de relation produisant des fichiers « *{stem_suffix}.{extension} ».\"\n\n#: mocodo/convert/relations.py:244\nmsgid \"Reciprocal relative identification around {association}.\"\nmsgstr \"Identification relative réciproque autour de {association}.\"\n\n#: mocodo/convert/relations.py:325\nmsgid \"A weak entity (here, {entity}) cannot be strengthened by itself.\"\nmsgstr \"Une entité faible (ici, {entity}) ne peut pas être renforcée par elle-même.\"\n\n#: mocodo/convert/relations.py:328\nmsgid \"Cycle of weak entities in {entities}.\"\nmsgstr \"Cycle d'entités faibles dans {entities}.\"\n\n#: mocodo/convert/relations.py:339\nmsgid \"Totality (/T\\\\ or /XT\\\\) is mandatory for \\\"=>\\\" inheritance of parent \\\"{name}\\\".\"\nmsgstr \"La totalité (/T\\\\ ou /XT\\\\) est obligatoire pour l'héritage « => » de l'entité-mère « {name} ».\"\n\n#: mocodo/convert/relations.py:600\nmsgid \"is {name}\"\nmsgstr \"est {name}\"\n\n#: mocodo/diagram_link.py:11 mocodo/leg.py:443\nmsgid \"Attribute \\\"{attribute}\\\" in entity \\\"{entity_1}\\\" references an unknown entity \\\"{entity_2}\\\".\"\nmsgstr \"L'attribut « {attribute} » de l'entité « {entity_1} » fait référence à une entité « {entity_2} » inconnue.\"\n\n#: mocodo/diagram_link.py:17 mocodo/leg.py:449\nmsgid \"Attribute \\\"{attribute_1}\\\" in entity \\\"{entity_1}\\\" references an unknown attribute \\\"{attribute_2}\\\" in entity \\\"{entity_2}\\\".\"\nmsgstr \"L'attribute « {attribute_1} » de l'entité « {entity_1} » fait référence à un attribut « {attribute_2} » inconnu dans l'entité « {entity_2} ».\"\n\n#: mocodo/mcd.py:81\nmsgid \"Duplicate association \\\"{name}\\\". If you want to make two associations appear with the same name, you must suffix it with a number.\"\nmsgstr \"Association « {name} » dupliquée. Si vous souhaitez faire apparaître deux associations sous le même nom, vous devez suffixer celui-ci avec un nombre.\"\n\n#: mocodo/mcd.py:87\nmsgid \"Duplicate entity \\\"{name}\\\". If you want to make two entities appear with the same name, you must suffix it with a number.\"\nmsgstr \"Entité « {name} » dupliquée. Si vous souhaitez faire apparaître deux entités sous le même nom, vous devez suffixer celui-ci avec un nombre.\"\n\n#: mocodo/mcd.py:93\nmsgid \"One entity and one association share the same name \\\"{name}\\\".\"\nmsgstr \"Une entité et une association ont le même nom « {name} ».\"\n\n#: mocodo/mcd.py:97\nmsgid \"The ERD \\\"{title}\\\" is empty.\"\nmsgstr \"Le MCD « {title} » est vide.\"\n\n#: mocodo/mcd.py:115\nmsgid \"Association \\\"{association}\\\" linked to another association \\\"{entity}\\\"!\"\nmsgstr \"Association « {association} » liée à une autre association « {entity} ».\"\n\n#: mocodo/mcd.py:117\nmsgid \"Association \\\"{association}\\\" linked to an unknown entity \\\"{entity}\\\"!\"\nmsgstr \"Association « {association} » liée à une entité inconnue « {entity} ».\"\n\n#: mocodo/mcd.py:124\nmsgid \"Inheritance \\\"{inheritance}\\\" linked to an association \\\"{entity}\\\"!\"\nmsgstr \"L'héritage « {inheritance} » est lié à une association « {entity} ».\"\n\n#: mocodo/mcd.py:126\nmsgid \"Inheritance \\\"{inheritance}\\\" linked to an unknown entity \\\"{entity}\\\"!\"\nmsgstr \"L'héritage « {inheritance} » est lié à une entité inconnue « {entity} ».\"\n\n#: mocodo/mcd.py:135\nmsgid \"Constraint \\\"{constraint}\\\" linked to an unknown entity or association \\\"{box}\\\"!\"\nmsgstr \"Une contrainte « {constraint} » est liée à une entité ou association inconnue « {box} ».\"\n\n#: mocodo/mcd.py:142\nmsgid \"Constraint \\\"{constraint}\\\" aligned with an unknown entity or association \\\"{box}\\\"!\"\nmsgstr \"Une contrainte « {constraint} » est alignée avec une entité ou association inconnue « {box} ».\"\n\n#: mocodo/mcd.py:175\nmsgid \"The weak entity \\\"{entity}\\\" should have a discriminator.\"\nmsgstr \"L'entité faible « {entity} » devrait avoir un discriminateur.\"\n\n#: mocodo/mcd.py:399\nmsgid \"Unable to reuse the geometry file \\\"{filename}\\\".\"\nmsgstr \"Impossible de réutiliser le fichier de géométrie « {filename} ».\"\n\n#: mocodo/mcd.py:438\nmsgid \"Unable to save geometry file \\\"{filename}\\\".\"\nmsgstr \"Impossible de sauvegarder le fichier de géométrie « {filename} ».\"\n\n#: mocodo/mcd_to_svg.py:10\nmsgid \"PNG and PDF generation requires cairosvg to be installed\"\nmsgstr \"Générer un PNG ou un PDF requiert une installation fonctionnelle de CairoSVG.\"\n\n#: mocodo/mocodo_error.py:25\nmsgid \"Invalid sub-argument: \\\"{subsubopt}={subsubarg}\\\".\"\nmsgstr \"Sous-argument invalide : « {subsubopt}={subsubarg} ».\"\n\n#: mocodo/mocodo_error.py:28\nmsgid \"Invalid sub-sub-option: \\\"{subsubopt}\\\".\"\nmsgstr \"Sous-sous-option invalide : « {subsubopt} ».\"\n\n#: mocodo/mocodo_error.py:31\nmsgid \"Unknown \\\"{opt}\\\" sub-option: \\\"{subopt}\\\".\"\nmsgstr \"Sous-option « {opt} » inconnue : « {subopt} ».\"\n\n#: mocodo/rewrite/_drown.py:24\nmsgid \"ENTITY\"\nmsgstr \"ENTITÉ\"\n\n#: mocodo/rewrite/_drown.py:25\nmsgid \"ASSOC\"\nmsgstr \"ASSOC\"\n\n#: mocodo/rewrite/_drown.py:27 mocodo/rewrite/_grow.py:91\nmsgid \"attr\"\nmsgstr \"at\"\n\n#: mocodo/rewrite/_drown.py:28\nmsgid \"role\"\nmsgstr \"rôle\"\n\n#: mocodo/rewrite/_grow.py:88\nmsgid \"Binary\"\nmsgstr \"Binaire\"\n\n#: mocodo/rewrite/_grow.py:88\nmsgid \"Quaternary\"\nmsgstr \"Quaternaire\"\n\n#: mocodo/rewrite/_grow.py:88\nmsgid \"Reflexive\"\nmsgstr \"Réflexive\"\n\n#: mocodo/rewrite/_grow.py:88\nmsgid \"Ternary\"\nmsgstr \"Ternaire\"\n\n#: mocodo/rewrite/_grow.py:89\nmsgid \"Entity\"\nmsgstr \"Entité\"\n\n#: mocodo/rewrite/_grow.py:90\nmsgid \"Weak Entity\"\nmsgstr \"Entité faible\"\n\n#: mocodo/rewrite/_grow.py:92\nmsgid \"id\"\nmsgstr \"id\"\n\n#: mocodo/rewrite/_grow.py:124\nmsgid \"Cannot find a suitable combination of card schemes and arities.\"\nmsgstr \"Impossible de trouver une combinaison adéquate de schémas de cardinalités et d'arités.\"\n\n#: mocodo/rewrite/arrange_bb.py:111\nmsgid \"Layout calculation time exceeded.\"\nmsgstr \"Temps de calcul du plongement dépassé.\"\n\n#: mocodo/rewrite/arrange_bb.py:234\nmsgid \"Failed to calculate a non-constrained planar layout.\"\nmsgstr \"Impossible de calculer un plongement planaire.\"\n\n#: mocodo/rewrite/arrange_bb.py:236\nmsgid \"Failed to calculate a planar layout satisfying the given constraint.\"\nmsgstr \"Impossible de calculer un plongement planaire satisfaisant la contrainte donnée.\"\n\n#: mocodo/rewrite/obfuscate.py:54\nmsgid \"Obfuscation failed. Not enough substitution words in \\\"{filename}\\\".\"\nmsgstr \"L'obfuscation a échoué. Pas assez de mots de substitution dans « {filename} ».\"\n\n#: mocodo/rewrite/op_tk.py:71\nmsgid \"Operation \\\"{op_name}\\\" cannot be applied to \\\"{pre_token}\\\".\"\nmsgstr \"L'opération « {op_name} » ne peut pas être appliquée à « {pre_token} ».\"\n\n#: mocodo/tools/parser_tools.py:11\nmsgid \"Parsing error:\\n{e}\\n\"\nmsgstr \"Erreur d'analyse syntaxique :\\n{e}\\n\"\n\n#: mocodo/tools/parser_tools.py:22 mocodo/tools/parser_tools.py:24\nmsgid \"{pin}\\\"{v}\\\" is not a valid line beginning.\"\nmsgstr \"{pin}« {v} » n'est pas un début de ligne valide.\"\n\n#: mocodo/tools/parser_tools.py:26\nmsgid \"{pin}Malformed box name.\"\nmsgstr \"{pin}Nom de boîte mal formé.\"\n\n#: mocodo/tools/parser_tools.py:28\nmsgid \"{pin}A valid box name starting a line must be followed by a colon or a comma.\"\nmsgstr \"{pin}Un nom de boîte valide en début de ligne doit être suivi d'un deux-points ou d'une virgule.\"\n\n#: mocodo/tools/parser_tools.py:30\nmsgid \"{pin}Illegal comma after inheritance.\"\nmsgstr \"{pin}Virgule illégale après un héritage.\"\n\n#: mocodo/tools/parser_tools.py:32 mocodo/tools/parser_tools.py:34\n#: mocodo/tools/parser_tools.py:36\nmsgid \"{pin}Malformed cardinalities.\"\nmsgstr \"{pin}Cardinalités mal formées.\"\n\n#: mocodo/tools/parser_tools.py:38\nmsgid \"{pin}An inheritance name must be \\\"\\\", \\\"X\\\", \\\"T\\\" or \\\"XT\\\".\"\nmsgstr \"{pin}Un nom d'héritage doit être «  », « X », « T » ou « XT ».\"\n\n#: mocodo/tools/parser_tools.py:40\nmsgid \"{pin}Only two coords are allowed.\"\nmsgstr \"{pin}Seulement deux coordonnées sont autorisées.\"\n\n#: mocodo/tools/parser_tools.py:42\nmsgid \"{pin}An association leg cannot be empty.\"\nmsgstr \"{pin}Une patte d'association ne peut pas être vide.\"\n\n#: mocodo/tools/parser_tools.py:44\nmsgid \"{pin}Expected a number or a box name.\"\nmsgstr \"{pin}Un nombre ou un nom de boîte est attendu.\"\n\n#: mocodo/tools/parser_tools.py:46\nmsgid \"{pin}Only a box name is possible here.\"\nmsgstr \"{pin}Seul un nom de boîte est possible ici.\"\n\n#: mocodo/tools/parser_tools.py:48\nmsgid \"{pin}Unclosed square bracket.\"\nmsgstr \"{pin}Crochet fermant manquant.\"\n\n#: mocodo/tools/parser_tools.py:52\nmsgid \"{pin}A constraint name cannot contain more than three characters.\"\nmsgstr \"{pin}Un nom de contrainte ne peut contenir plus de trois caractères.\"\n\n#: mocodo/tools/parser_tools.py:54\nmsgid \"{pin}Expected a box name or a constraint leg.\"\nmsgstr \"{pin}Un nom de boîte ou une patte de contrainte est attendu.\"\n\n#: mocodo/tools/parser_tools.py:56\nmsgid \"{pin}Illegal character after a constraint name.\"\nmsgstr \"{pin}Caractère illégal après un nom de contrainte.\"\n\n#: mocodo/tools/parser_tools.py:58\nmsgid \"{pin}A parent name must be followed by an inheritance arrow among \\\"<=\\\", \\\"<-\\\", \\\"->\\\", \\\"=>\\\".\"\nmsgstr \"{pin}Un nom de parent doit être suivi d'une flèche d'héritage parmi « <= », « <- », « -> », « => ».\"\n\n#: mocodo/tools/parser_tools.py:60\nmsgid \"{pin}Please change the old foreign key syntax (\\\"->\\\") by the new one (\\\">\\\").\"\nmsgstr \"{pin}Veuillez changer l'ancienne syntaxe de clé étrangère (« -> ») par la nouvelle (« > »).\"\n\n#: mocodo/tools/parser_tools.py:62\nmsgid \"{pin}The constraint targets must be comma-separated.\"\nmsgstr \"{pin}Les cibles de la contrainte doivent être séparées par des virgules.\"\n\n#: mocodo/tools/parser_tools.py:64 mocodo/tools/parser_tools.py:66\nmsgid \"{pin}An attribute label cannot start with \\\"{v[1]!r}\\\".\"\nmsgstr \"{pin}Un nom d'attribut ne peut pas commencer par « {v[1]!r} ».\"\n\n#: mocodo/tools/parser_tools.py:68\nmsgid \"{pin}An attribute label cannot contain \\\"{v}\\\".\"\nmsgstr \"{pin}Un nom d'attribut ne peut pas contenir « {v} ».\"\n\n#: mocodo/tools/parser_tools.py:70 mocodo/tools/parser_tools.py:72\nmsgid \"{pin}An attribute starting with \\\"#\\\" must contain two \\\">\\\".\"\nmsgstr \"{pin}Vous semblez essayer de spécifier une clé étrangère. Au niveau du MCD (modèle conceptuel de données), ce sont les associations qui répondent à ce besoin. Les clés étrangères n'apparaîtront qu'après passage au relationnel, dans le MLD (modèle logique de données). À ce niveau, elles devront suivre la syntaxe : « #clé étrangère > table d'origine > clé primaire ».\"\n\n#: mocodo/tools/parser_tools.py:74\nmsgid \"{pin}Expected an entity name.\"\nmsgstr \"{pin}Un nom d'entité est attendu.\"\n\n#: mocodo/tools/parser_tools.py:76\nmsgid \"{pin}A box name cannot contain \\\"{v}\\\".\"\nmsgstr \"{pin}Un nom de boîte ne peut pas contenir « {v} ».\"\n\n#: mocodo/tools/parser_tools.py:78\nmsgid \"{pin}Expected a comma.\"\nmsgstr \"{pin}Une virgule est attendue.\"\n\n#: mocodo/tools/parser_tools.py:80\nmsgid \"{pin}Malformed number.\"\nmsgstr \"{pin}Nombre mal formé.\"\n\n#: mocodo/tools/parser_tools.py:82\nmsgid \"{pin}More than two coordinates.\"\nmsgstr \"{pin}Plus de deux coordonnées.\"\n\n#: mocodo/tools/parser_tools.py:84\nmsgid \"{pin}An attribute label cannot have more than one optionality marker.\"\nmsgstr \"{pin}Un nom d'attribut ne peut pas avoir plus d'un marqueur d'optionalité.\"\n\n#: mocodo/tools/parser_tools.py:85\nmsgid \"{pin}Token \\\"{t}\\\" encountered. Expected tokens: {expected}.\"\nmsgstr \"{pin}Token « {t} » rencontré. Tokens attendus : {expected}.\"\n"
  },
  {
    "path": "mocodo/resources/lorem/disparition.txt",
    "content": "aaaaaaah\nabaissa\nabandon\nabandonna\nabandonnai\nabandonnait\nabandonnant\nabandonnas\nabandons\nabasourdi\nabasourdir\nabasourdis\nabasourdissants\nabat\nabattait\nabattant\nabattis\nabattit\nabattoir\nabattra\nabattrait\nabattu\nabattus\nabbou\nabdallah\nabdication\nabdou\nabdul\nabhorrait\nabhorration\nabjuration\nabjurons\nablation\nablution\nablutions\naboli\nabolir\nabolira\nabolirait\nabolis\nabolissait\nabolissant\nabolit\nabolition\nabomination\nabominations\nabonda\nabondant\nabondants\nabord\naborda\nabordai\nabordait\nabordant\nabords\nabouchant\nabout\nabouti\naboutir\naboutirai\naboutirait\naboutissait\naboutissants\naboutit\naboya\nabraca\nabracadabrant\nabraham\nabrasif\nabrasion\nabri\nabricot\nabritai\nabritait\nabrupt\nabruti\nabrutira\nabrutissant\nabrutit\nabscission\nabscons\nabsolu\nabsolution\nabsolvant\nabsorba\nabsorbait\nabsorbant\nabstint\nabsurdo\nabus\nabusait\nabymant\nabyssal\nabyssin\nabyssum\nabyssus\nabâtardirai\nabîma\nabîmant\nacabit\nacacia\nacacias\nacajou\nacapulco\naccabla\naccablait\naccablant\naccablants\naccalmit\nacclama\nacclamation\nacclimata\nacclimatation\naccola\naccommodait\naccompagna\naccompagnait\naccompagnant\naccompli\naccomplir\naccomplira\naccomplirai\naccomplis\naccomplissait\naccomplissant\naccomplit\naccord\naccordait\naccordant\naccords\naccort\naccosta\naccostant\naccoucha\naccouchait\naccouda\naccoudant\naccount\naccoupla\naccourais\naccourait\naccourir\naccourons\naccourrai\naccourrait\naccours\naccourt\naccouru\naccourus\naccourut\naccourût\naccroc\naccrochait\naccrochant\naccrocs\naccroupi\naccroupir\naccroupis\naccroupissant\naccroupit\naccu\naccumulait\naccumulation\naccusa\naccusait\naccusant\naccusatif\naccusation\nachab\nacharna\nacharnai\nacharnait\nacharnant\nachat\naconit\nacoquina\nacqua\nacquis\nacquisition\nacquit\nacquitta\nacromion\nactif\naction\nactions\nactivation\nactor\nactualisation\nadagio\nadam\nadamantin\nadaptait\nadaptation\naddition\nadduction\nadjoint\nadjoints\nadjudant\nadjuvants\nadministra\nadministrait\nadministratif\nadministration\nadmira\nadmirai\nadmirais\nadmirait\nadmirant\nadmiration\nadmis\nadmission\nadmit\nadmonition\nadolf\nadonaï\nadonis\nadonisant\nadonna\nadopta\nadoptait\nadoptif\nadoption\nadorait\nadorant\nadouba\nadoubla\nadoucir\nadoucira\nadoucirait\nadoucissait\nadoucissant\nadoucit\nadrar\nadrian\nadrianus\nadroit\nadulait\nadvint\naffabulation\naffaibli\naffaiblir\naffaiblissait\naffaiblit\naffaira\naffairai\naffairait\naffairant\naffaissa\naffaissait\naffaissant\naffala\naffalant\naffamant\naffichant\naffichât\naffinait\naffirma\naffirmait\naffirmant\naffirmatif\naffirmation\naffirmât\naffliction\nafflua\nafflux\naffola\naffolait\naffolant\naffolants\naffolons\naffranchi\naffranchir\naffranchis\naffranchissant\naffront\naffrontait\naffrontant\naffronts\naffublait\naffublant\naffût\naffûta\naficionado\nafin\nafraid\nafricain\nafricains\nafro\nagadir\nagain\nagami\nagaçait\nagaçant\nagaçants\nagglutina\nagglutinatif\naggrava\naggravant\nagil\nagincourt\nagir\nagira\nagirai\nagirait\nagissais\nagissait\nagissant\nagit\nagita\nagitait\nagitant\nagitation\nagonir\nagonisa\nagonisai\nagonisait\nagonisant\nagostino\nagouti\nagrafait\nagrandi\nagrandir\nagrandira\nagricolas\nagrippai\nagrippait\nagrippant\nagrippants\nahan\nahanait\nahanant\nahiyohu\nahmad\nahuri\nahurir\nahuris\nahurissant\nahurissants\nahurit\naida\naidant\naiglon\naignan\naigri\naigrir\naigu\naiguail\naiguilla\naiguillon\naiguillons\naiguisas\naiguisoir\naigus\nailippopolis\naillant\naima\naimais\naimait\naimant\naimions\naimons\nainsi\nairain\nairlington\nairostat\nairs\najaccio\najourant\najours\najout\najouta\najoutai\najoutait\najoutant\najoutons\najouts\najustant\nakvavit\nalain\nalambic\nalangui\nalanguir\nalanguis\nalanguissait\nalanguissant\nalanguit\nalaric\nalarma\nalarmait\nalarmant\nalarmants\nalas\nalaska\nalbanais\nalbatros\nalbi\nalbin\nalbinia\nalbinoni\nalbinos\nalbion\nalbugo\nalbum\nalcala\nalcalin\nalcool\nalfa\nalhambra\nalias\nalibi\nalibis\nalignant\nalita\nalitait\nalla\nallah\nallai\nallais\nallait\nallant\nallas\nallia\nalliant\nalligator\nallions\nallobarbital\nallons\nalloua\nalluma\nallumai\nallumait\nallumoir\nallusion\nallusions\nalluvion\nalluvions\nallât\nallô\nalma\nalmanach\nalmanachs\nalors\nalourdissait\naloyau\naloysius\nalpha\nalpins\nalto\naltra\naluminium\nalunir\namadou\namadouant\namaigrit\namanda\namant\namants\namaryllis\namas\namassa\namassait\namassant\namati\namaury\nambiant\nambigu\nambigus\nambition\nambulant\namical\namicaux\namici\namidon\naminci\namincis\namincissant\namiral\namis\nammoniac\namoindri\namoindrir\namoindrissait\namoindrit\namolli\namollir\namollissant\namontillado\namortissait\namorçoir\namour\namouracha\namours\namphigouri\namphitryon\namplifiait\namplification\namputation\namusait\namusant\namusants\nanalogaux\nanalysa\nanalysait\nanalysant\nanalysons\nananas\nanar\nanars\nanas\nanastasia\nanchilops\nanchois\nandiamo\nandilly\nanglais\nanglicans\nanglicisation\nanglisch\nanglo\nangoissa\nangoissait\nangoissant\nangoissants\nangora\nangström\nanimait\nanimal\nanimaux\nanimula\nanis\nanjou\nankara\nankarais\nanna\nannonça\nannonçait\nannonçant\nannonçât\nannotations\nannulant\nannulation\nanobli\nanoblir\nanoblit\nanodin\nanormal\nanormaux\nanschauung\nanschluss\nantan\nanthrax\nanti\nanticatarrhal\nanticipation\nanticipons\nanticlimax\nantico\nantidictatoriaux\nantinous\nanton\nantony\nantrim\nanudissant\nanything\nanônumos\naoût\napaisa\napaisait\napaisant\napitoya\napitoyant\naplani\naplanir\naplanira\naplaniront\naplatir\naplatis\naplatissait\naplatissant\naplatit\naplomb\napocalypsis\napollon\napostat\napostolorum\napostropha\napostrophait\napparaissait\napparaissant\napparat\napparaux\napparaît\napparaîtra\napparaîtrai\napparaîtrait\nappariait\nappariant\napparition\nappartint\napparut\nappauvris\napplaudi\napplaudir\napplaudirais\napplaudis\napplaudissais\napplaudit\napplication\nappliqua\nappliquait\nappliquant\napport\napporta\napportai\napportait\napportant\napportas\napports\napposai\napposition\nappris\napprit\napprivoisa\napprobation\napprocha\napprochai\napprochait\napprochant\napprochons\napprofondi\napprofondir\napprofondirons\napprofondissait\napprofondissant\napprouva\napprovisionnait\napproximatif\napproximatifs\napproximation\nappui\nappuya\nappuyait\nappuyant\nappât\naquarium\naquila\naquilin\naquilon\naquilons\narabisant\narabisants\narago\naragon\naramis\narbin\narcan\narchaïsant\narchi\narchibattit\narchibattu\narchiduc\narchifaux\narchimort\narchiviaux\narcimboldo\narcs\nardu\nardus\nargon\nargoud\nargousin\nargousins\nargua\nargus\naria\nariana\narias\narius\narlington\narma\narmagnac\narmait\narmand\narmons\narmorial\narmstrong\narnaud\narouan\narousal\narracha\narrachait\narrachant\narrachons\narras\narriva\narrivai\narrivais\narrivait\narrivant\narrivions\narrogant\narroi\narrondi\narrondir\narrondissant\narrosa\narrosant\narsonval\nartagnan\narthur\nartichauts\narticulait\narticulant\narticulation\narticulations\nartisan\nartison\narums\nascot\nasimodo\naska\nasphyxia\nasphyxiait\nasphyxiant\nasphyxiation\naspic\naspidistras\naspira\naspirai\naspirant\naspirants\naspirons\nassagir\nassaillait\nassaillant\nassailli\nassaillir\nassaillira\nassaillit\nassainir\nassainirait\nassassin\nassassina\nassassinai\nassassinait\nassassinat\nassassinats\nassassins\nassaut\nassauts\nassimilait\nassimilant\nassimilation\nassis\nassista\nassistai\nassistais\nassistait\nassistanat\nassistant\nassistants\nassistas\nassit\nassocia\nassociait\nassociation\nassociations\nassombri\nassombrir\nassombrissait\nassombrissant\nassombrit\nassomma\nassommait\nassommoir\nassorti\nassortir\nassortis\nassortissant\nassortit\nassoupi\nassoupir\nassoupirais\nassoupissait\nassoupit\nassourdir\nassourdis\nassourdissant\nassouvi\nassouvir\nassouvira\nassouviras\nassouvissait\nassouvit\nassura\nassurait\nassurant\nassurbanipal\nastaroth\nastic\nastral\natarax\nataturk\natchoum\nathos\natlas\natoll\natonal\natrium\natropos\nattabla\nattablant\nattacha\nattachait\nattachant\nattachât\nattaqua\nattaquai\nattaquait\nattaquant\nattardait\nattifant\nattifiaux\nattila\nattira\nattirail\nattirait\nattirant\nattisoir\nattraction\nattractions\nattrait\nattrapa\nattrapait\nattribua\nattribuait\nattribut\nattribution\nattrista\nattristait\nattristant\nattrition\naubigny\naubour\naubusson\nauctor\naucun\naucuns\naudit\nauditif\nauditifs\naudition\naudruicq\naugsbourg\naugurait\naugural\naugurants\naugustin\naugustus\naujourd\naulnay\nauparavant\naupick\naura\naurai\naurais\naurait\nauras\nauric\naurillac\naurions\nauroch\naurochs\naurons\nauront\naurora\nauschwitz\nausculta\nauscultation\naussi\naussitôt\naustro\nautan\nautant\nauto\nautobiographiait\nautobus\nautocar\nautochtons\nautocollant\nautocongratulait\nautojustifia\nautojustifiait\nautomancipation\nautomatisation\nautomnal\nautonomat\nautonourrissant\nautoportrait\nautopropulsant\nautopsia\nautorisa\nautorisait\nautorisant\nautorisation\nautos\nautotrucida\nautour\nautrui\navachi\navachirait\navachirons\navachis\navachissait\navachit\navais\navait\navala\navalait\navalant\navancions\navant\navança\navançai\navançait\navançant\navaro\navaros\navatar\navatars\naviation\navignon\navilir\navilis\navilissait\navilissant\navilissants\navillons\navion\navions\naviron\navis\navisa\navisaga\navisai\navisait\navisant\navision\navivants\navocal\navocat\navocats\navogadro\navoir\navoisinait\navons\navorton\navortons\navoua\navouait\navouant\navouas\navril\naxial\naxiomatisation\naxolotls\nayant\nayants\nayons\nazimuth\nazimuths\nazincourt\naziz\nazor\nazoukh\nazur\naïachi\naïda\nbaba\nbabiroussa\nbabouin\nbaccara\nbach\nbachot\nback\nbacon\nbacs\nbadaud\nbadauds\nbadin\nbadoit\nbaffrait\nbafouait\nbafouilla\nbafouillant\nbafouillis\nbahia\nbahut\nbaignait\nbaignant\nbail\nbain\nbaisa\nbaisant\nbaisotant\nbakchich\nbaladins\nbalafrait\nbalai\nbalalaïka\nbalam\nbalandras\nbalança\nbalançait\nbalançant\nbalbutia\nbalbutiait\nbalbutiant\nbalcon\nbalcons\nbaldaccini\nbaldaquin\nbalibar\nbalkan\nbalkanais\nbalkans\nballon\nballons\nballot\nbalourd\nbalthazar\nbalzac\nbalzar\nbambin\nbambinard\nbambins\nbambochait\nbambou\nbanal\nbanals\nbanania\nbanat\nbanc\nbancal\nbanco\nband\nbandit\nbandits\nbang\nbanjo\nbanjos\nbank\nbanni\nbannir\nbannirait\nbannissant\nbantou\nbaobab\nbaobabs\nbaour\nbaptismaux\nbaragouin\nbarakalla\nbaralipton\nbarbara\nbarbarisation\nbarbatif\nbarbillons\nbarbon\nbarbotait\nbarbu\nbarclay\nbardait\nbarguigna\nbaril\nbarka\nbarlach\nbarmaid\nbarman\nbarnabooth\nbaron\nbarra\nbarrait\nbarrant\nbarri\nbarricadait\nbars\nbaruch\nbaryton\nbascula\nbasculais\nbasculait\nbasculant\nbasin\nbassin\nbassins\nbastia\nbastiannais\nbastion\nbataillon\nbataillons\nbath\nbatifolait\nbatifolant\nbattait\nbattant\nbattants\nbattit\nbattrons\nbattu\nbattus\nbaudoin\nbaudruchon\nbavait\nbavard\nbavarda\nbavotant\nbazooka\nbhuj\nbiafra\nbiais\nbianca\nbianco\nbibs\nbichon\nbifur\nbigot\nbijou\nbijoux\nbilan\nbildungsroman\nbillard\nbillards\nbillot\nbiniou\nbiplan\nbiribi\nbiscornu\nbiscornus\nbismarck\nbison\nbisous\nbissac\nbissant\nbistouri\nbistrot\nbistrots\nbitch\nbivouaquait\nblack\nblafard\nblalard\nblanc\nblanca\nblanchi\nblanchir\nblanchirait\nblanchis\nblanchissait\nblanchissant\nblanchissants\nblanchit\nblanchot\nblancs\nblandula\nblason\nblasonnait\nblasons\nbloc\nbloch\nblock\nblockhaus\nblond\nblondi\nblondin\nbloody\nbloquant\nblotti\nblottir\nblottis\nblouson\nblousons\nblutoir\nbobinard\nbobo\nbocal\nbock\nbohm\nbohu\nbois\nboisson\nboissons\nboit\nbombant\nbombançait\nbombarda\nbombinait\nbona\nbonbon\nbonbons\nbond\nbondi\nbondir\nbondis\nbondissait\nbondissant\nbondit\nbonifacio\nbonjour\nbonnir\nbons\nbook\nbootk\nbooz\nbord\nbordj\nbords\nborg\nborgia\nborgias\nborkou\nborn\nborniol\nborniols\nbororo\nbosco\nboss\nbossu\nboston\nbotillons\nbottin\nbottins\nboubou\nbouc\nboucan\nboucla\nbouclât\nbouda\nbouddha\nboudin\nboudins\nboudiou\nboudoir\nbouffant\nbouffi\nbouffon\nbouffons\nbougnat\nbougnats\nbougon\nboui\nbouillait\nbouillant\nbouilli\nbouillir\nbouillon\nbouillonnant\nbouillons\nboukha\nboul\nboulingrins\nboulon\nboulons\nboulot\nboulottait\nboult\nbouquin\nbouquins\nbour\nbourbaki\nbourbon\nbourdalous\nbourdon\nbourdonnait\nbourdonnant\nbourdons\nbourg\nbourgois\nbourgs\nbourguiba\nbourguignon\nbourlinguant\nbourricot\nbourru\nbousculant\nbousillant\nbousins\nbout\nboutant\nboutants\nbouton\nboutons\nboutz\nbouvillon\nboxon\nboyard\nboyau\nboyaux\nbrabançon\nbrabham\nbrahma\nbrahms\nbrailla\nbraillait\nbrain\nbrama\nbrancha\nbrandi\nbrandir\nbrandissait\nbrandissant\nbrandissons\nbrandit\nbrando\nbrandon\nbrandons\nbranlait\nbranlant\nbranlants\nbranly\nbras\nbrassard\nbrassicourt\nbravant\nbravissimo\nbravo\nbravos\nbrazza\nbricola\nbricolait\nbricolant\nbrigand\nbrigands\nbrigantin\nbrillait\nbrillant\nbrillat\nbrimbala\nbrimborion\nbrimborions\nbrin\nbrindisi\nbrins\nbrio\nbris\nbrisa\nbrisant\nbrisants\nbristol\nbritannial\nbroc\nbroca\nbrocard\nbrocards\nbroda\nbrodait\nbroquarts\nbrou\nbrouhaha\nbrouillait\nbrouillamini\nbrouillard\nbrouillards\nbrouillon\nbrouillons\nbrout\nbroutait\nbroyait\nbroyant\nbrrr\nbruit\nbruits\nbrulât\nbrulôt\nbrun\nbrunissoir\nbrut\nbrutal\nbruyant\nbruyants\nbrûla\nbrûlait\nbrûlant\nbrûlants\nbrûlis\nbrûlot\nbubons\nbubula\nbuccin\nbucco\nbuck\nbugatti\nbuilding\nbuis\nbuisson\nbuissonnant\nbuissons\nbull\nbungalow\nbunny\nburgraviat\nburin\nburnous\nburton\nbustos\nbuta\nbutait\nbutin\nbutoir\nbutor\nbuts\nbuvait\nbuvant\nbuvons\nbyron\nbâillant\nbâillon\nbâtard\nbâtards\nbâti\nbâtir\nbâtissant\nbâtit\nbâton\nbâtons\nböhm\ncabas\ncabin\ncabochon\ncabotait\ncaboulot\ncaboulots\ncabri\ncaca\ncacha\ncachait\ncachalot\ncachalots\ncachant\ncaciquant\ncadastral\ncadran\ncadratin\ncaduc\ncafard\ncafards\ncagibi\ncagna\ncagoulard\ncaha\ncahin\ncaillot\ncaillou\ncailloutis\ncailloux\ncaius\ncalcinant\ncalcul\ncalcula\ncalculs\ncaldarium\ncalfats\ncalicots\ncalifourchon\ncaligula\ncalissons\ncalmar\ncalmi\ncalmir\ncalmons\ncalot\ncalquait\ncalus\ncalvados\ncalypso\ncamail\ncamard\ncambrai\ncamion\ncamp\ncampa\ncampagnard\ncampagnol\ncampagnols\ncamping\ncanada\ncanal\ncanalisait\ncanalisation\ncanard\ncanards\ncanasson\ncanaux\ncandis\ncanif\ncanin\ncanon\ncanons\ncanot\ncanots\ncanta\ncantal\ncantaral\ncanticorum\ncanticum\ncanton\ncantons\ncantorum\ncanulard\ncanyon\ncaoutchouc\ncaparaçon\ncapharnaüm\ncapisco\ncapit\ncapital\ncapitalisation\ncapitaux\ncapitons\ncapitula\ncaporal\ncapot\ncapouan\ncapricants\ncaps\ncaptif\ncaptivant\ncaptura\ncapuccino\ncapuchons\ncapucin\ncarabins\ncaracas\ncaraco\ncarafon\ncarat\ncarats\ncaravaning\ncaravanings\ncarburant\ncarcan\ncarcopino\ncardan\ncardin\ncardinal\ncardinaux\ncardium\ncardons\ncargos\ncari\ncaribou\ncarignano\ncarillon\ncarissima\ncarl\ncarlin\ncarmin\ncarmins\ncarnation\ncarnavals\ncaroli\ncaroling\ncarolus\ncarpillon\ncarquois\ncarri\ncarta\ncarton\ncartons\ncaruso\ncary\ncasablanca\ncasanova\ncasbah\ncasimir\ncasino\ncasoar\ncass\ncassa\ncassagnac\ncassant\ncassatas\ncassis\ncasting\ncastor\ncastorp\ncastration\ncasus\ncatamaran\ncatarina\ncatarrhait\ncatarrhal\ncatastropha\ncatgut\ncatimini\ncatogans\ncattaro\ncaulaincourt\ncausa\ncausait\ncausant\ncausons\ncaviar\ncavour\ncaïds\ncaïman\ncaïn\nchacal\nchacun\nchafaudant\nchafouins\nchagrin\nchagrina\nchagrinait\nchagrins\nchahut\nchair\nchairman\nchairs\nchaland\nchalazions\nchalgrin\nchaman\nchamans\nchambarda\nchamboulait\nchamois\nchamp\nchampi\nchampignon\nchampignons\nchampion\nchampionnat\nchampollion\nchamps\nchandail\nchanson\nchansons\nchant\nchanta\nchantait\nchantant\nchantillon\nchantilly\nchants\nchantât\nchançard\nchaos\nchaouch\nchap\nchaqu\nchar\ncharabia\ncharançon\ncharbon\ncharbons\nchardons\nchariff\nchariot\ncharivari\ncharlatan\ncharlot\ncharmant\ncharmants\ncharnu\ncharognard\ncharognards\ncharria\ncharrons\nchas\nchassa\nchassait\nchassant\nchat\nchatham\nchaton\nchatouillis\nchatoyant\nchats\nchauchat\nchaud\nchaudron\nchauds\nchaulin\nchaussons\nchauvin\nchaux\nchaînon\nchaînons\nchaïr\nchiala\nchiapas\nchiasma\nchibouk\nchic\nchicago\nchichi\nchichis\nchico\nchiffon\nchiffonnants\nchiffons\nchiffrait\nchilam\nchild\nchinatown\nchinois\nchinook\nchiogga\nchipolata\nchivas\nchloroformant\nchloroformisation\nchoc\nchocolat\nchocolats\nchocs\nchoir\nchoisi\nchoisir\nchoisis\nchoisissait\nchoisissant\nchoisit\nchoit\nchoix\nchomsky\nchoral\nchosification\nchotts\nchou\nchouchou\nchoux\nchrist\nchristian\nchromos\nchrono\nchronos\nchuchota\nchuchotant\nchuchotis\nchuinta\nchuintant\nchuintis\nchurchill\nchut\nchutait\nchutant\nchâlit\nchâssis\nchâtain\nchômait\nciao\ncicatrisation\ncigarillo\ncigarillos\ncingla\ncinglait\ncinglant\ncinglons\ncinq\ncircinal\ncirconlocutions\ncirconstancia\ncirconvallation\ncirconvolution\ncircuit\ncirculait\ncirculant\ncircumnavigation\ncirro\ncitadin\ncitait\ncitant\ncitation\ncitron\ncity\ncivil\ncivilisation\ncivium\nclac\nclafoutis\nclair\nclairon\nclaironna\nclaironnant\nclairvoyant\nclam\nclama\nclamait\nclan\nclapotis\nclaqua\nclaquant\nclark\nclassant\nclawdia\nclic\nclifford\nclignancourt\nclimat\nclimats\nclin\nclochard\nclochards\nclodion\ncloison\nclopant\nclopin\nclos\ncloua\nclouait\nclouant\nclous\nclown\nclowns\ncloîtrai\ncloîtrait\nclub\ncnrs\ncoach\ncoachs\ncoagulait\ncoagulant\ncoalitif\ncobalt\ncochin\ncochon\ncocktail\ncocktails\ncoco\ncocopinar\ncocos\ncoda\ncodifia\ncodifiant\ncogito\ncogna\ncoin\ncoins\ncolback\ncolcotar\ncoligram\ncolimaçon\ncolin\ncolis\ncolla\ncollaborait\ncollaboration\ncollait\ncollant\ncollapsus\ncollation\ncollations\ncollimation\ncollision\ncollodion\ncollusion\ncolombin\ncolonial\ncolonisation\ncolorado\ncolossal\ncolportait\ncols\ncolumbarium\ncolumbia\ncoma\ncombat\ncombattant\ncombattu\ncombinaison\ncombinaisons\ncombinant\ncomblant\ncombustion\ncommanda\ncommandait\ncommandant\ncommando\ncommandos\ncommis\ncommissariat\ncommissariats\ncommission\ncommotion\ncommun\ncommunal\ncommunicants\ncommunication\ncommunications\ncommunion\ncommunions\ncommuns\ncommutation\ncomodoro\ncompact\ncompagnon\ncompagnons\ncompara\ncomparait\ncompas\ncompassion\ncompatir\ncompatissant\ncompatissons\ncompilant\ncompilation\ncompilations\ncomplaisant\ncomplication\ncomplications\ncomplot\ncomplotait\ncomplots\ncomponction\ncomportait\ncomportant\ncomposa\ncomposition\ncomprimant\ncompris\ncomprit\ncompromis\ncompromission\ncompromit\ncompta\ncomptabilisant\ncomptabilisation\ncomptait\ncomptant\ncomptoir\ncomput\ncomtat\nconakry\nconciliant\nconcis\nconclu\nconcluait\nconcluant\nconclusion\nconclut\nconcoction\nconcordants\nconcourir\nconcourront\nconcours\nconcourt\nconcouru\nconcussion\ncondamna\ncondamnait\ncondamnant\ncondamnation\ncondition\ncondor\nconduira\nconduiras\nconduirons\nconduisait\nconduisant\nconduisit\nconduisît\nconduit\nconduits\nconfia\nconfiait\nconfiant\nconfiguration\nconfin\nconfins\nconfirma\nconfirmant\nconfirmation\nconfit\nconfits\nconflagra\nconflagrant\nconflagration\nconflit\nconflits\nconfluant\nconfond\nconfondant\nconfondants\nconfondu\nconfondus\nconfort\nconfrontation\nconfus\nconfusion\nconginatal\nconglobation\nconglutinatif\nconjoint\nconjoints\nconjonction\nconjugal\nconjungo\nconjungos\nconnais\nconnaissait\nconnaissant\nconnaissons\nconnard\nconnaît\nconnaîtra\nconnaîtrais\nconnaîtras\nconnaîtrons\nconnaîtront\nconnu\nconnus\nconnut\nconquis\nconsacra\nconsanguin\nconsanguins\nconscrit\nconscrits\nconsigna\nconsignation\nconsistait\nconsistorial\nconsola\nconsolant\nconsolation\nconsomma\nconsommation\nconsomption\nconson\nconsortium\nconspirait\nconspiration\nconspuant\nconstant\nconstantin\nconstants\nconstata\nconstatant\nconstatation\nconstats\nconstitua\nconstituait\nconstituant\nconstituants\nconstitution\nconstriction\nconstrictor\nconstruction\nconstruisant\nconstruisit\nconstruit\nconsul\nconsulat\nconsulats\nconsulta\nconsultai\nconsultait\nconsultant\nconsultation\ncontact\ncontacta\ncontactant\ncontacts\ncontant\nconti\ncontigu\ncontinants\ncontinu\ncontinua\ncontinuait\ncontinuant\ncontinuation\ncontinuum\ncontondant\ncontour\ncontournant\ncontours\ncontradiction\ncontradictions\ncontraignait\ncontraignant\ncontraint\ncontraria\ncontrariant\ncontrariis\ncontrario\ncontrat\ncontribuait\ncontribution\ncontristant\ncontrit\ncontrition\ncontrôla\ncontrôlait\ncontrôlant\ncontumax\nconvaincant\nconvaincu\nconvainquit\nconviction\nconvint\nconvocation\nconvoi\nconvois\nconvol\nconvola\nconvoqua\nconvulsif\nconvulsions\nconçoit\nconçu\nconçut\ncoordonnons\ncopains\ncopur\ncoqs\ncoquin\ncorail\ncoran\ncorbillard\ncorbillards\ncorbin\ncorday\ncordial\ncordon\ncordons\ncorfou\ncorindon\ncormorans\ncorna\ncornac\ncornalin\ncorniaud\ncornichons\ncorona\ncoronat\ncorporation\ncorps\ncorpus\ncorridor\ncorrobora\ncorrompu\ncorrompus\ncorruption\ncors\ncortical\ncortico\ncoruscants\ncoruscation\ncoryza\ncosa\ncosmic\ncosmos\ncosy\ncotation\ncotillon\ncoton\ncotonnant\ncotons\ncotât\ncouac\ncouard\ncouards\ncoucha\ncouchant\ncouci\ncoucou\ncouguars\ncouillon\ncoula\ncoulait\ncoulant\ncoulis\ncouloir\ncount\ncountry\ncoup\ncoupa\ncoups\ncour\ncourait\ncourant\ncourir\ncourlis\ncournot\ncourons\ncourroux\ncours\ncourt\ncourtaud\ncourtauld\ncourtois\ncouru\ncourus\ncourut\ncouscous\ncousin\ncousins\ncousit\ncoussin\ncoussins\ncoustil\ncoustou\ncousu\ncouvait\ncouvant\ncouvrait\ncouvrit\ncouça\ncoïncidant\ncoït\ncracha\ncrachant\ncrachin\ncrachotant\ncrack\ncrado\ncraignait\ncraignant\ncraignit\ncraignons\ncraignît\ncraint\ncraintif\ncramant\ncramoisi\ncramoisis\ncrampon\ncramponnant\ncrapaud\ncrapaudin\ncrapauds\ncrapouillot\ncraquait\ncrawford\ncrayon\ncrayonnant\ncrazy\ncria\ncriaillant\ncriait\ncriant\ncriard\ncriblait\ncriblant\ncric\ncrin\ncrinolins\ncris\ncrispait\ncrispant\ncrissant\ncristal\ncristallin\ncritiquait\ncritiquant\ncrocs\ncrocus\ncroirait\ncroirons\ncroiront\ncrois\ncroisa\ncroisait\ncroisillon\ncroisillons\ncroissant\ncroit\ncroix\ncroquant\ncroquants\ncroquis\ncross\ncrossland\ncroulant\ncroup\ncroupion\ncroupir\ncroupissait\ncroupissant\ncroupit\ncroustillant\ncroustillants\ncroyais\ncroyait\ncroyant\ncroyons\ncroît\ncroûton\ncrubovin\ncruchon\ncrucial\ncrucifia\ncrucifiait\ncrucifix\ncrut\ncrypto\ncubain\ncuir\ncuisait\ncuisant\ncuisants\ncuisinait\ncuisit\ncuissard\ncuisson\ncuit\nculbutait\nculminant\nculmination\nculpabilisant\nculs\ncumin\ncumulus\ncunha\ncupidon\ncurait\ncurantur\ncurarisant\ncuratif\ncuraçao\ncurling\ncurnonsky\ncurricula\ncurriculum\ncustomary\ncyclospiral\ncycloïdal\ncygnal\ncyprin\ncyprins\ncyrano\ncyrards\ncâbla\ncâlin\ncâlinou\ncôtissant\ncôtoyait\ndabrant\ndactylo\ndactylos\ndada\ndadais\ndadas\ndaggoo\ndahu\ndaily\ndaim\ndaims\ndamasquin\ndamasquins\ndamnant\ndamnation\ndamni\ndams\ndancing\ndancings\ndanican\ndanois\ndans\ndansa\ndansait\ndanton\ndanzig\ndarby\ndard\ndardait\ndardant\ndards\ndarmon\ndarwinial\ndarwisch\ndassault\ndatait\ndatant\ndaunou\ndauphin\ndauphinat\ndauphinois\ndauphins\ndauzat\ndavidoff\ndavis\ndavos\ndayan\ndays\ndiagnostic\ndiamant\ndiamants\ndiamond\ndiavolo\ndick\ndicta\ndictait\ndictatorial\ndiction\ndicton\ndictons\ndidon\ndidot\ndiffus\ndiffusait\ndiffusant\ndiffusion\ndilapidation\ndilatation\ndiminua\ndiminutif\ndinard\ndindon\ndingo\ndiongor\ndior\ndira\ndirait\ndirimant\ndirons\ndiront\ndisait\ndisant\ndiscontinu\ndiscordant\ndiscourait\ndiscourir\ndiscours\ndiscouru\ndiscriminant\ndiscrimination\ndiscussion\ndiscutant\ndisions\ndisjoint\ndisloquât\ndisons\ndisparaissait\ndisparaissant\ndisparaît\ndisparaîtrons\ndisparition\ndisparu\ndisparus\ndisparut\ndisposa\ndisposait\ndisposant\ndisposas\ndispositif\ndispositifs\ndisposition\ndisposât\ndisproportion\ndisputant\ndissimula\ndissimulait\ndissimulant\ndissipant\ndissocia\ndissolus\ndissoluto\ndissous\ndistant\ndistillait\ndistinct\ndistinctif\ndistinction\ndistincts\ndistingua\ndistinguait\ndistinguo\ndistraction\ndistrait\ndistribution\ndiurnal\ndiva\ndivagant\ndivagation\ndivaguait\ndivaguant\ndivan\ndivans\ndivin\ndivinisant\ndivins\ndivisa\ndivision\ndivisions\ndivulgation\ndivulguait\ndiwan\ndixit\ndjouf\ndjougachvili\ndocks\ndoctorat\ndoctrinal\ndodo\ndodonial\ndodu\ndoigt\ndoigts\ndois\ndoit\ndoktor\ndollar\ndollars\ndolly\ndomaicq\ndomanial\ndominait\ndomination\ndominion\ndominus\ndonald\ndonation\ndonc\ndonjon\ndonjons\ndonna\ndonnait\ndonnant\ndonnons\ndonnât\ndont\ndori\ndorian\ndoris\ndorlotant\ndormait\ndormant\ndormi\ndormir\ndormit\ndormitif\ndort\ndortoir\ndosant\ndossard\ndotait\ndouait\ndouaumont\ndoubla\ndoublon\ndoublons\ndoubrovnik\ndoucin\ndougga\ndough\ndouglas\ndourdan\ndouta\ndoutait\ndoux\ndown\ndracon\ndragon\ndragons\ndragua\ndramma\ndrancy\ndrap\ndraps\ndrogman\ndroit\ndroits\ndrossant\ndrouot\ndrumont\ndubitatif\ndubitation\ndubitations\ndublin\nducal\nducaton\nducats\ndudit\ndugland\ndugong\ndugongs\ndulcifiant\ndumping\ndumpty\ndunhill\ndupin\nduplicata\nduplication\ndura\ndurait\ndurandal\ndurant\ndurazzo\ndurci\ndurcissant\ndurcit\nduring\nduroc\ndutronc\ndvorak\ndynamo\ndîna\ndînait\ndînons\nfabius\nfabliau\nfabrication\nfabriqua\nfabriquait\nfacs\nfaction\nfacto\nfactotum\nfactotums\nfactum\nfacultatif\nfada\nfagots\nfaiblard\nfaibli\nfaiblir\nfaiblissant\nfaiblit\nfailli\nfaillir\nfaillis\nfaillit\nfaim\nfair\nfairfax\nfais\nfaisait\nfaisant\nfaisions\nfaisons\nfait\nfaits\nfaix\nfakir\nfalbalas\nfallacial\nfallait\nfalloir\nfallu\nfallut\nfalot\nfalzar\nfamilial\nfaminard\nfaminards\nfamulus\nfanal\nfanas\nfanatisait\nfanaux\nfanfaron\nfangio\nfanion\nfans\nfantassin\nfantassins\nfantômas\nfaon\nfaraud\nfarci\nfarcir\nfarcis\nfarfouilla\nfarfouillant\nfarouk\nfascina\nfascinait\nfascinant\nfascinants\nfascination\nfatal\nfatalitas\nfathom\nfatigant\nfatigua\nfatras\nfatum\nfaubourg\nfaubourgs\nfauchard\nfaucillon\nfaucon\nfaudra\nfaudrait\nfaufilant\nfaustillon\nfaustina\nfaustus\nfaut\nfautif\nfautifs\nfaux\nfavori\nfavoris\nfavorisât\nfaçon\nfaçonna\nfaçonnait\nfaçons\nfiasco\nfiat\nficha\nfichu\nfiction\nfidji\nfifty\nfigaro\nfigl\nfignola\nfignolant\nfigon\nfigurait\nfigurant\nfiguration\nfiguris\nfila\nfilait\nfilant\nfilial\nfiliation\nfiliations\nfilin\nfill\nfilm\nfilms\nfilon\nfilou\nfils\nfinal\nfinaud\nfini\nfinir\nfinira\nfinirait\nfiniras\nfinis\nfinissait\nfinissant\nfinissons\nfinit\nfinitif\nfinlandais\nfins\nfisch\nfissah\nfission\nfissurant\nfiston\nfixa\nfixait\nfixant\nfixatif\nfixation\nfjord\nflacon\nflacons\nflagrant\nflair\nflairant\nflamand\nflamba\nflambait\nflamboyait\nflamboyant\nflanc\nflancs\nflanqua\nflanquait\nflanquant\nflançois\nflash\nflask\nflatta\nflattait\nflic\nflics\nflinguait\nflip\nflips\nflocons\nfloctuation\nfloraux\nflorin\nflorissant\nflot\nflots\nflotta\nflottait\nflottant\nflou\nflour\nfluctuation\nfluvial\nflux\nfluxion\nfluxionnait\nflânant\nfoccard\nfoch\nfoin\nfois\nfoison\nfolds\nfolichonnait\nfolio\nfolios\nfolk\nfolklorain\nfolkoch\nfolâtrait\nfonction\nfonctionna\nfonctionnait\nfond\nfonda\nfondait\nfondant\nfondants\nfondation\nfondations\nfondouk\nfondra\nfondrait\nfonds\nfondu\nfondus\nfont\nfonts\nfonça\nfonçait\nfonçant\nfootball\nforain\nforains\nforban\nforclot\nford\nforfait\nforfaits\nforhuir\nforma\nformat\nformation\nformol\nformulant\nformulation\nforpaysant\nfort\nfortifiait\nfortifiant\nfortification\nfortin\nfortissimo\nforts\nfortuit\nfortunatos\nforça\nfouaillant\nfouchtra\nfoudroyant\nfoui\nfouilla\nfouillait\nfouillant\nfoulard\nfouloir\nfoundation\nfour\nfourbi\nfourbis\nfourbu\nfourbus\nfourgonnas\nfourgons\nfourguait\nfourni\nfournil\nfournir\nfournirait\nfourniront\nfournissait\nfournit\nfourra\nfourrant\nfourvoyant\nfous\nfoutons\nfoutrait\nfoutu\nfoutus\nfrac\nfracas\nfracassa\nfracassant\nfractions\nfractura\nfragrant\nfrais\nfraisil\nfranc\nfrancfort\nfranchi\nfranchir\nfranchirait\nfranchis\nfranchissant\nfranchit\nfranciscain\nfranciscains\nfrancisco\nfrancs\nfrangin\nfrangination\nfrangins\nfranglais\nfrank\nfranz\nfrançais\nfrançois\nfrappa\nfrappait\nfrappant\nfraîchir\nfraîchira\nfriand\nfriands\nfricatif\nfricot\nfricsay\nfriction\nfrigo\nfrigorifiant\nfrimas\nfringant\nfripon\nfrisait\nfrisson\nfrissonna\nfrissonnait\nfrissonnant\nfrissons\nfrit\nfroid\nfroidi\nfroids\nfroissa\nfrom\nfrondaison\nfrondaisons\nfront\nfrontal\nfronton\nfronts\nfronça\nfronçant\nfrottait\nfrottis\nfroufroutait\nfroufroutants\nfructifiant\nfructification\nfrugal\nfruit\nfruits\nfrusquin\nfrustrait\nfrustration\nfrôla\nfrôlait\nfrôlant\nfugitif\nfugitifs\nfuir\nfuis\nfuit\nfulgurant\nfulguration\nfull\nfulmicoton\nfulmina\nfulminant\nfulminants\nfulmination\nfuma\nfumait\nfumant\nfumants\nfumigation\nfumoir\nfumons\nfungus\nfuribard\nfuribond\nfurin\nfurlongs\nfurtif\nfury\nfusa\nfusait\nfusant\nfusil\nfusils\nfutur\nfuturs\nfuyais\nfuyait\nfuyant\nfuyants\nfuyard\nfuyons\ngabarit\ngabo\ngabonais\ngadin\ngadsby\ngaffiot\ngafilt\ngaga\ngagna\ngagnai\ngagnait\ngagnant\ngagnants\ngagnons\ngaillard\ngain\ngainait\ngala\ngalant\ngalgala\ngalimatias\ngalion\ngallimard\ngallons\ngalonnait\ngalons\ngalop\ngalopait\ngalopin\ngalopins\ngaluchat\ngalvanisa\ngalvanisant\ngambadant\ngamin\ngamins\ngamma\ngammon\nganaith\ngandin\ngandourah\ngang\nganglion\ngant\ngants\ngara\ngaramond\ngaranti\ngarantir\ngarantira\ngarantirait\ngarantirons\ngarantissait\ngarantissant\ngarantit\ngard\ngardai\ngardais\ngardait\ngardant\ngargan\ngargantua\ngargouillis\ngarni\ngarnis\ngarnison\ngarros\ngarrot\ngars\ngarçon\ngarçons\ngaston\ngatchi\ngaulant\ngaulois\ngavial\ngavoty\ngayac\ngazait\ngazon\ngazons\ngazouillis\ngaînait\ngeorges\nghost\nghôlan\ngibbons\ngibus\ngicla\ngifla\ngigli\ngigot\ngigotait\ngimond\ngina\ngiocoso\ngiovanni\ngirardin\ngirardon\ngiraudoux\ngirl\ngiron\ngisait\ngisant\ngiscard\ngitan\nglacial\nglaciaux\nglacis\nglanait\ngland\nglapi\nglapir\nglapissait\nglapissant\nglapit\nglas\nglass\nglaça\nglaçait\nglaçons\nglissa\nglissait\nglissant\nglobal\ngloria\nglorifiant\nglossanthrax\ngloussa\ngloutir\nglouton\ngloutonnant\nglow\ngluant\nglupf\ngnaptor\ngnard\ngnards\ngobbi\ngodard\ngodillot\ngodrons\ngogaillait\ngogni\ngolgotha\ngolgothas\ngoliath\ngombrich\ngombrowicz\ngonfalon\ngonfanon\ngonflait\ngonflant\ngong\ngonisait\ngood\ngordon\ngorgonzola\ngoriot\ngossipy\ngotha\ngottschalk\ngoudron\ngoujat\ngoulot\ngoulots\ngoum\ngoupillon\ngoura\ngourbi\ngourd\ngourdin\ngourds\ngourmand\ngourou\ngouzis\ngovinda\ngoût\ngoûta\ngoûtait\ngoûtons\ngoûts\ngrabat\ngracchus\ngradin\ngradins\ngraduation\ngradus\ngraf\ngraffiti\ngraffitial\ngrain\ngrains\ngraissait\ngram\ngrammatical\ngrammaticaux\ngranada\ngrand\ngrandi\ngrandissait\ngrandissant\ngrandit\ngrands\ngranit\ngrant\ngranulait\ngrapillon\ngratification\ngratin\ngratis\ngrattant\ngrattoir\ngratuit\ngravait\ngravant\ngravat\ngravats\ngravillon\ngravir\ngravissant\ngray\ngribaldi\ngribouillis\ngrido\ngriffonnant\ngriffus\ngrignotait\ngrilla\ngrimant\ngrimaud\ngrimaça\ngrimaçait\ngrimaçant\ngrimpa\ngrimpait\ngrimpant\ngrinling\ngrinçait\ngrippa\ngris\ngrisi\ngrisonnant\ngrisou\ngrivois\ngrog\ngroggy\ngrogna\ngrognant\ngrognon\ngroin\ngronda\ngrondant\ngroom\ngrooms\ngros\ngrossi\ngrossir\ngrossissant\ngrosso\ngroucho\ngrouillant\ngroup\ngroupait\ngroupant\nguadalajara\nguaira\nguida\nguido\nguidon\nguignon\nguillain\nguillotin\nguillotina\nguimbard\nguindant\nguingois\nguirlands\ngunfight\ngunman\ngymnasium\ngyroscopal\ngyrus\ngîta\nhabana\nhabanas\nhabilla\nhabillait\nhabillant\nhabillas\nhabillons\nhabillât\nhabit\nhabita\nhabitais\nhabitait\nhabitant\nhabitants\nhabitation\nhabits\nhabitua\nhabsbourg\nhachant\nhachoir\nhadzushi\nhagard\nhagards\nhaggada\nhaidarabad\nhaig\nhaillon\nhainaut\nhainisch\nhajdu\nhalifax\nhall\nhallali\nhallucinant\nhallucination\nhallucinations\nhalo\nhalvah\nhamac\nhamada\nhambourg\nhamid\nhamilton\nhammam\nhanap\nhanaps\nhandicap\nhangar\nhangars\nhanouka\nhanoï\nhans\nhantait\nhantant\nhappa\nhara\nharakiri\nharangua\nharanguant\nharas\nharassant\nharassants\nhardi\nhardit\nhardouin\nhari\nharicots\nharmonicas\nharmonisait\nharnois\nharo\nharpin\nharpo\nharpon\nharpons\nharry\nhartmann\nharwich\nhasard\nhasarda\nhasardant\nhaschana\nhaschich\nhassan\nhaus\nhaussait\nhaut\nhautain\nhautbois\nhauts\nhawaii\nhaydn\nhayworth\nhaïkaï\nhaïr\nhaïssait\nhaïssant\nhibou\nhidalgo\nhilarion\nhimalaya\nhippy\nhirudination\nhispano\nhissa\nhissant\nhistoria\nhistrion\nhistrions\nhittorf\nhodja\nhoffmann\nhoggar\nhold\nholidays\nholland\nhollandais\nhollywood\nholà\nhomard\nhomatropini\nhomicidal\nhomini\nhomo\nhomunculus\nhongrois\nhonni\nhonnissait\nhonnissant\nhonolulu\nhonora\nhonorait\nhonorant\nhonorio\nhonoris\nhoratio\nhorion\nhorizon\nhorizontal\nhorizontaux\nhormis\nhorn\nhorrifiait\nhorrifiant\nhorrifiants\nhorripilant\nhors\nhosanna\nhospodar\nhospodars\nhourdis\nhouri\nhourvari\nhouspillant\nhoyau\nhrivnas\nhugo\nhuilait\nhuis\nhuissait\nhuit\nhull\nhumain\nhumains\nhumant\nhumidifiant\nhumour\nhumpty\nhumus\nhuntingdon\nhurla\nhurlai\nhurlait\nhurlant\nhuron\nhurons\nhurrah\nhussard\nhussards\nhutin\nhydro\nhydrobromidum\nhydrocution\nhypnotisant\nhypocras\nhypocrisif\nhâtif\nhôpital\nhôpitaux\nibant\nibnadir\nibrahim\nicoglan\nicoglans\nidiosunkrasis\nidiot\nidiots\nidolâtrait\niftikhar\nigli\nignition\nignora\nignorais\nignorait\nignorant\nignorions\nignorons\nignorât\niguidi\nilitch\nillico\nillumina\nilluminant\nillumination\nillusion\nillusions\nillustra\nillustrations\nimagina\nimaginai\nimaginait\nimaginant\nimaginatif\nimagination\nimaginations\nimago\niman\nimbibait\nimbitation\nimbrication\nimbriquant\nimbroglio\nimbu\nimita\nimitait\nimitant\nimitation\nimmaculant\nimmaculation\nimmatriculation\nimmatriculations\nimmisçait\nimmisçant\nimmobilisa\nimmobilisait\nimmola\nimmoral\nimmoraux\nimmortalisa\nimmortalisait\nimmortalisant\nimmortalisation\nimmuno\nimpact\nimpair\nimpairs\nimparfait\nimparfaits\nimparti\nimpartial\nimpartir\nimplanta\nimplantait\nimplantant\nimpliquait\nimpliquant\nimplora\nimplorant\nimplorants\nimploration\nimplorations\nimplosion\nimpoli\nimportait\nimportant\nimportants\nimportation\nimportations\nimportun\nimposa\nimposait\nimposant\nimposât\nimprima\nimprimait\nimprobus\nimproductif\nimproductifs\nimpromptu\nimprouva\nimprovisa\nimprovisait\nimprovisant\nimpuissant\nimpulsion\nimpulsions\nimpur\nimpurs\ninadaptation\ninamical\ninanimait\ninanition\ninaugura\ninaugurai\ninaugurait\ninaugural\ninaugurant\ninauguration\ninca\nincapsulant\nincarnant\nincarnat\nincarnation\ninch\nincirconcis\nincisant\nincisif\nincisifs\nincision\nincitait\nincitation\nincivils\ninclama\ninclina\ninclinai\ninclinait\ninclinant\ninclusion\nincognito\nincommodait\nincommunicatif\ninconfort\nincongru\nincongrus\ninconnu\ninconnus\ninconsistant\ninconsistants\ninconstant\nincorporait\nincorporant\nincrusta\nincrustais\nincrustait\nincrustant\nincrustation\nincrustations\nincubation\ninculpa\ninculqua\ninculquât\nincurvait\nincurvant\nindian\nindiavolato\nindic\nindicatif\nindication\nindications\nindics\nindigna\nindignait\nindignants\nindignation\nindigo\nindiqua\nindiquait\nindiquant\nindisposa\nindistinct\nindistinction\nindividu\nindividus\nindivis\nindivision\nindivulgation\nindous\ninduction\ninduisit\nindustrialisation\ninfailli\ninfamant\ninfamants\ninfant\ninfanticidal\ninfantil\ninfantin\ninfants\ninfarcti\ninfarctus\ninfiltrations\ninfini\ninfinis\ninfirma\ninflammation\ninflux\ninforma\ninformait\ninformant\ninformation\ninformations\ninfortun\ninfraction\ninfranchi\ninfrastructural\ninfusant\ninfusion\ningrat\ningrid\ninguinal\ningurgita\ningurgitation\ninhabillant\ninhala\ninhibant\ninhuma\ninhumain\ninhumait\ninhumation\ninhumons\ninitia\ninitial\ninitiatif\ninitiation\ninitiaux\ninitiât\ninjonction\ninjuria\ninjuriants\ninjustifiait\ninnovant\ninnovation\ninnsbruck\ninoculation\ninondant\ninopinant\ninopportun\ninopportuns\ninoriginal\ninoubli\ninouï\ninouïs\ninput\ninquisition\ninquisitions\ninquisitorial\ninsatisfaction\ninsatisfaisant\ninsatisfait\ninscription\ninscriptions\ninscrit\ninscrits\ninscrivait\ninscrivant\ninscrivit\ninsignifiant\ninsignifiants\ninsinuai\ninsinuant\ninsinuants\ninsinuation\ninsista\ninsistai\ninsistait\ninsistant\ninsolant\ninsolation\ninsouciant\ninsoumission\ninspirait\ninspirant\ninspiration\ninstalla\ninstallait\ninstallant\ninstallation\ninstallons\ninstant\ninstants\ninstar\ninstaura\ninstaurait\ninstauration\ninstigation\ninstilla\ninstinct\ninstinctif\ninstinctifs\ninstincts\ninstituant\ninstitut\ninstomation\ninstructif\ninstruction\ninstructions\ninstruit\ninsu\ninsubordination\ninsuffisant\ninsuffisants\ninsultant\ninsultants\ninsupport\ninsus\nintact\nintima\nintimidant\nintimidation\nintitulant\nintoxication\nintrados\nintransitif\nintrigant\nintrigants\nintrigua\nintriguait\nintriguant\nintroductif\nintroduction\nintroduisait\nintroduisant\nintroduisis\nintroduisit\nintroduisons\nintroduit\nintroïbo\nintrus\nintuitif\nintuition\ninunguis\ninvaincu\ninvasion\ninvita\ninvitai\ninvitait\ninvitant\ninvitasti\ninvitation\ninvocat\ninvocation\ninvocations\ninvolutif\ninvolutifs\ninvoquait\nions\nipso\nirai\nirais\nirait\niran\niranian\niridium\nirions\niris\nirisait\nirisant\nirisations\nirlandais\niron\nironisa\nironisait\nirons\niront\niroquois\nirradiait\nirradiant\nirraouaddi\nirriguons\nirrita\nirritait\nirritant\nirritants\nirritation\nirroration\nirruption\nirwin\nisard\nisards\nischion\nisidro\nislam\nislandais\nismaïl\nisola\nisolais\nisolait\nisolant\nisolibration\nisonzo\nispahan\nissoudun\nissu\nissus\nistanboul\nitaly\nithos\nitou\niturbi\niulius\nivan\nivoirin\nixil\nizumi\njabot\njack\njacob\njadis\njaguar\njailli\njaillir\njaillira\njaillissait\njaillissant\njaillit\njakobson\njalon\njalons\njalousait\njaloux\njamais\njamaïcain\njambart\njambon\njapon\njaponais\njardin\njardins\njargon\njarjack\njarnacais\njarnicoton\njasmin\njason\njauni\njava\njawol\njazz\njoan\njobard\njohn\njohnson\njoignait\njoignant\njoignit\njoignons\njoigny\njoint\njointif\njoli\njolis\njonas\njonchant\njonction\njosiah\njoua\njouait\njouant\njoufflu\njoug\njouir\njouissant\njouissants\njouissif\njoujoux\njouons\njour\njournal\njournaux\njours\njouxtait\njouxtant\njouât\njovial\njoyau\njoyaux\njuan\njuba\njubilation\njudas\njudaïsant\njudith\njudo\njugurtha\njuif\njuifs\njuin\njulliard\njulot\njunior\njunot\njupin\njupon\njura\njurait\njurant\njuridiction\njuro\njuron\njurons\njury\njusant\njusqu\njust\njustaucorps\njustifia\njustifiait\njustifiant\njustification\njustifiât\njustin\njuxtaposition\nkaakil\nkadams\nkafka\nkakari\nkakis\nkaku\nkalmouk\nkalpasoutra\nkamtchatka\nkana\nkangourou\nkant\nkaolin\nkapok\nkarajan\nkaramazov\nkari\nkarl\nkasbah\nkatoun\nkatun\nkawa\nkhamsin\nkhan\nkidnappa\nkidnapping\nkill\nkilo\nkilog\nkilogs\nkilos\nkimono\nking\nkippour\nkiri\nkirk\nkirsch\nklan\nklux\nknock\nknout\nknow\nkobold\nkorsakov\nkotor\nkouglof\nkoûppodoutourams\nkrabs\nkrach\nkraft\nkrat\nkrips\nkronprinz\nkudan\nkulturkampf\nkunimoto\nkuraki\nkurus\nlabial\nlabor\nlabour\nlabourant\nlabrador\nlabyrinthal\nlacan\nlacandon\nlacanial\nlacrymal\nlacunal\nlads\nlady\nlagonda\nlaid\nlaids\nlaissa\nlaissait\nlaissant\nlaissons\nlait\nlaiton\nlamantin\nlamantins\nlambris\nlaminoir\nlampant\nlampion\nlamplight\nlancinant\nlandaux\nlanguido\nlanguir\nlanguissait\nlanguissant\nlanguissants\nlanguit\nlanzmann\nlança\nlançai\nlançait\nlançant\nlanças\nlapida\nlapidait\nlapidification\nlapin\nlapins\nlapis\nlappa\nlaps\nlapsus\nlaquais\nlaranda\nlarbaud\nlarbin\nlarcin\nlarcins\nlard\nlardait\nlargactyl\nlarigot\nlarmoyait\nlarmoyant\nlarvati\nlarynx\nlascar\nlascars\nlascif\nlassait\nlasso\nlatakia\nlatin\nlatinum\nlatirostris\nlatour\nlaudanum\nlava\nlavabo\nlavait\nlavis\nlayon\nlazuli\nlazzi\nlazzis\nlham\nlhomond\nliaison\nliait\nlibation\nlibations\nlibidinal\nlibitum\nlibrary\nlicol\nlicou\nlilas\nlilial\nlimaçon\nlimina\nlimitait\nlimitatif\nlimitation\nlimon\nlimonial\nlimons\nlimours\nlinda\nling\nlingots\nlinon\nlins\nlion\nlions\nlipp\nlippman\nlippmann\nlippu\nliquidation\nlirons\nlisait\nlisant\nlisons\nlits\nlittoral\nlivarot\nliving\nlivius\nlivorno\nlivra\nlivraison\nlivrait\nlivrant\nlivry\nllord\nlloyd\nlocal\nlocarno\nlocation\nlocaux\nloch\nloco\nlocus\nlocutions\nloggia\nloggias\nlogis\nlogogriphiant\nlogos\nloin\nlointain\nlointains\nloir\nloisif\nloisir\nlolita\nlollobrigida\nlombric\nlombrics\nlondon\nlong\nlongai\nlongchamp\nlongs\nloop\nlord\nlorgnon\nlorgnons\nlormian\nlors\nlorsqu\nloti\nlotir\nlotis\nlotus\nloua\nlouai\nlouait\nlouant\nloucha\nlouchant\nlouis\nloukhoum\nloup\nloups\nlourant\nlourd\nlourdaud\nlourdauds\nlourds\nloustic\nlouvain\nlouvoyant\nlovait\nlowry\nloyal\nloyaux\nlucchino\nluciano\nlucky\nluisant\nlulling\nlumbago\nlumignon\nlumignons\nlunaisons\nlunch\nlundi\nlupanar\nlupin\nlupus\nluron\nlustral\nluth\nlutin\nlutrin\nluttait\nluxation\nlyndon\nlynx\nlyon\nlyrical\nlâchant\nmacaroni\nmach\nmachin\nmachinal\nmachination\nmachinations\nmackintosh\nmacquart\nmacula\nmacy\nmadras\nmadrid\nmadrigal\nmadrigaux\nmaffia\nmafflu\nmagasin\nmagasins\nmagistral\nmagistrat\nmagistrats\nmagistraux\nmagma\nmagnani\nmagnat\nmagni\nmagnifiait\nmagnificat\nmagnus\nmagot\nmaharadjah\nmaharadjahs\nmahdi\nmahmoud\nmahon\nmaigri\nmaigrichon\nmaigrichonnant\nmaigrichons\nmaigrir\nmaigrissait\nmaigrit\nmail\nmaillard\nmaillon\nmaillons\nmaillot\nmaillotin\nmaillots\nmain\nmains\nmaint\nmaints\nmais\nmaison\nmaisons\nmajor\nmajorat\nmaladif\nmaladroit\nmalandrin\nmalandrins\nmalaria\nmalaxa\nmalcolm\nmaldiction\nmalfaisant\nmalfaisants\nmalin\nmallarmus\nmalo\nmalsain\nmalstrom\nmamamouchi\nmaman\nmamans\nmammouth\nmanant\nmanatus\nmanchon\nmanchot\nmanchots\nmandarin\nmandat\nmandatant\nmandou\nmandrin\nmanhattan\nmaniait\nmaniant\nmanipula\nmanitou\nmann\nmanoir\nmanoirs\nmanqua\nmanquait\nmanquant\nmanquants\nmansard\nmantic\nmanu\nmanuscrit\nmanuscrits\nmaquignon\nmaquignons\nmaquilla\nmaquis\nmarabout\nmarais\nmarasquin\nmarat\nmaraudait\nmarc\nmarcassin\nmarcassins\nmarcha\nmarchai\nmarchait\nmarchal\nmarchand\nmarchands\nmarchant\nmarchions\nmarchons\nmarcillac\nmardi\nmargina\nmarginal\nmarginalia\nmari\nmarigot\nmarigots\nmarin\nmarina\nmarino\nmarins\nmarivaudant\nmarlo\nmarmara\nmarmiton\nmarmonna\nmarmonnait\nmarmorial\nmarmot\nmarocain\nmarocains\nmaroni\nmaroquin\nmarquait\nmarquant\nmarquis\nmarquisats\nmarri\nmarron\nmars\nmarshall\nmarsouins\nmarsyas\nmartial\nmartiaux\nmartin\nmarx\nmary\nmascaron\nmascarons\nmasculin\nmasqua\nmasquait\nmasquant\nmassa\nmassacra\nmassacrât\nmassif\nmassifs\nmastabas\nmastic\nmastiff\nmastiquait\nmastoc\nmasulipatam\nmata\nmatch\nmathias\nmaths\nmathurin\nmatifou\nmatignon\nmatin\nmatinal\nmatins\nmatis\nmatois\nmatraquant\nmatriarcal\nmatrification\nmaubourg\nmaudis\nmaudissant\nmaudit\nmaudits\nmaupassant\nmauriac\nmaurocordata\nmauss\nmauvais\nmaux\nmavrocordato\nmavrokhordatos\nmaxima\nmaximin\nmaximum\nmaximus\nmaya\nmayo\nmazout\nmazurka\nmaçon\nmaçons\nmaîtrisant\nmaïs\nmccormick\nmcdonald\nmcluhan\nmiam\nmiaulait\nmich\nmichard\nmichi\nmichigan\nmicro\nmicron\nmicrosillon\nmicrovision\nmidas\nmidi\nmignardant\nmignon\nmignons\nmigrain\nmigrations\nmijotait\nmijotant\nmijotions\nmikado\nmilady\nmilan\nmilita\nmilitant\nmilitari\nmilliard\nmilliards\nmillion\nmilord\nmilords\nmimait\nmimant\nmini\nminimal\nminimum\nminium\nminois\nminuit\nminus\nmiraculant\nmirliton\nmirobolant\nmiroir\nmiroirs\nmirror\nmiss\nmission\nmistral\nmitan\nmitard\nmithridatisation\nmitraillait\nmitron\nmitrons\nmitrovitsa\nmitzvah\nmiyura\nmoab\nmobilisa\nmobilisation\nmoby\nmoccolo\nmodifiant\nmodification\nmodillons\nmodo\nmodulait\nmodulant\nmodus\nmogol\nmohican\nmoignon\nmoins\nmois\nmoisi\nmoisir\nmoisson\nmoka\nmoku\nmokulu\nmolasson\nmollir\nmollo\nmonacal\nmondain\nmondial\nmondiaux\nmonica\nmonobloc\nmonopolisait\nmonotonous\nmons\nmont\nmonta\nmontait\nmontant\nmontanus\nmontra\nmontrait\nmontrant\nmontrât\nmonts\nmontsouris\nmoonlight\nmops\nmoraillon\nmoral\nmoralisation\nmorand\nmordant\nmordaunt\nmordicus\nmordiou\nmordorait\nmordra\nmordu\nmorfil\nmorfond\nmorfondait\nmorfondu\nmoribond\nmoribonds\nmoritz\nmorland\nmorpion\nmort\nmorti\nmortifiant\nmortification\nmortis\nmorts\nmoss\nmotard\nmotif\nmotifs\nmotiva\nmotivai\nmoto\nmots\nmotu\nmotus\nmoucha\nmoucharab\nmouchard\nmouchoir\nmouchoirs\nmouilla\nmouillait\nmouillant\nmoula\nmoulait\nmoulin\nmoulins\nmoult\nmoulu\nmountain\nmourait\nmourant\nmourir\nmouron\nmourra\nmourrir\nmourrons\nmourut\nmoussaillon\nmousson\nmoussu\nmoustachu\nmouton\nmoutons\nmouvant\nmozart\nmuch\nmucus\nmugir\nmugis\nmugissait\nmugit\nmuids\nmulligan\nmulon\nmulot\nmulots\nmulti\nmultipliait\nmultipliant\nmultiplication\nmundi\nmuni\nmunich\nmunichois\nmunicipal\nmunicipaux\nmural\nmurant\nmurky\nmurmura\nmurmurait\nmurmurant\nmurmuras\nmurs\nmuscadin\nmuscas\nmusic\nmusical\nmusigny\nmussipontins\nmussolini\nmust\nmustang\nmustapha\nmusulman\nmutandis\nmutant\nmutation\nmutatis\nmutilait\nmutilant\nmutilation\nmyocardiaux\nmyosotis\nmâchicoulis\nmâchonnant\nmâchu\nmâcon\nmâts\nmûri\nmûrir\nmûrit\nmûrs\nnabab\nnabot\nnacarat\nnadir\nnagasaki\nnagis\nnagra\nnahum\nnain\nnains\nnaissain\nnaissait\nnaissant\nnaka\nnana\nnanan\nnancy\nnantir\nnantis\nnantuckais\nnapalm\nnappa\nnaquis\nnaquit\nnard\nnarguant\nnarihira\nnarquois\nnarra\nnarrait\nnarrant\nnarratif\nnarration\nnarvals\nnasillards\nnaso\nnatal\nnatif\nnation\nnational\nnato\nnatura\nnavaja\nnavigua\nnaviguant\nnavrait\nnavrant\nnaxos\nnazi\nnazin\nnaît\nnaîtrait\nnaîtront\nnaïf\nniais\nniait\nniant\nnichan\nnichant\nnicias\nnicolas\nnictation\nnictitant\nnidoral\nnids\nnigaud\nnight\nnimbait\nnimbo\nnimbostratus\nnimium\nninas\nninipotch\nniolo\nnippon\nnirvâna\nnivial\nnoam\nnobody\nnocif\nnocifs\nnocta\nnocturnal\nnocturnis\nnodal\nnodus\nnoguchi\nnoir\nnoirci\nnoircir\nnoircis\nnoircissait\nnoircissant\nnoircit\nnoirs\nnois\nnoix\nnomadisant\nnombril\nnominatif\nnomination\nnomma\nnommait\nnommant\nnommons\nnoms\nnonchalant\nnonchalants\nnonnain\nnonobstant\nnoor\nnord\nnords\nnorfolk\nnorint\nnormal\nnormand\nnormatif\nnorodom\nnoroît\nnostalgical\nnostra\nnota\nnotait\nnotarial\nnotariaux\nnotations\nnothing\nnotions\nnouant\nnougats\nnounou\nnounous\nnourri\nnourrir\nnourris\nnourrissait\nnourrissant\nnourrisson\nnourrit\nnous\nnovak\nnoya\nnoyait\nnoyau\nnoyauta\nnoyaux\nnoyon\nnoyons\nnuit\nnuits\nnunc\nnuptial\nnutri\nnutritif\nnutrition\nnylon\noakham\noakwood\noaristys\noasis\noaxaca\nobjurgua\nobjurguant\nobligation\nobligations\noblong\noblongs\nobnubila\nobnubilant\nobradovitch\nobscur\nobscurci\nobscurcir\nobscurcissait\nobscurcissant\nobscurcit\nobscuri\nobscurs\nobstina\nobstinait\nobstinant\nobstination\nobstruction\nobtins\nobtint\nobtus\nobus\nocarina\noccasion\noccipital\nocciput\noccis\nocclusion\noccultait\noccultations\noccupa\noccupait\noccupant\noccupas\noccupation\noccupations\noccupons\noctant\noctavo\noctavos\noctogonal\noctroi\noctroyait\noctuor\nodilon\nodorant\nodorants\nodorat\nofficiait\noffrait\noffrant\noffrir\noffrira\noffrirai\noffrirait\noffris\noffrit\noffrons\noffs\noffusqua\noffusquait\noffusquant\nogdan\nogival\noglio\noignon\noignons\noindra\noirrait\noisif\noisifs\noisillon\noisillons\noisir\nolfactif\nolga\nolifant\nomar\nombilic\nombilical\nombilicaux\nombrait\nomicron\nomis\nomission\nomissions\nomnia\nomnibus\nonassinck\nonction\nonctions\nondoyons\nondulant\nondulation\nonyx\nopacifiait\nopacifiant\nopalin\nopalins\nophtalmo\nopina\nopinai\nopinant\nopinion\nopium\nopopanax\nopoponax\nopossum\noppidum\nopportun\nopposa\nopposait\nopposant\nopposition\nopprimait\noptalidon\noptat\noptatif\noptatifs\noptima\noptimal\noptions\noptât\nopus\noraison\noraisons\noral\norang\noratorio\nordinator\nordo\nordonna\nordonnai\nordonnait\nordonnant\norgandi\norganisa\norganisait\norganisant\norganisation\norganisations\norgon\noribus\norigan\noriginal\noriginant\noriginaux\norignals\norillons\norion\norlando\norly\nornait\nornans\nornant\norpin\norrouy\norsay\northographiait\nortolans\nosai\nosais\nosait\nosaka\nosant\noscars\noscillant\noscillation\noscillo\noshi\noskar\noslo\nosman\nossia\nossian\nosso\noswald\nothon\notoshi\nottaviani\nottavio\notto\nottoman\nouais\nouatant\noubli\noublia\noubliais\noubliait\noubliant\noublias\noublions\noublis\noudinot\noudry\noufik\noufkir\nouistiti\noulianov\noulipo\nouragan\nouragans\nourdi\nourdir\nourdira\nourdis\nourdissant\nourdissoir\nourdit\nours\noursin\noustachis\noutang\noutangs\noutil\noutils\nouvoir\nouvrait\nouvrant\nouvrir\nouvrira\nouvrirai\nouvrirais\nouvrirait\nouvris\nouvrit\nouvroir\nouvrons\nouïr\nouïs\nouït\novation\novibos\novins\novoïdal\noxford\noxydation\noyant\noyonnax\noyons\nozaru\noïdipos\npacha\npaddock\npadron\npagination\npagus\npaillard\npaillasson\npain\npair\npairs\npaix\npakçon\npaladin\npaladins\npalais\npalan\npalanquin\npalatin\npalatinat\npalissant\npallas\npalliatifs\npalpa\npalpation\npalpitait\npalpitant\npalpitations\npalustris\npamir\npampa\npanama\npanard\npanards\npaniqua\npaniquant\npannoir\npanofsky\npanorama\npans\npansas\npantalon\npantalons\npantois\npapa\npapal\npaparazzi\npapillon\npapillotait\npapon\npapou\npaprika\npapyrus\nparaboom\nparadait\nparadis\nparadoxal\nparadoxaux\nparaissais\nparaissait\nparaissant\nparamont\nparana\nparangon\nparaphait\nparaphant\nparaphrasa\nparaît\nparaîtra\nparaîtrait\nparc\nparcourait\nparcourant\nparcourir\nparcours\nparcourt\nparcouru\nparcourut\npardon\nparfait\nparfaits\nparfit\nparfois\nparfum\nparfumait\nparfums\npari\nparia\nparis\nparkinson\nparla\nparlait\nparlant\nparlas\nparlons\nparlât\nparmi\nparnassum\nparodi\nparoi\nparoissial\nparoli\nparos\nparrain\nparsifal\npart\npartait\npartant\npartants\nparti\npartial\nparticipa\nparticipait\nparticipant\nparticipation\npartir\npartira\npartirai\npartirait\npartiras\npartirons\npartis\npartisan\npartit\npartitif\npartition\npartons\npartout\nparturiant\nparturition\nparturitions\nparu\nparut\nparvins\nparvint\nparvis\npasionaria\npass\npassa\npassai\npassait\npassant\npassants\npassas\npassation\npassif\npassion\npassionnant\npassons\npastour\npatapouf\npatatration\npataud\npathos\npathovocalisation\npatins\npatois\npatriarcal\npatrimonial\npatriotard\npatron\npatrons\npatrouilla\npatrouillait\npaturin\npaturins\npaty\npaul\npaulhan\npaulin\npauma\npaumait\npaumant\npavillon\npavlov\npavois\npavor\npavot\npawlonias\npaya\npayai\npayait\npays\npaysan\npaysans\nphantasma\nphantasmant\npharaon\npharynx\nphhhht\nphilidor\nphilip\nphilippard\nphilo\nphilosophant\nphoto\nphotographia\nphotos\nphtiriasis\npiaillant\npianissimo\npiano\npianos\npianotait\npiaula\npiaulant\npica\npicaillons\npichu\npiganiol\npignochait\npignon\npignons\npilaf\npilla\npillait\npillard\npillards\npilon\npilori\npilum\npimpant\npindarisants\npingouin\npingouins\npinçard\npion\npipait\npiqua\npiquant\npiquants\npissant\npistant\npistils\npiston\npistons\npitchu\npiton\npityriasis\npivot\nplacard\nplacards\nplafond\nplafonds\nplaid\nplaida\nplaidait\nplaignant\nplain\nplaintif\nplaintifs\nplaira\nplaisait\nplaisant\nplaisantait\nplaisir\nplaisirs\nplan\nplanait\nplanant\nplanta\nplantait\nplantant\nplanton\nplantons\nplaqua\nplasma\nplastic\nplastron\nplat\nplaton\nplatonisant\nplats\nplay\nplaçait\nplaçant\nplaît\npliant\nploc\nplof\nplomb\nplombs\nploucs\nplouf\nployant\nplum\nplumial\nplumitifs\nplupart\nplus\nplut\npluton\nplutôt\npluvation\nplâtra\npochard\npoco\npodrida\npogrom\npoids\npoignant\npoignard\npoignards\npoignons\npoil\npoils\npoilu\npoindra\npoing\npoint\npointa\npointait\npoints\npointu\npointus\npoinçon\npoinçons\npoirautai\npoirota\npoirotait\npois\npoison\npoissard\npoisson\npoissons\npoitrail\npoivra\npolarisants\npoli\npolir\npolisson\npoliticards\npolka\npolo\npolochon\npolochons\npolonais\npoltron\npoltrons\npommard\npompait\npompidou\nponant\nponction\npond\npondant\npondu\npons\nponson\npont\npontchartrain\npontifical\npontificat\nponton\npoor\npopa\npopol\npopotin\npopulation\npopuli\npopulo\npornic\nport\nporta\nportail\nportait\nportant\nportants\nporthos\nportillon\nportillons\nportion\nportland\nporto\nportons\nportrait\nportraits\nports\nportsmouth\nportât\nposa\nposai\nposant\nposas\npositif\nposition\npost\nposta\npostal\npostaux\npostichard\npostillon\npostulait\npostulat\npotain\npotard\npotlatch\npotocki\npots\npouah\npouf\npouffant\npoula\npoulaga\npoulain\npouls\npoumon\npoupard\npoupards\npoupon\npoupons\npour\npourchassa\npourchassait\npourim\npourpoint\npourquoi\npourra\npourrais\npourrait\npourras\npourri\npourrions\npourrir\npourrira\npourriras\npourris\npourrissait\npourrissant\npourrissants\npourrit\npourrons\npourront\npoursuit\npoursuivait\npoursuivant\npoursuivi\npoursuivit\npoursuivrait\npourtant\npourtour\npourvoir\npourvoirons\npourvu\npourvus\npoussa\npoussait\npoussant\npoussas\npoussif\npoussin\npoussât\npouvait\npouvant\npouvoir\npouvoirs\npouvons\npoux\npratiqua\npratiquait\npria\npriait\npriant\nprima\nprimat\nprimitif\nprimitifs\nprimonatif\nprimordial\nprincipal\nprincipaux\nprincipium\nprions\npriori\npris\nprison\nprit\nprivait\nprivatif\nprivation\nprix\nprobant\nprobatif\nprocalmadiol\nprochain\nproclama\nproconsul\nprocurait\nprocuration\nprodiguions\nproductif\nproductifs\nproduction\nproduisait\nproduisant\nproduisit\nproduit\nproduits\nprof\nprofana\nprofilant\nprofit\nprofita\nprofitant\nprofond\nprofonds\nprofus\nprofusion\nprogrammation\nprohibait\nprohibition\npromis\npromit\npromouvoir\nprompt\nprompto\npromu\npromulguant\npronom\npronominal\nprononciation\nprononça\nprononçait\nprononçant\npronostic\npronostics\npronostiquait\npronto\npropagation\npropitia\nproportion\nproportions\npropos\nproposa\nproposait\nproposant\nproposition\nproposons\nproprio\npropulsa\npropulsion\nprorata\nproscrit\nproscrivait\nproscrivant\nproscrivit\nprostration\nprotagon\nprotagons\nprototypal\nprou\nproutt\nprouva\nprouvait\nprouvant\nprovincial\nprovision\nprovisions\nprovocation\nprovoqua\nprovoquait\nprovoquant\nprovoquât\nproximal\nprurigo\nprurit\nprônait\npsalmodia\npsalmodiant\npsychologisation\npuait\npuant\npuants\npubis\npublia\npublic\npublication\npublics\npudding\npudibond\npugilat\npuis\npuisait\npuisant\npuisard\npuisqu\npuissant\npuissants\npuits\npulsion\npulsions\npuma\npumas\npunch\npuni\npunir\npunit\npunitif\npunition\npunito\npurifiant\npurification\npurifications\npurin\npuritain\npurotin\npurotins\npurpurin\npurpurins\npurs\npurânas\nputain\nputains\nputatif\nputatifs\nputsch\npyjama\npyroproductif\npython\npâlir\npâlissant\npâlit\npâlot\npâmait\npâmant\npâmoison\npâtir\npâtira\npâtis\npâtissons\npâtit\npâtour\nquadri\nquadrigonal\nquadrupla\nquaggiu\nquai\nqualification\nquand\nquant\nquanti\nquantum\nquart\nquartaut\nquarto\nquarts\nquartz\nquasi\nquasia\nquasimodo\nquatuor\nquay\nquayno\nquidam\nquidams\nquignon\nquillon\nquillons\nquinault\nquintal\nquintaux\nquintinshill\nquintupla\nquipos\nquiproqui\nquiproquo\nquitta\nquittait\nquittant\nquittas\nquoaillant\nquoi\nquoiqu\nquorum\nrabais\nrabaud\nrabbin\nrabonnir\nrabougri\nrabougris\nrabougrit\nrabâcha\nrabâchait\nrabâchant\nraccord\nraccourci\nraccourcir\nraccourcit\nraccourir\nraccourt\nraccroc\nraccrocha\nraccusa\nrachis\nraciaux\nrack\nraclant\nraconta\nracontais\nracontait\nracontant\nracontar\nracontars\nracontas\nracorni\nracornissait\nradar\nradiation\nradin\nradio\nradioactif\nradis\nradotant\nradotis\nraffirma\nraffolait\nrafla\nrafraîchi\nrafraîchir\nrafraîchis\nrafraîchissant\nragaillardi\nragaillardira\nragaillardirait\nraglan\nragot\nragoûtants\nrahat\nraid\nraidi\nraidis\nraidit\nraifort\nrail\nraincy\nraisin\nraisins\nraison\nraisonnait\nraisons\nraki\nralluma\nramadan\nramas\nramassa\nramassis\nramdam\nramolli\nramollis\nramollit\nrampait\nrampant\nrampot\nrampotons\nramsay\nramun\nranci\nrandall\nrandolph\nrandonnait\nrang\nrank\nranz\nrançon\nrançonnants\nrapatriait\nrapiat\nrapin\nrapointir\nrapparaissait\nrapparu\nrapparut\nrapport\nrapportai\nrapports\nrappris\nrapprochions\nrapt\nrara\nrasa\nrasoir\nraspail\nrassainir\nrassortir\nrassura\nrassurant\nrastignac\nratatam\nratichons\nration\nratissant\nrats\nrauqua\nravaillac\nravala\nravi\nravin\nravir\nravissant\nravivant\nravoir\nraya\nraymond\nrayon\nrayonnait\nrayonnant\nrayons\nrazzias\nrhin\nrhino\nrhodopot\nrhomboïdal\nrhum\nrhumatisant\nrhumatismal\nriant\nribotait\nricain\nricana\nricanait\nricanant\nriccoboni\nrich\nrichard\nrichmond\nrictus\nriflard\nriga\nrigaudons\nright\nrigolait\nrigolant\nrigolard\nrigolo\nrigor\nrimbaud\nrimini\nrimski\nrinuccinni\nrions\nripaillait\nriposta\nriqui\nrisquait\nrisquant\nrita\nrital\nritualisa\nritualisation\nrivadavia\nrival\nrivalisation\nroad\nrobins\nrobinson\nroblot\nroboratif\nrobot\nrocamadour\nroch\nrocking\nrococo\nrodas\nrodin\nrogatons\nrognon\nroidi\nrois\nroland\nroll\nrollmops\nroma\nromain\nroman\nromanisation\nromanorum\nromans\nromantic\nromantisation\nromarin\nrompant\nrompit\nrompons\nrompu\nrompus\nromuald\nromulus\nrond\nrondos\nronds\nronflant\nronron\nroom\nrorqual\nrorquals\nrosa\nrosato\nrossignol\nrostand\nrota\nrotatif\nrothschild\nrotor\nrotto\nrouan\nroubaud\nroucoulant\nrougir\nrougissant\nrougit\nrougon\nroulait\nroulant\nroulis\nroupillon\nroussin\nrouvrir\nroux\nrowing\nroyal\nruban\nrubans\nrubican\nrubicond\nrubicons\nrubis\nrudolf\nruffian\nruffo\nrugby\nrugi\nrugir\nrugis\nrugissait\nrugissant\nrugit\nruhlmann\nrullianus\nruminant\nrural\nrutabaga\nruth\nrutilant\nrâlant\nrôdait\nrôdant\nrôti\nrôtir\nrôtissait\nsabayon\nsabbat\nsabin\nsabinial\nsabla\nsablons\nsabot\nsabotait\nsabots\nsachant\nsachions\nsaclant\nsacra\nsacrifiant\nsacripants\nsacristain\nsacristains\nsacs\nsafari\nsafran\nsaga\nsagas\nsahagun\nsahara\nsahib\nsaid\nsaignait\nsaillants\nsaillir\nsain\nsaindoux\nsaint\nsais\nsaisi\nsaisir\nsaisira\nsaisirait\nsaisiras\nsaisirons\nsaisis\nsaisissait\nsaisissant\nsaisit\nsaison\nsaisons\nsait\nsala\nsalah\nsalaison\nsalants\nsalgidal\nsali\nsalir\nsalis\nsalissant\nsalivant\nsalmigondis\nsalomonis\nsalon\nsaloon\nsalopards\nsalpicon\nsalsifis\nsalua\nsaluant\nsalut\nsalutations\nsaluts\nsalvatori\nsamaritain\nsambin\nsampan\nsamson\nsanatorium\nsancta\nsanction\nsandorf\nsandwich\nsandwichs\nsang\nsanglant\nsanglants\nsanglot\nsanglota\nsanglotait\nsanglotant\nsanglots\nsangs\nsanguin\nsano\nsans\nsanson\nsantal\nsantana\nsaoul\nsaoulait\nsaphir\nsaphirs\nsapin\nsarah\nsarbacan\nsardon\nsarrasin\nsarrasins\nsarrau\nsarraus\nsarrois\nsartinuloc\nsasso\nsatan\nsatchmo\nsatiation\nsatin\nsatisfaction\nsatisfactions\nsatisfaisant\nsatisfait\nsaturant\nsaturation\nsaucisson\nsauf\nsaupoudra\nsaura\nsaurais\nsaurait\nsauras\nsaurons\nsaut\nsauta\nsautant\nsautoir\nsautoirs\nsavais\nsavait\nsavant\nsavants\nsavarin\nsavary\nsavions\nsavoir\nsavoirs\nsavons\nsavorgnan\nsavoura\nsavourait\nsavourant\nsavoyards\nsaxo\nsaxon\nscala\nscandalisa\nscandalisant\nscapin\nscarborough\nscarifiant\nscarmouchis\nscazons\nschako\nscharf\nschizo\nschlussnig\nschnaps\nschola\nschonthan\nschool\nschumann\nschupo\nsciait\nscilicat\nscintillait\nscintillant\nscintillations\nscions\nscission\nsclavons\nscolarisation\nscorbut\nscorpion\nscotch\nscotland\nscott\nscout\nscribouillard\nscript\nscription\nscriptor\nscriptum\nscrivain\nscruta\nscrutait\nscrutant\nscrutin\nscrutins\nsculpta\nsculptural\nscutari\nshadows\nshah\nshako\nshampooing\nshandy\nshavouot\nshikibu\nshiraz\nshkodra\nshot\nshulhan\nshut\nsiam\nsiamois\nsibylla\nsibyllin\nsiffla\nsifflait\nsifflant\nsifflota\nsifflotait\nsifflotant\nsigalas\nsigna\nsignait\nsignal\nsignalait\nsignalant\nsignalons\nsignalât\nsignaux\nsignifiait\nsignifiant\nsignificandi\nsignificatif\nsignification\nsignifications\nsignifying\nsignons\nsignor\nsihanouk\nsillon\nsillons\nsilo\nsilos\nsimili\nsimilia\nsimilibus\nsimonisait\nsimoun\nsimplicitas\nsimulait\nsimulant\nsimulation\nsinatra\nsinciput\nsindon\nsinfonias\nsinon\nsint\nsinuant\nsinus\nsinusoïdal\nsion\nsiphon\nsirdar\nsirocco\nsirop\nsirotait\nsisal\nsituation\nsitôt\nsixain\nskiff\nslatim\nslips\nslivowitz\nslogan\nslogans\nsloop\nsloughi\nsmalah\nsmall\nsmaragdin\nsmigard\nsmith\nsmoking\nsnack\nsncf\nsnob\nsobranvi\nsobranyi\nsocial\nsociaux\nsoda\nsodomisant\nsodomisation\nsofa\nsofas\nsofia\nsoif\nsoigna\nsoignait\nsoin\nsoins\nsoir\nsois\nsoit\nsokoro\nsola\nsolda\nsoldat\nsoldats\nsoliman\nsollicita\nsolo\nsolti\nsolum\nsolus\nsolution\nsolutions\nsombra\nsombrait\nsombrons\nsommant\nsommation\nsommations\nsomnambulant\nsomnolait\nsomnolant\nsonda\nsondant\nsondas\nsong\nsonna\nsonnai\nsonnait\nsonnant\nsonnons\nsono\nsons\nsont\nsopha\nsophistication\nsopor\nsoprano\nsororal\nsors\nsort\nsortait\nsortant\nsorti\nsortir\nsortirons\nsortis\nsortit\nsortons\nsorts\nsouchon\nsouci\nsoucis\nsoudain\nsoudanais\nsoudoya\nsoudoyait\nsouffla\nsoufflait\nsoufflant\nsoufflot\nsouffrait\nsouffrant\nsouffrir\nsouffrit\nsouffrons\nsouffrît\nsouhait\nsouhaitait\nsouhaitons\nsouhaits\nsouk\nsouligna\nsoulignait\nsoult\nsoumis\nsoumission\nsound\nsoupait\nsoupir\nsoupira\nsoupirait\nsoupirant\nsoupirants\nsoupirs\nsoupçon\nsoupçonnait\nsoupçons\nsourcil\nsourcils\nsourd\nsourdait\nsouri\nsouriait\nsouriant\nsouris\nsourit\nsournois\nsous\nsouscription\nsoustraction\nsoustrait\nsoustraits\nsoutint\nsouvaroff\nsouvi\nsouvint\nsouzay\nsoyons\nspahi\nspahis\nspalato\nsparadrap\nsphinx\nspica\nspinoza\nspiqua\nsplit\nsport\nsportif\nsportifs\nsports\nsquadron\nsquaw\nstabilisation\nstaff\nstaffs\nstagna\nstagnant\nstamboul\nstampillon\nstanding\nstanislas\nstaphylococcus\nstar\nstarbuck\nstation\nstationnait\nstationnant\nstations\nstatu\nstatufiant\nstatut\nstatuts\nstich\nstick\nstigma\nstimula\nstimulant\nstimulus\nstipulant\nstirling\nstock\nstockait\nstockholm\nstocks\nstomacal\nstomato\nstomox\nstop\nstoppa\nstoppait\nstoppât\nstormings\nstory\nstourbir\nstout\nstradivarius\nstraggling\nstram\nstrangula\nstrangulant\nstrangulation\nstrapontin\nstrato\nstravagant\nstravagants\nstriait\nstrict\nstricts\nstrobo\nstrontium\nstructural\nstubb\nstuc\nstudiantin\nstudio\nstudiorum\nstudios\nstuffing\nstupid\nsturmi\nstylo\nstyx\nsuait\nsuant\nsubcortico\nsubi\nsubir\nsubissant\nsubissons\nsubit\nsubito\nsubjonctif\nsubjonctifs\nsublinguaux\nsubscription\nsubscrit\nsubsistait\nsubstantif\nsubstantifs\nsubstitua\nsubstituai\nsubstituait\nsubstitut\nsubstitution\nsubstituts\nsubstratum\nsubstruction\nsubtil\nsubtils\nsuccinct\nsuccion\nsuccomba\nsuccombait\nsuch\nsucrins\nsuffi\nsuffira\nsuffirait\nsuffisait\nsuffisant\nsuffisants\nsuffit\nsuffocant\nsuffoqua\nsuffoquait\nsuffoquant\nsuicida\nsuicidait\nsuicidant\nsuicidât\nsuintait\nsuis\nsuit\nsuivait\nsuivant\nsuivants\nsuivi\nsuivit\nsuivons\nsuivrais\nsuivrons\nsuiza\nsully\nsultan\nsumma\nsummum\nsunna\nsunt\nsupplantait\nsuppliait\nsupplication\nsuppliât\nsupport\nsupportait\nsupportant\nsupposa\nsupposant\nsupposition\nsuppositions\nsuppositorial\nsupposons\nsupprimait\nsupputant\nsupra\nsupranational\nsuraigu\nsurakarta\nsurard\nsurcroît\nsurgi\nsurgir\nsurgirait\nsurgissait\nsurgissant\nsurgit\nsurhumain\nsuri\nsurin\nsurmoi\nsurnom\nsurnomma\nsurnommait\nsuroît\nsurplombait\nsurplus\nsurpris\nsurprit\nsurpuissant\nsursaut\nsursauta\nsursautait\nsursautant\nsursis\nsurtout\nsurvint\nsurvivait\nsurvivant\nsurvivons\nsurvivrait\nsurvivront\nsurvola\nsuscita\nsuscitait\nsuscitant\nsusdit\nsuspicion\nsussurait\nsuturant\nsuturation\nsuys\nsuât\nsuçait\nsuçotait\nswann\nswift\nswing\nsymbolisait\nsymbolisant\nsymbolisation\nsympa\nsymposium\nsyncopal\nsyndicat\nsyndicats\nsyndics\nsynopsis\nsyphilis\ntabac\ntabou\ntact\ntaft\ntagadac\ntaiba\ntailladant\ntaillis\ntailor\ntaira\ntairons\ntais\ntaisait\ntaisant\ntaisons\ntakagawa\ntakamoku\ntalc\ntalion\ntalisman\ntalk\ntallipot\ntalmud\ntalon\ntalonnait\ntalons\ntamanoir\ntamazusa\ntambour\ntambourin\ntambours\ntamis\ntampon\ntandis\ntango\ntanguant\ntank\ntanka\ntankas\ntant\ntantôt\ntaon\ntaons\ntapant\ntapi\ntapinois\ntapir\ntapira\ntapis\ntapit\ntapota\ntapotait\ntapotant\ntaquin\ntaquoir\ntarabiscot\ntaratata\ntaraud\ntard\ntardjouman\ntargui\ntari\ntarin\ntarir\ntaris\ntarissant\ntarlatan\ntartinait\ntarzan\ntassili\ntatata\ntatillon\ntatou\ntatouait\ntatous\ntaxi\ntaxis\ntaylor\ntchad\ntchouan\nthanatogramma\nthank\nthaon\nthat\nthird\nthirty\ntholon\nthomas\nthon\nthorah\nthorax\nthousand\nthugga\nthulin\nthuya\nthym\ntiflis\ntifs\ntillac\ntilman\ntimariot\ntimon\ntimoration\ntimour\ntindouf\ntinkling\ntins\ntint\ntintinnabulant\ntintouins\ntippoo\ntira\ntirailla\ntiraillant\ntirait\ntirana\ntirant\ntiras\ntiroir\ntiroirs\ntirons\ntison\ntissait\ntissant\ntissu\ntitan\ntitanic\ntito\ntitra\ntituba\ntitubant\ntitubation\ntitus\ntoast\ntobolsk\ntocsin\ntoffana\ntohu\ntoisa\ntoison\ntoit\ntoits\ntold\ntomahawk\ntomahawks\ntomba\ntombais\ntombait\ntombant\ntombouctou\ntonitruant\ntonna\ntonnant\ntonton\ntontons\ntophus\ntopinambour\ntopons\ntorchis\ntorchon\ntorchons\ntord\ntordait\ntordant\ntordu\ntordus\ntorsion\ntort\ntorticolis\ntortil\ntortilla\ntortillard\ntortillon\ntorturait\ntorturant\ntoscan\ntotal\ntotalisation\ntoton\ntouat\ntoubib\ntoubibs\ntoucha\ntouchait\ntouchant\ntouffu\ntoujours\ntoulon\ntoundra\ntour\ntourbillon\ntourbillonna\ntourbillonnant\ntourbillons\ntourillon\ntouring\ntourlourou\ntourna\ntournait\ntournant\ntournants\ntournis\ntournoi\ntournois\ntournons\ntournoya\ntournoyant\ntours\ntous\ntoussa\ntoussaint\ntoussant\ntoussota\ntout\ntoutou\ntown\ntrabuco\ntrac\ntracas\ntracassait\ntracassant\ntractions\ntractus\ntradition\ntraditions\ntraduction\ntraductions\ntraduisait\ntraduisit\ntraduit\ntrafic\ntraficants\ntrafiquait\ntrahi\ntrahir\ntrahison\ntrahissait\ntrahit\ntrain\ntrait\ntraitait\ntraitant\ntraits\ntrajan\ntralala\ntralalas\ntramail\ntramait\ntramant\ntran\ntranchant\ntranquillisant\ntransafricain\ntransat\ntranscription\ntranscrit\ntranscrits\ntranscrivant\ntransformation\ntransfusion\ntransfusions\ntransi\ntransistors\ntransit\ntransitif\ntransmis\ntransmission\ntransparaissait\ntransparaît\ntranspassait\ntranspira\ntranspirait\ntranspirant\ntransport\ntransporta\ntransports\ntranssubstantiation\ntransvaal\ntrapu\ntrapus\ntraquait\ntraquant\ntrauma\ntravail\ntravailla\ntravaillait\ntravaillons\ntravaux\ntrayant\ntraça\ntraçait\ntraçant\ntraînait\ntraînant\ntraînard\ntriangulation\ntrianon\ntribart\ntribu\ntribunal\ntribus\ntric\ntricot\ntricots\ntrimard\ntringas\ntrinqua\ntrinquant\ntrio\ntriompha\ntriomphait\ntriomphal\ntriomphant\ntriomphants\ntrip\ntriparturition\ntripla\ntripota\ntripots\ntrismus\ntristan\ntristou\ntristram\ntritons\ntriturait\ntrituration\ntrivial\ntriviaux\ntrocart\ntrognons\ntrois\ntroll\ntronc\ntrop\ntroquas\ntrot\ntrottoir\ntrou\ntroubadour\ntroubla\ntroublait\ntroublant\ntroublants\ntrouffions\ntroufignon\ntroupiau\ntrous\ntroussa\ntrouva\ntrouvai\ntrouvait\ntrouvant\ntrouvas\ntrouvons\ntrouvât\ntroyat\ntroïkas\ntruands\ntruc\ntrucida\ntrucidant\ntrucs\ntruly\ntrusquin\ntrust\ntryphiodorus\ntrônait\ntsumori\ntuait\ntuba\ntubar\ntudor\ntumuli\ntumulus\ntunis\ntuons\nturbin\nturbot\nturc\nturf\nturin\ntutorial\ntutoyant\ntutoyons\ntutti\ntuyau\ntuyaux\ntwilight\ntympan\ntympanon\ntympans\ntyphon\ntyphons\ntyphus\ntypo\ntypos\ntyran\ntyrannisant\ntyrans\ntâchant\ntâchons\ntâta\ntâtonnant\ntâtons\nuaxactun\nubac\nuicidant\nulrich\nultimal\nultimatum\nultimaux\nultra\nultradisant\nultrafin\nultramontains\nungaro\nuninominal\nunion\nunir\nunira\nunis\nunissait\nunissant\nunisson\nunit\nunto\nuomo\nupanishads\nupas\nupsala\nuranium\nurbain\nurbino\nursins\nurubu\nurus\nusai\nusant\nuskub\nustion\nusufruit\nusuzumi\nutilisa\nutilisai\nutilisait\nutilisant\nutilisation\nuttaïr\nuxorilocal\nvacant\nvacations\nvaccin\nvaccino\nvachards\nvacilla\nvacillant\nvacuum\nvagabond\nvagabonds\nvagi\nvagissais\nvagissait\nvagissant\nvagissons\nvagit\nvagula\nvaillant\nvain\nvaincrait\nvaincs\nvaincu\nvainquit\nvains\nvairons\nvais\nvalait\nvalant\nvaldingua\nvaldo\nvalida\nvalidation\nvallon\nvallons\nvalmont\nvaloir\nvalparaiso\nvalu\nvalut\nvamp\nvanish\nvantail\nvantait\nvaquait\nvaquons\nvariorum\nvasavadatta\nvasistas\nvassal\nvassall\nvassaux\nvatican\nvaticination\nvaudra\nvaut\nvautour\nvautrin\nvaux\nvavin\nvaziluia\nvibra\nvibrait\nvibrant\nvibration\nvibrions\nvichnou\nvictor\nvictoria\nvictorias\nvidait\nvidons\nvifs\nvigilant\nvigilants\nvignon\nviking\nvilain\nvilla\nvillacorta\nvillacoublay\nvils\nvincit\nvindicatif\nvindication\nvingt\nvins\nvint\nviol\nviolait\nviolant\nviolationis\nviolin\nviolon\nviolons\nvirginal\nvirginia\nvirginy\nviridans\nviridifiant\nviril\nvirtualisation\nvirtuosi\nvirus\nvisa\nvisant\nvisconti\nvision\nvisita\nvisitait\nvisitant\nvisitation\nvison\nvissa\nvital\nvitalium\nvitaux\nvitrail\nvitraux\nvivais\nvivait\nvivant\nvivants\nvivifiant\nvivions\nvivons\nvivrait\nvivrons\nvizir\nvladimir\nvobiscum\nvocabulariat\nvocalisait\nvocalisant\nvocalisation\nvocalisations\nvocation\nvocaux\nvogt\nvoici\nvoilà\nvoir\nvois\nvoisin\nvoisinait\nvoit\nvoitot\nvoix\nvola\nvolait\nvolant\nvolants\nvolapück\nvolatil\nvolcan\nvolition\nvolons\nvolontariat\nvolubilis\nvomi\nvomir\nvomissant\nvomitif\nvont\nvoudrais\nvoudrait\nvoudras\nvoudrions\nvoudrons\nvoulais\nvoulait\nvoulant\nvouloir\nvouloirs\nvoulons\nvoulu\nvoulut\nvoulût\nvous\nvouvoya\nvoyagions\nvoyais\nvoyait\nvoyal\nvoyant\nvoyants\nvoyions\nvoyl\nvoyons\nvoyou\nvoyous\nvrai\nvrilla\nvrombir\nwagon\nwagons\nwagram\nwaiting\nwalpurgis\nwapiti\nwarburg\nwarm\nwartburg\nwashington\nwasn\nwasqu\nwhat\nwhig\nwhipcord\nwhisky\nwhiskys\nwhist\nwidmark\nwigwam\nwilburg\nwill\nwilliam\nwilligis\nwillo\nwilson\nwinding\nwindow\nwindows\nwinston\nwisconsin\nwitold\nwittig\nwobisch\nwoodrow\nwoolf\nworms\nwright\nxiphidion\nxviii\nxxiii\nyacht\nyack\nyard\nyarn\nyatagan\nyazid\nyaùq\nyoga\nyoghourt\nyogi\nyolanda\nyori\nyorick\nyork\nyotsu\nyoung\nyour\nyours\nyoyo\nyucatan\nyvazoulay\nyvon\nzahir\nzain\nzakouskis\nzanzi\nzanzibar\nzarathoustra\nzazou\nzigouillait\nzigzaguait\nzigzaguant\nzinc\nzincs\nzingaro\nzinnia\nzinzin\nzinzins\nzinzolin\nzippo\nzohar\nzola\nzona\nzonal\nzoos\nzori\nzorilla\nzotanburg\nzoziau\nzozotant\nzurich\nzurichois\nzygoma\nânon\nçatapathabrâhmana\nçruti\nîlot\nîlots\nôtai\nôtait\nôtant\n"
  },
  {
    "path": "mocodo/resources/lorem/en4.txt",
    "content": "able\nacid\naide\nAIDS\nally\nalso\namid\nArab\narea\narmy\natop\naunt\nauto\naway\nbaby\nback\nbake\nball\nband\nbank\nbare\nbarn\nbase\nbath\nbeam\nbean\nbear\nbeat\nbeef\nbeer\nbell\nbelt\nbend\nbest\nbias\nbike\nbill\nbind\nbird\nbite\nblow\nblue\nboat\nbody\nboil\nbold\nbolt\nbomb\nbond\nbone\nbook\nboom\nboot\nborn\nboss\nboth\nbowl\nbuck\nbulb\nbulk\nbull\nburn\nbury\nbush\nbusy\nbutt\ncage\ncake\ncall\ncalm\ncamp\ncard\ncare\ncart\ncase\ncash\ncast\ncave\ncell\nchef\nchew\nchin\nchip\nchop\ncite\ncity\nclay\nclip\nclub\nclue\ncoal\ncoat\ncode\ncoin\ncold\ncome\ncook\ncool\ncope\ncopy\ncord\ncore\ncorn\ncost\ncoup\ncrew\ncrop\ncure\ncute\ndamn\ndare\ndark\ndata\ndate\ndawn\ndead\ndeal\ndear\ndebt\ndeck\ndeem\ndeep\ndeer\ndeny\ndesk\ndiet\ndirt\ndisc\ndish\ndisk\ndock\ndoll\ndoor\ndose\ndown\ndrag\ndraw\ndrop\ndrug\ndrum\nduck\ndumb\ndump\ndust\nduty\neach\nearn\nease\neast\neasy\necho\nedge\nedit\nelse\neven\never\nevil\nexam\nexit\nface\nfact\nfade\nfail\nfair\nfall\nfame\nfare\nfarm\nfast\nfate\nfear\nfeed\nfeel\nfile\nfill\nfilm\nfind\nfine\nfire\nfirm\nfish\nfist\nfive\nflag\nflat\nflee\nflip\nflow\nfold\nfolk\nfood\nfool\nfoot\nfork\nform\nfour\nfree\nfrom\nfuel\nfull\nfund\ngain\ngame\ngang\ngate\ngaze\ngear\ngene\ngift\ngirl\ngive\nglad\ngoal\ngoat\ngold\ngolf\ngood\ngrab\ngray\ngrin\ngrip\ngrow\nhair\nhalf\nhall\nhand\nhang\nhard\nharm\nhate\nhaul\nhave\nhead\nheal\nhear\nheat\nheel\nhell\nhelp\nherb\nhere\nhero\nhers\nhide\nhigh\nhike\nhill\nhint\nhire\nhold\nhole\nholy\nhome\nhook\nhope\nhorn\nhost\nhour\nhuge\nhunt\nhurt\nicon\nidea\ninto\niron\nitem\njail\njazz\njoin\njoke\njump\njury\njust\nkeep\nkick\nkill\nkind\nking\nkiss\nknee\nknow\nlack\nlady\nlake\nlamp\nland\nlane\nlast\nlate\nlawn\nlead\nleaf\nlean\nleap\nleft\nlend\nlens\nless\nlife\nlift\nlike\nlimb\nline\nlink\nlion\nlist\nlive\nload\nloan\nlock\nlong\nlook\nloop\nlose\nloss\nlost\nlots\nloud\nlove\nluck\nlung\nmail\nmain\nmake\nmale\nmall\nmany\nmark\nmask\nmass\nmate\nmath\nmeal\nmean\nmeat\nmeet\nmelt\nmenu\nmere\nmess\nmild\nmilk\nmill\nmind\nmine\nmiss\nmode\nmood\nMoon\nmore\nmost\nmove\nmuch\nmust\nmyth\nnail\nname\nnear\nneat\nneck\nneed\nnest\nnews\nnext\nnice\nnine\nnone\nnoon\nnorm\nnose\nnote\nodds\nokay\nonce\nonly\nonto\nopen\noral\nours\noven\nover\npace\npack\npage\npain\npair\npale\npalm\npant\npark\npart\npass\npast\npath\npeak\npeel\npeer\npick\npile\npill\npine\npink\npipe\nplan\nplay\nplea\nplot\nplus\npoem\npoet\npoke\npole\npoll\npond\npool\npoor\npork\nport\npose\npost\npour\npray\npull\npump\npure\npush\nquit\nrace\nrack\nrage\nraid\nrail\nrain\nrank\nrape\nrare\nrate\nread\nreal\nrear\nrely\nrent\nrest\nrice\nrich\nride\nring\nriot\nrise\nrisk\nroad\nrock\nrole\nroll\nroof\nroom\nroot\nrope\nrose\nruin\nrule\nrush\nsack\nsafe\nsail\nsake\nsale\nsalt\nsame\nsand\nsave\nscan\nseal\nseat\nseed\nseek\nseem\nself\nsell\nsend\nsexy\nshed\nship\nshit\nshoe\nshop\nshot\nshow\nshut\nsick\nside\nsigh\nsign\nsilk\nsing\nsink\nsite\nsize\nskin\nskip\nslam\nslap\nslew\nslip\nslot\nslow\nsnap\nsnow\nsoak\nsoap\nsoar\nsock\nsofa\nsoft\nsoil\nsole\nsome\nsong\nsoon\nsort\nsoul\nsoup\nspin\nspit\nspot\nstar\nstay\nstem\nstep\nstir\nstop\nsuch\nsuck\nsuit\nsure\nswim\ntail\ntake\ntale\ntalk\ntall\ntank\ntape\ntask\nteam\ntear\nteen\ntell\ntend\ntent\nterm\ntest\ntext\nthan\nthat\nthem\nthen\nthey\nthin\nthis\nthus\ntide\ntile\ntill\ntime\ntiny\ntire\ntoll\ntone\ntool\ntoss\ntour\ntown\ntrap\ntray\ntree\ntrim\ntrip\ntrue\ntube\ntuck\ntune\nturn\ntwin\ntype\nugly\nunit\nupon\nurge\nused\nuser\nvary\nvast\nvery\nview\nvile\nvote\nwage\nwait\nwake\nwalk\nwall\nwant\nwarm\nwarn\nwash\nwave\nweak\nwear\nweed\nweek\nwell\nwest\nwhat\nwhen\nwhip\nwhom\nwide\nwife\nwild\nwill\nwind\nwine\nwing\nwipe\nwire\nwise\nwish\nwith\nwolf\nwood\nword\nwork\nwrap\nyard\nyeah\nyear\nyell\nyour\nzone\n"
  },
  {
    "path": "mocodo/resources/lorem/fr.txt",
    "content": "pour\ndans\nplus\nsont\navec\ncette\nmais\ncomme\ntout\nnous\nMais\nfait\nété\naussi\nleur\nbien\npeut\ndeux\nencore\nmarché\nPour\ndonc\ncours\nmoins\nsans\nentre\nfaire\nelle\nvous\nprix\ndont\négalement\nDans\neffet\npays\nmillions\nBelgique\nmois\nleurs\ntaux\nannées\ntemps\ngroupe\nainsi\ntoujours\nsociété\ndepuis\ntous\nsoit\nfaut\nBruxelles\nfois\nquelques\nsera\nentreprises\ncontre\nfrancs\nNous\nCette\ndernier\nétait\nchez\nmonde\nalors\nsous\nactions\nautres\nreste\ntrois\nnotre\ndoit\nnouveau\nmilliards\navant\nexemple\ncompte\nbelge\npremier\nnouvelle\nElle\nterme\navait\nproduits\ncela\nniveau\nbénéfice\ntoute\ntravail\npartie\ntrop\nhausse\nsecteur\npart\nbeaucoup\nvaleur\ncroissance\nrapport\nannée\nbase\nBourse\nlors\nvers\nsouvent\nautre\npeuvent\nsurtout\ntoutes\nnombre\nfonds\npoint\ngrande\njour\navoir\nquelque\nplace\ngrand\npersonnes\nplusieurs\ncertains\npermet\npolitique\nchaque\nchiffre\npourrait\ndevrait\nproduit\nrien\nmieux\ncelui\nqualité\nFrance\nvente\njamais\nproduction\naction\nbaisse\nAvec\nrésultats\nvotre\nrisque\ndébut\nbanque\nvoir\navons\nelles\nmoment\nquestion\npouvoir\ntitre\ndoute\nlong\npetit\nnotamment\ndroit\nheures\ncependant\nservice\nEtats-Unis\njours\ncelle\ndemande\nbelges\nceux\nservices\nbonne\nseront\néconomique\nraison\nsituation\nDepuis\nentreprise\nnouvelles\npossible\ntoutefois\ntant\nnouveaux\nselon\nparce\nseul\nsociétés\nvient\njusqu\nquatre\nmarchés\nmise\nseulement\nsemble\nclients\nTout\nCela\nserait\nfort\nfrais\nlieu\ngestion\nfont\nquand\ncapital\ngouvernement\nprojet\ngrands\nréseau\ndonnées\nprendre\nplan\npoints\noutre\npourtant\nAinsi\ntype\nEurope\npendant\nComme\nmesure\nactuellement\npublic\ndire\nimportant\npartir\nparfois\nveut\nprésent\npassé\nforme\nautant\ndéveloppement\nmettre\ngrandes\ninvestisseurs\ntrouve\nmaison\nmoyen\nchoix\ndoivent\ndirection\nsimple\npériode\nenfants\ndollars\npersonnel\nassez\nprogramme\ngénéral\nbanques\nsemaine\nprésident\npersonne\neuropéenne\nmoyenne\ntard\npetite\ncertaines\nsavoir\nloin\nexplique\nplupart\njeunes\ncinq\ncontrat\nBanque\nvaleurs\nseule\nrendement\nnombreux\nfonction\noffre\nclient\nactivités\nenviron\nministre\ncadre\nsens\nétaient\nsécurité\nrecherche\nParis\nsorte\ndécembre\nsuite\ndavantage\nensuite\njanvier\ndonne\nvrai\ncause\nconditions\nsuis\njuin\npeine\ncertain\nseptembre\nsommes\nfamille\npris\nlaquelle\ndirecteur\npropose\ngens\nderniers\nétant\nchose\nportefeuille\nobligations\nafin\ndifférents\ntechnique\nailleurs\naméricain\nventes\nSelon\nlivre\noctobre\nvraiment\nsein\ndollar\nEnfin\nhaut\nPlus\npetits\nporte\ndurée\ndomaine\naurait\njeune\nprésente\npasse\nlorsque\nchoses\npuis\nVous\naucun\ntandis\ncoup\nexiste\npropre\ncarte\ncrise\nimportante\natteint\nrevenus\nmontant\nforte\nQuant\nrapidement\nville\nmars\npremiers\nmarque\nvéritable\nligne\nlongtemps\npropres\ndevant\npasser\ndépart\ntotal\nsérie\nquoi\nparticulier\nconcurrence\nélevé\nposition\nconnu\nprincipe\ntendance\ncourt\npages\névidemment\nrésultat\naura\nparmi\nSans\naméricaine\nface\ntrouver\ndurant\nfemmes\nconstruction\ndésormais\ndistribution\ntelle\ndifficile\nautour\neuropéen\npratique\ncentre\nvendre\njuillet\nrégion\nsociale\nfiliale\nfilm\nbesoin\nmode\nreprésente\nréalité\nfemme\nvaut\nTél\naucune\nhommes\ndonner\ntitres\nnombreuses\ndifférentes\nmoyens\nformation\nchiffres\nGénérale\nprochain\ngenre\nbureau\ncommunication\nparticipation\ngros\npourquoi\nestime\ndevient\nréalisé\ncréation\nnovembre\npourra\nsemaines\nconsommation\nfaible\nterrain\nsite\ndroits\nmoitié\npuisque\nreprise\ncompris\nprojets\navril\nvont\ncall\ndonné\nsimplement\nfirme\nperte\nBien\nPhilippe\nsait\nprend\nvite\nstratégie\npetites\nmarketing\npresque\nMichel\nmanque\nréaliser\nfinanciers\nComment\nvoiture\nchef\nconstitue\nInternet\nenfin\ncharge\nnature\nsecond\npayer\nactuel\nElles\ninvestissements\ndispose\nfinancier\nmembres\ndate\navaient\ngamme\nrevanche\ncomment\ndécision\ntour\nactionnaires\nsolution\ncréer\nconcerne\nbelle\nlequel\ntél\nseconde\nversion\nPays-Bas\ncher\nchacun\nlire\ntechniques\ndécidé\nmouvement\nconseil\nnécessaire\nmeilleur\ndouble\nsujet\ngénéralement\nrestent\ncelles\npolitiques\nmalgré\nconfiance\nhomme\nCertains\nayant\npapier\ncommerce\nRégion\nWallonie\nWindows\ntermes\ncontraire\ninformations\ntrimestre\ndifférence\ncertaine\nformule\nvoit\nprogrammes\nactuelle\npermis\ndossier\nQuand\nguerre\nacheter\nrendre\nfévrier\nmain\nvoire\nbons\ntechnologie\neuropéens\néléments\nunique\nvenir\ngénérale\ncourant\nsuffit\nconserver\nmaximum\nforce\nlargement\nmilliard\nsoient\nPierre\ndevenir\nfranc\nminimum\nmort\nresponsable\npossibilité\npresse\naffaires\nlongue\ntravers\nrelativement\nDeux\nprésence\neuropéennes\ndevraient\ngroupes\nensemble\nsanté\npense\nbénéfices\ncompagnie\npublique\ncœur\nrevenu\nmesures\ntable\nnettement\nquestions\npermettre\nChez\nretour\nmajorité\npotentiel\nmoindre\nrécemment\nsecteurs\nréduction\nlarge\ntraitement\nperdu\nétrangers\nparents\nfond\ncapacité\nvitesse\nactivité\nquel\ntient\ntaille\néviter\nrisques\nJean\nPourtant\nAllemagne\nparler\npropos\nquant\nsignifie\nvoie\njouer\nprévoit\nblanc\nnoir\nparti\nlogiciel\ncontinue\nNotre\nbois\nmeilleure\nperspectives\ndévelopper\ncelui-ci\nœuvre\nstructure\nsuivre\ntiers\nprise\nprofessionnels\nraisons\nnéanmoins\npreuve\nsocial\nbénéficiaire\ncouleurs\nmondial\nmaintenant\nessentiellement\nprévu\nJapon\nprévisions\ncentrale\nAlors\ninternational\nyeux\nbonnes\nopérations\npied\npourraient\nLondres\njuge\ndevra\nuniquement\ncorps\ndivers\nParmi\nnuméro\nréduire\nTous\ntexte\ntenu\nbudget\npression\nstyle\néconomiques\nJacques\nmontre\npopulation\nanalystes\nprocessus\nplacement\nclassique\ndividende\nrester\npublics\nfortement\nplein\nwallonne\nExpress\nfaudra\ntravailler\nCrédit\ndirectement\nprime\nFlandre\ncrédit\nmonnaie\nprécise\nappel\nAutre\ntravaux\njuste\nChaque\ntableau\nterre\npermettent\ndevenu\nrouge\nmémoire\npartenaires\nrapide\ntravailleurs\njoue\nobjectif\nsalle\nparle\nmusique\nmilieu\nautorités\nchute\nrégime\nliste\nopération\nbout\nperformances\nélectronique\nhaute\nresponsables\nlancé\nvoitures\npatron\nMalgré\naffiche\nsitue\nétudes\nMicrosoft\ncondition\nretrouve\nrevient\nBelgacom\nroute\nEnsuite\nLuxembourg\ncampagne\ncomptes\nhors\nculture\nCommission\npossibilités\nsemestre\nactifs\nfinalement\ninternationale\nmonétaire\npassage\njustice\npage\ntels\npoids\ncelle-ci\ncommercial\nentendu\nmondiale\naccord\ndiverses\ntotalement\nclair\nbiens\neuro\nYork\nparfaitement\nviennent\ndivision\nréseaux\nprincipal\nlancer\nsupérieur\natteindre\nréférence\ntéléphone\nmanagement\nvins\nproche\ncollection\nfiscale\nCeci\ninformatique\ninvestissement\nvolume\nmatériel\npublicité\ntrain\ncoupon\nprogression\ntenir\nprotection\ncouleur\nnouvel\nLorsque\nchange\nchangement\ngarantie\nsomme\nBelge\nplaisir\nfils\nlaisse\nimportants\nprivé\nbesoins\nœuvres\naméricains\nrelations\npeau\nmoteur\naugmentation\nsuivi\nvolonté\nbeau\nbancaire\nlaisser\nbureaux\nprincipalement\nintéressant\nlogiciels\nsommet\nvivre\nélevés\nRobert\ncontrats\noublier\nperformance\nréponse\nconcept\nobtenir\nposte\nattendre\nlignes\nconsiste\naugmenté\nvert\nfigure\ndéveloppé\nmagasins\ncollaboration\nrépondre\nholding\nlivres\nconvient\nfonctions\nfera\npouvait\nmillion\nPaul\nbritannique\nvoix\nGrande-Bretagne\ndisque\naffaire\nminutes\nquelle\ncontexte\nlimite\nmains\ncommun\nréduit\nPourquoi\nparticuliers\nverre\nwallon\nallemand\neffets\nChine\nmeilleurs\nrend\napplications\nprocédure\ndevait\nprofit\nméthode\npose\ncommence\nidée\ncréé\nnuit\nNord\ncapitaux\noptions\nconsommateur\ncartes\nmétier\nprobablement\naller\nfacile\nInternational\nimportantes\nMarc\ncapitale\ndevise\nprochaine\ntransport\nStreet\ndemander\nutilisateurs\nimage\npropriétaire\nfacilement\npubliques\ncroire\ndisponible\nLouis\nveulent\nCharleroi\nconsommateurs\ndevises\ndifficultés\nsort\nnational\nmachines\nannoncé\nchoisi\ndécouvrir\nsoutien\navez\nperdre\ncuisine\ntelles\ntravaille\nouvert\nphase\ncertainement\ntélévision\npratiquement\nannuel\nbord\npaiement\nBank\ninstitutions\nseuls\narrive\nconstate\nmarques\nnationale\nregard\nreprésentent\nBelges\nétat\nlibre\nrachat\nToutefois\nportes\nsortir\ncommandes\npermettant\nmanager\nfiscal\ncinéma\nhistoire\nzone\nsauf\navantages\nvoici\neffectivement\npuisse\nréel\npuissance\nfixe\nBelgium\ncontact\népoque\nrythme\nprincipaux\nvendu\nutilisé\nétude\nLeur\nsensible\nBref\nrencontre\nspécialistes\nbrut\nmauvais\nnéerlandais\nsupplémentaire\nmots\nreprises\nnécessaires\nsoir\nPrix\nmachine\npenser\nparts\ncomprend\nfusion\nacquis\ntotale\nvoyage\nlogique\nconcurrents\nidées\ntrouvé\ndette\nréellement\nfinancement\ndisponibles\nvieux\nlance\nmarge\ndirigeants\navis\nchanger\nconséquence\nsociales\nsupérieure\nCertes\nfaisant\nordinateur\npartenaire\nwarrant\nfabrication\nredressement\nsuffisamment\ndélégué\npourront\npoursuit\nchemin\nemplois\nréalise\névolution\nCour\nautomobile\nPremier\nancien\nnote\nparties\npension\nprofessionnel\nassure\ngarder\nRien\nActuellement\nest-il\nclimat\nSICAV\ndépartement\nsept\npartout\nimmobilier\nlancement\nrating\nréussi\npatrimoine\nexpérience\nAnvers\nanciens\ngraphique\nFortis\nfaveur\nretrouver\ndroite\nresponsabilité\ncommande\nKredietbank\ndirect\nutiliser\ntonnes\nconnaissance\nacheté\naméricaines\nclairement\nsemblent\nbiais\nfutur\nneuf\nchance\nfaillite\néquipe\nmusée\ncompagnies\ndocuments\npertes\nsortie\nseraient\nchoisir\ntellement\nindustriel\nprécompte\nimmédiatement\navantage\nconstituent\ndéchets\nsport\ndemeure\ngarde\nmaisons\nSolvay\nconséquences\nactive\ndépenses\ndonnent\nemployés\nsites\nélections\ndétient\nobligation\nfruits\nvéhicule\nConseil\ninvesti\nmission\nprofiter\nvisite\ncomprendre\nprofessionnelle\naffirme\nWall\ncharges\nprivée\nrares\nsuccession\nliberté\nrentabilité\nsuivant\nefficace\nassurer\nimages\nagences\nimpossible\nJohn\nenfant\nfournisseurs\nphoto\nsalaires\nAvant\ncompter\ndisposition\nformes\nbénéficiaires\nlesquels\nmaintenir\nprécisément\ncouple\nenregistré\nrecul\noffrir\npeur\nhauteur\ncentres\nvoulu\nindustrielle\npositif\nadministrateur\nintéressante\ncommerciale\ninterne\npleine\npassant\nvision\nfaits\nretard\ncertes\nlundi\nOutre\nporter\nécrit\ncesse\nlocaux\ndélai\ntrouvent\nclassiques\ncommencé\nréalisée\nAlain\nvigueur\ngagner\nCelui-ci\nPhilips\nceux-ci\nfavorable\npouvoirs\nparticipations\nannonce\ngénération\nélément\ndevenue\ntouche\nconseils\ndevoir\nsouligne\nrespectivement\nrapports\nvacances\nlieux\nnaturellement\nstatut\nceci\ndestiné\ndéfaut\nobjectifs\nrécente\nsaison\nindustriels\nSuisse\ncatégorie\ncomplexe\nhuit\nfisc\nobtenu\nrepris\noccupe\nsérieux\némis\nQuelques\ncomportement\nlimité\nvingt\nconjoncture\ngauche\nmarche\nordre\nmobilier\nparcours\nperspective\nnormes\nrecours\nCommunauté\nannuelle\nlecteur\nobjets\nfabricant\nniveaux\nEntre\nréalisation\namateurs\nconséquent\nprésenter\nCelle-ci\nvise\ntypes\ndétail\nmauvaise\nprofesseur\nprogressé\nsigne\npassée\napproche\nReste\nreturn\njardin\nflamand\nNamur\nbilan\nsensiblement\nTrois\nutilise\ncommune\ndimanche\noption\npartis\nanalyse\nfilms\nsurface\nwarrants\nprises\nsecret\nhistorique\njournée\nPendant\nallemande\nAndré\nfille\nproposer\navions\naugmenter\nparc\nDelhaize\nLors\nlimitée\nappareils\nvilles\nau-dessus\ndiminution\nprochaines\nservir\nBernard\ncommission\nfaiblesse\nplus-value\nsouhaite\ninternationales\nproducteur\nproducteurs\ncode\nbelles\ncabinet\nfonctionnement\ngérer\nmouvements\npratiques\nrégions\ndossiers\nmeilleures\nParce\nentrée\nvendredi\nactif\nsociaux\nsupplémentaires\ncafé\nmessage\nphysique\nSociété\ncommunes\ndizaine\nfaute\nsélection\nsource\nfacteurs\nmilliers\nsoleil\ntirer\nconcernant\nBourses\nfallait\nsentiment\nbénéficier\ndébat\nélevée\nouvrage\npolice\npouvez\nattention\na-t-il\nconstructeurs\ncontribuable\nmoderne\npassion\nprimes\nsuit\nauquel\ndépasse\nspécialisée\nbruxellois\ndéclaration\nmultiples\nquartier\nvidéo\ndépend\nliquidités\ncorrection\ncomité\ncherche\nfiliales\nSous\nsigné\nleader\ncalcul\nRens\nartistes\ndéficit\ncadres\nfédéral\nprobable\nremboursement\nefforts\nrestaurant\nToutes\ncouverture\ndomicile\nsoins\ndevront\nluxe\ncomplet\ndanger\nindispensable\nsyndicats\ncomporte\nfaite\njuridique\nlangue\nrendez-vous\ndemandé\nrespect\ncontinuer\nlesquelles\nlocal\nrare\nrestructuration\nautomatiquement\nplat\nboursier\ncotées\ndécide\nCependant\nCertaines\nmatériaux\nordinateurs\ntradition\nprogressivement\ncapable\nclasse\nfamiliale\nréserve\nfonctionne\nsolutions\nfabricants\npaie\nFinances\nréelle\nchangé\nmasse\nunités\nconsidéré\nauront\nnoms\nriche\nPatrick\nproposé\nsalon\nterritoire\nfixé\nmagasin\ncandidats\nmarges\nasiatique\ninférieur\nréaction\nfleurs\nrecord\ntribunal\nrecettes\npoursuivre\ndessous\nportant\nAussi\nSabena\nacteurs\ndehors\nconstructeur\nrelation\noffrent\nspectaculaire\nproduire\nconfort\nfamilles\ninvestir\nreprend\nsert\nmontrer\nmérite\nplaces\nSoit\njudiciaire\ntextes\nquasi\nSNCB\njeux\npermettra\nétudiants\nmembre\nphotos\npositions\nCockerill\nlendemain\ncent\ngagné\njaponais\nmark\npointe\nsolide\nVoici\nanglais\nprésentent\ndécisions\nlégislation\nmédias\nvictimes\nécran\nnécessairement\ndécouverte\nclub\nenvironnement\nnoter\ncrée\nexportations\nnégociations\nrépond\nentier\nbusiness\npeinture\nvoisins\nfaibles\nlocation\nnord\npromotion\ntechnologies\nauraient\ncaisse\nentend\nsimples\nmaladie\nmenu\nchances\ncommerciaux\nprintemps\nBenelux\nposer\nAsie\nusage\nactionnaire\nprennent\nrésistance\nsurprise\nEtats\nmariage\nnécessité\nPuis\ncote\nPlusieurs\nbeauté\nexclusivement\nlettre\npayé\nrendu\nsoftware\nutile\ngestionnaires\nbénéficie\nprocédé\nvaste\ncrois\nnormal\nCentre\nconstruire\ndémarche\nemprunts\nnaissance\ndistance\ntourner\nClub\nattendant\nquantité\ntourne\najoute\nbancaires\najouter\ngéant\nautomatique\nfaux\nattend\nlitres\nprésenté\nargent\nconfirme\nindépendants\nénorme\ndestinés\nvéhicules\nressources\nstandard\nauparavant\nconstruit\nQuelle\nprincipales\ndisposer\nglobal\nécoles\nQuel\nréputation\nfameux\nrappelle\nconseille\nheure\nveille\ndifficulté\nlimites\ncommerciales\nsamedi\npalais\nvend\nTractebel\nconnaissent\nreprendre\nvillage\nemploi\namis\nbudgétaire\ncroit\nmises\nsouci\ncontient\nhabitants\nWeekend\nbras\nbeaux\nbruxelloise\nfaisait\nintroduit\nintérieur\noutils\nprécis\nchercheurs\ntaxe\nsalaire\ntransactions\nChristian\nchambre\nportée\nréflexion\nhasard\nmatin\nassureurs\nréforme\nBeaucoup\nfournir\nrecherches\nliés\ntenue\nproposent\naide\nferme\nsecondes\nCGER\ncontenu\nquotidien\nflamande\ncentaines\ncourse\nbillet\ncritique\nnaturel\nprincipale\nsupport\nweek-end\nDehaene\nGand\nchargé\néconomies\naugmente\nguide\nproposition\nlaissé\nspécialiste\nfrancophones\nimportance\nvent\nconception\npréférence\nspectacle\navenir\ngrave\ncommencer\ndiminuer\nchercher\nbonheur\ndizaines\nexactement\noutil\nscénario\nJones\ncoups\némissions\néventuellement\nRoyale\nsoumis\nlecture\nmonter\nGrand\ncentral\nexigences\nassuré\ncontacts\nconsacré\nfaut-il\nréussite\néchéance\nrecevoir\ntableaux\narriver\névident\nItalie\namélioration\nauteurs\nestimé\nquinze\nRussie\ndemain\nprécédent\nvendeur\névénements\nautrement\nexperts\nfortes\nfurent\npossibles\ncirconstances\nplacer\npublication\nréserves\nsauce\nvenu\nCharles\ncollaborateurs\nimplique\nobligataire\nétabli\nCD-Rom\nforcément\nremarquable\nClaude\ntourisme\ninternationaux\ndirecte\ncompétences\nconseiller\nfacteur\nplastique\nrarement\nRoyal\naffiché\nlutte\nrelative\nactuels\nenvie\nministres\nsecrétaire\ncapitalisation\nlangage\npositive\ncirculation\nconvaincre\nnotion\nvisage\nvouloir\najoutée\ncaractéristiques\nEric\nUnion\npaix\ncourrier\ndisposent\ndéveloppe\nprésentation\nbarre\ncomparaison\ndéterminer\nfirmes\nfournisseur\ninformatiques\nluxembourgeois\nachats\nsolde\nSerge\nglobale\npropriété\nstratégique\nRenault\npartage\nporté\nsources\nKong\ncour\ndestinée\nabsolument\nbranche\nouvre\nplans\nproductivité\nRésultat\naméliorer\njoué\nParlement\ndépit\nfichiers\npersonnalité\nconstitué\ngestionnaire\nné\nprofession\nqualités\nconscience\nmédecin\ncelles-ci\ndesign\ndécor\nfaudrait\nparticiper\nappelle\nforces\nsuisse\nappareil\nconduite\nlongueur\ntarifs\nvérité\nlien\nlocales\nfrancophone\nclubs\ncorrespond\ncoupons\nestiment\ndéfi\nprotéger\nréalisés\nméthodes\nrevenir\nsuperbe\nvolontiers\ndocument\nnommé\ntente\nfinancer\nscientifique\nGeorges\ntravaillent\nlié\nzones\naime\nlettres\nouverte\nHong\nmurs\nphilosophie\nrappeler\nutilisés\nsuivante\nreprésentant\ntraduit\nremettre\nsitué\ndifférente\nlongs\néconomie\ndiscours\ndistributeur\ndomaines\nrégional\nfaites\nitalien\nrestera\nusine\nGroup\npersonnage\nportent\nattendu\nJean-Pierre\narticles\nchangements\nfallu\nléger\nmener\npropriétaires\nspécifique\nrécupérer\nvoyages\nprocéder\nlocale\nmédecins\nprivés\ntransmission\nconcurrent\ncourte\nquart\nbaisser\npieds\npublié\nFord\nmenace\nréunion\ntransfert\ncomposé\ndimension\npersonnages\nralentissement\nconclusion\nagents\nparfum\nrémunération\ndifficiles\nmettent\npierre\nproches\nréglementation\nsalles\ngrimpé\nprochains\nprévue\nélectrique\ndynamique\nexposition\ninstallé\nplancher\ndistributeurs\ndéclare\nconnue\npréparation\nréalisées\nbeurre\nopérateurs\nachat\nprovince\nspécifiques\nAlbert\nrenforcer\ntéléphonique\ncomptable\neffectuer\ntrafic\ndegré\ndéfinitivement\nhumain\noptique\nremarque\ntalent\nappelé\nmodifier\ndéfinition\npeintre\nrespecter\nstade\nstatistiques\ncertificats\nlimiter\nlivraison\nplacements\nraconte\nvolumes\nimmobiliers\nanciennes\nchevaux\nmédicaments\nPeter\nfeuilles\nfootball\nidentique\npouvons\nremise\nstructures\ntenter\naccords\ncotisations\nindice\nneutre\nconstituer\nmontrent\nplacé\nloyer\nproximité\nvoient\népouse\nCanada\nentrer\npostes\nprécision\ncité\nconcours\npatrons\npopulaire\npétrole\nnégatif\nallemands\nroman\nvictime\nitalienne\nménages\nrepas\nPetroFina\nlangues\ntendances\npire\nprudence\nsavent\nNéanmoins\nconduit\nmille\nrénovation\négard\nAméricains\nexercice\navance\neffectué\nfortune\nfournit\nlecteurs\nMorgan\ndécouvert\ndifférent\nemploie\nbleu\nroyal\ntechnologique\ntélécommunications\nAmsterdam\nfiscales\nindique\ninformation\nlourd\nsignal\nMieux\naider\nancienne\napporte\nnette\nprestations\npublicitaires\nsensibles\ncommunauté\nvolatilité\nétape\nassurance\nlancée\nrésoudre\ngaranti\nmodification\nrevue\nspéciale\nchacune\ndifférences\nmessages\npriorité\nrecommandation\nrécent\ncharme\ndividendes\nOlivier\npassent\nfinale\nimmeubles\nlogement\npourcentage\nrire\nstabilité\ndifficilement\ndéfense\nmagazine\neaux\njeunesse\ncontinuent\nrévolution\nétonnant\norganisation\nconstater\nemprunt\néditions\nDaniel\nutilisée\ncompartiment\npublicitaire\narticle\nbande\ncapacités\ncentrales\nconsidérée\nmilieux\noccasion\nquasiment\npouvant\nVermeulen-Raemdonck\nvisiteurs\nchambres\nconsidérablement\ndemi\ndécouvre\nessentiel\nbroker\ndettes\nmardi\nreconnaissance\nsalariés\nformules\ngrosse\nheureux\nperd\nradio\nallait\nmultimédia\npartiellement\nseules\nGérard\nSecurities\ntoucher\njugement\nconsidérer\nremplacer\ncouvrir\nprécieux\nsegment\ndessins\nespace\nindices\nrefuse\nchefs\nexemples\nrejoint\nspécialisé\nobjet\nprécédente\nrose\nversions\ndestination\nEncore\ndeviennent\npersonnelle\nplats\nvingtaine\nvirus\nFaut-il\nchasse\nlongues\nToute\nbases\ncotée\nfinal\nmonnaies\ntravaillé\napporter\naspects\ndisparu\nDavid\nManagement\nport\nracheter\nrelever\nCelui\ncatalogue\ncentaine\nchaleur\nprofil\nreprésentants\nconclu\nréside\nscientifiques\nChambre\nsecondaire\nserveur\nXIXe\nexige\ngrimper\nimmeuble\nmontants\npaysage\nvendus\nassurances\ncatégories\ndure\ndécote\nsoutenir\nédition\ndangereux\nagréable\nvoulait\ncombien\ndisparition\noptimiste\nplus-values\ntomber\nerreur\nsituations\nspécialisés\nsubi\nsuivent\nclassement\nnorme\nrentable\nsang\nsocialiste\ntombe\nJustice\nattitude\nmines\nliée\nplantes\nvague\nGeneral\nlégumes\nCeux-ci\nconflit\nexcellent\nlicence\ntravailleur\nappris\nest-elle\ngagne\nmari\npréparer\npurement\nsituée\nvérifier\nJean-Luc\ngain\nmétal\nsurfaces\ndouze\nexpliquer\nmeubles\nchaussures\ncréée\ninstitution\nsolidarité\nMaastricht\nbasée\njournal\nsoin\nsourire\nGuerre\nbouteilles\nflexibilité\nmaintient\nappartient\nmoments\nrouges\nbasé\ndevons\ninstallations\nBacob\nassociation\nformat\nCity\nPage\ndisques\nmodem\nmélange\nordinaire\nvide\nchimique\ndisent\npharmaceutique\nnumérique\nporteur\nrépartition\nblanche\ncomposants\nfuture\nparvient\névoque\nDurant\ncalme\nElectrabel\nculturel\ngrosses\nbaissé\nlois\nmoteurs\nprincipes\ntrente\néventuelle\nprévoir\ntours\nPentium\nacheteur\ndimensions\nfonctionnaires\norganisé\nrencontré\nrusse\nsavoir-faire\nétablissements\nFédération\nToujours\ncréativité\napplication\ndépasser\nimporte\njaune\nmarqué\nmécanique\nsocialistes\ntranche\nQuelles\nenvisage\ntraiter\nSurtout\nacheteurs\nchinois\nclaire\nvécu\nObjectif\nbail\ndemandes\ndiversification\nmontré\nrenseignements\nsouscription\nTokyo\nentendre\ntests\nSiemens\nfilles\nunité\nBekaert\ncomposition\nresté\nsinon\nagence\nfini\nmodifications\nCash\nindustrielles\nobtient\npermanence\nrestaurants\nréels\néchange\nflorins\nterrains\némergents\natouts\noffrant\nbouche\nchamp\nchaud\nmonte\npreneur\nprésents\nquitte\ntarif\nfacture\nfiscaux\nmodeste\nprocesseur\nFund\navenue\ncompétition\nrelevé\ntenté\nEst-ce\nMusée\nbijoux\ndifférentiel\ndéclaré\ninstitutionnels\ntraité\nIntel\ntraditionnels\nvictoire\nconnus\ncorrectement\nDominique\nTant\naccessible\nrencontrer\nstocks\nespérer\njouent\nmenée\nnécessite\nprovenant\nutilisent\naffichent\ndélais\ninférieure\nsent\nspécial\nAmérique\nacquérir\nalbum\nidéal\nvéritables\nassocié\ncandidat\nconnaissances\nsignes\ncheveux\nconserve\nstress\ndirecteurs\ndonnée\nendroit\ntraditionnelle\nMartin\nciel\nconvention\nobligataires\nprouver\nEspagne\nPetit\nSource\ndessin\nhumaine\nlait\nSeule\nThierry\nboursiers\ncontinent\ndestinées\nflamands\nnéerlandaise\npensions\ncommencent\nconsidérable\nnationales\nconjoint\ncrédits\nmilitaire\nmorceaux\nprivatisation\nrepose\nsommeil\ntraditionnel\nSeul\ncapables\ncombat\nfinances\npuissant\nBill\nRenseignements\nphysiques\nRichard\nallant\ncréations\ntoile\névidence\nconvaincu\nexcellente\nretraite\nthéorie\ntransformer\nTour\ntransaction\nvisant\nDeutsche\nMons\nattentes\ncycle\ndétails\nVotre\nhéros\nsérieusement\nCeux\nconsidération\nimpose\npropositions\nAutrement\nforts\nusines\nAfin\nQuels\naisément\nressemble\nrisquent\ntotalité\nimaginer\noriginale\nintégré\nintéressantes\nloyers\nauxquels\ncircuit\nindépendant\nintérieure\nmaintien\ncotisation\nmoyennes\nquitter\nstable\nCompaq\ngalerie\nliens\nsouffle\napprendre\nconcert\nliquide\nnoire\ntempérature\ntransparence\nécole\nchampion\ndiminué\ndésir\nressort\nvoulons\néquipé\nalimentaire\norganisations\nprésidence\nraisonnable\nratio\nrecommande\nutilisant\naccepter\naccepté\ncache\nchocolat\nchuté\ncomparer\ncourts\nfigurent\npassagers\nprison\nviande\nassociés\nesprit\nfroid\njeudi\nliées\nrevu\nsatisfaction\nsatisfaire\ntest\ntiennent\nvraie\ncontrairement\ndépassé\nextérieur\nAmerican\nEtat\ncomplémentaire\ndéclarations\nréactions\nFonds\nartiste\nconclure\ndéduction\nremis\ndéterminée\nfiscalité\ngrand-chose\nhumaines\nréponses\néquipes\nMichael\nSystems\naspect\ncommercialisation\nmanger\nRTBF\nengagé\nobligé\nproportion\nsignature\nétranger\nimposé\nsilence\nvote\nAfrique\nMobistar\ncible\ncontemporain\nfondateur\nJean-Claude\ncommuniquer\nexistent\nmajeure\nouvrir\nélectroniques\ncompétitivité\nerreurs\nnotation\nrang\nApple\naccident\ncertificat\nexceptionnel\nhttp\nproprement\nriches\nBarco\nQuoi\nviolence\nadapté\nbénéficient\nrécession\nsentir\narmes\narrivé\ncrainte\ngaranties\nménage\nofficiellement\nouvriers\nAutant\ndiscussion\nrejoindre\népoux\ncitoyens\nconcernés\ndéfinir\nParibas\nTelecom\nfabrique\nferont\nnée\noblige\npatients\npensent\nresponsabilités\ndoublé\nfraude\norganise\nHenri\nconclut\ndésire\nlégislateur\nécrans\nchoc\ngratuit\nmobile\nnaturelle\ndialogue\nrévision\nfamilial\nlourde\npoche\ndécider\nnégociation\ntort\nMaison\nTrésor\nconstante\ncotation\ndéterminé\nmanagers\nopté\ntransformation\nLife\nanniversaire\ncompétence\ngéographique\nmandat\nréservé\nétablir\nBusiness\nfins\nrichesse\ncommente\nintermédiaire\nretrouvé\nsciences\nbanquier\nformer\nmonté\nparfait\nveux\nRené\ninvestit\nparvenir\nvieille\ncollections\ndirige\nfonctionner\nmauvaises\ntapis\nvenus\nContrairement\nSuez\npiste\npistes\ntensions\ncampagnes\ninvestis\nproposés\ntabac\nbataille\nbritanniques\nfine\nliégeois\npartenariat\nprivées\nremplir\nsupérieurs\nBeaux-Arts\nlaser\nrestauration\nDutroux\nchimie\nrendent\ntextile\nBrabant\nColruyt\nJames\nNational\nQuatre\npréalable\nsouvenir\nvenue\nCommunal\navocat\ncomparable\nconsolidé\ncritiques\ninterdit\nmine\nquotidienne\nrigueur\nréduite\ntissu\nInvest\npain\nparticipants\nprocédures\nprofondeur\nretrouvent\nrues\ntaxation\nMexique\nasiatiques\nconducteur\ndemandent\nenvirons\nfermeture\ngris\nrumeurs\naccueille\namoureux\ndéfendre\npure\nsouffre\ncréneau\njournaux\nseuil\nJeux\nOffice\nauteur\ncash-flow\nfichier\ninstruments\nquelles\nséance\nvéritablement\nYves\nattirer\ncivil\ncivile\nstation\ncourbe\nhectares\ninfluence\ningénieurs\ntables\nvivent\nExemple\nblancs\ncouche\ncuir\ndevenus\nextraordinaire\npatient\npeux\naient\nanimaux\nassociations\nfoie\ninitiative\npoursuite\nsurvie\nFace\napparemment\nconsultant\nexpansion\nséjour\nchampagne\ncommentaires\ncomplexes\ncylindres\ndécennie\nrendements\nretenu\nsais\nsujets\ncuivre\noffert\nréagir\nvarie\nFondation\nartistique\ncommunications\nmonétaires\nmétaux\npermanente\npositifs\nélectriques\nbasse\nconcentration\ninvestisseur\nprovoqué\ndoux\nstations\ncoin\nmodifié\navocats\nestimations\noriginal\nsouplesse\nAttention\nFrank\nHainaut\nSuite\nannuels\ncellule\nclause\nexemplaires\nmalheureusement\nminute\nnormale\nFrédéric\nSud-Est\natout\nlatine\nlogements\npilotes\nsusceptibles\nRoger\nXVIIIe\nordres\nremarquer\nactuelles\nbouteille\nconstat\nopportunités\nprépare\nvendeurs\naccrue\nfruit\njugé\nloisirs\ntrentaine\ngendarmerie\nalimentaires\ncoté\nmodernes\npréciser\nréussir\nlaissent\nparfaite\nspécialement\névoluer\nDewaay\nDésormais\nGroupe\nmaladies\nnégligeable\ntension\nLion\nchansons\ndite\nfestival\nnégative\npréféré\nrestant\nCera\nadopté\ncoopération\ndistingue\ndouceur\nretirer\ntechnologiques\nEditions\nParfois\nbruit\ncomptant\ndémocratie\nexception\nmercredi\noffres\nsucre\nvedette\névolue\nBritish\nLeurs\ncompromis\nhauts\nélevées\némission\nFaire\nattendue\nlourds\nquels\nsoirée\névénement\nalternative\nchimiques\nconférence\nquitté\nserveurs\nBrésil\nCD-ROM\ncorrespondant\nlocataire\nmatériau\npériodes\nutilisées\nmorale\néquilibre\nSony\nfixer\ngratuitement\ntrait\nTrop\nadultes\nconsacrer\nnormalement\nparole\nprochainement\nsuscite\nverra\nclé\nmesurer\nnotes\npotentiels\nrelatives\nFlamands\nFrancfort\nPalais\nPlan\nRépublique\ntransports\nPortugal\ncouvert\njoueurs\nMalheureusement\ncoupe\ndispositions\neffort\nendroits\naides\ncontribution\ninsiste\nsouhaitent\ncommunal\nimpact\nprogresser\nSambre\nadministrateurs\ndeviendra\ndégager\nformations\nsouscrire\ncellules\nfacilité\ngras\nmilitaires\npassés\nquinzaine\nsouvient\nautomobiles\nbref\nconfortable\nessentielle\nofficiel\nvive\nvols\nMarcel\ncombinaison\ndistinction\ndéfinitive\njaponaise\nliaison\ntissus\ncadeau\ncanadien\ndistribué\nexistants\nordinaires\nservi\nsurveillance\nmédecine\nrevoir\nrécentes\nvoies\nRappelons\ncomptabilité\nfabriquer\nfasse\nintéressants\npeintures\nquartiers\nvalable\nétapes\nbénéficié\ncouvre\ndiminue\nenvers\nintroduire\nmissions\nPetrofina\napparition\ncoffre\ndigne\nfibres\ninitiatives\nlittérature\nrembourser\nretrait\nBundesbank\nPascal\nPologne\nconsacre\nemployeur\nfavorables\nmanquent\nassurée\nbattre\nchantier\nconclusions\nconsulter\ncraindre\nvivant\nChacun\ninternes\napprend\nliégeoise\nobserve\nprovenance\nsortes\nMarie\ncessé\ncéder\nestimée\nmarchandises\nPoste\nbalance\ncopie\ncuisson\nnégocier\nspéciaux\ntraite\nBruges\nhollandais\npeut-on\nporteurs\nrégler\nsoutenue\nsuivie\nStanley\naccueillir\nmédical\nnotoriété\nprovoquer\nsensibilité\nvocation\nimpression\nséduit\nconflits\nimposable\njournalistes\nmanifeste\nprovoque\nwallons\néditeurs\ncanal\nfondamentale\nfuturs\ngraves\nmené\npommes\nracheté\nremonte\nsolides\nsuffisante\nchargée\nchers\ndiscussions\ngarantit\nindicateurs\nprovient\nsoutenu\nsportif\nsystématiquement\nzéro\ncomptent\nrecette\nrécit\nsubir\névolué\nJohan\naccorde\nfaciliter\nhausses\nMacintosh\nServices\ndébuts\ngarantir\nportefeuilles\nsusceptible\nuniversités\nGlaverbel\nSotheby's\nactes\nbrasserie\ncaractéristique\ncherchent\nfavoriser\njustement\nprudent\nstock\néchelle\nénormément\nStandard\ncompose\ncouronne\nexceptionnelle\nflux\njustifier\nréfugiés\ntéléphoniques\nMonsieur\nVille\naccepte\ninspiré\npollution\nsituent\nallemandes\nboissons\ndouce\ngouvernements\nintervention\nmotifs\nprimaire\nWorld\nentrepreneurs\nreprésentation\nThomas\napparaissent\ncomplémentaires\ncycliques\nfranchement\ninstrument\nrayon\nFood\nconversion\npartager\nretenue\nsimplicité\nComité\nconfirmé\ndevaient\nexpériences\nfront\njeter\nlogistique\nreconnu\nAffaires\nHeureusement\ncomédie\nhistoriques\nimposer\nobligatoire\nrecourir\nréférences\ntraces\ntémoigne\nJava\nacte\nappliquer\ncatastrophe\nconduire\ncontribué\nfais\nintervenir\nmettant\npilote\nplafond\nremplacement\ntire\nBerlin\nVincent\nportable\nprofonde\nrefusé\nrepos\nbéton\nfermé\njuges\nparlementaires\nprévention\nDonc\ndispositif\nforment\nneige\nsuffisant\nLouvain\ndiffusion\nfédération\nlentement\nprenant\nsouris\ncontenter\ndouleur\nintervient\nlook\nmanœuvre\nparquet\npoussé\narguments\nbillets\nconsacrée\ndirigeant\ndécoration\nholdings\njustifie\nlevier\nmajeur\nmidi\nrecyclage\nrobe\nEntre-temps\nappels\ndirective\ninitial\nintéressés\npousser\npouvaient\nsecrets\nsurpris\nunivers\npoisson\nspécialisées\nséduire\nverser\ngénérations\nnettoyage\nouverts\nréductions\nvélo\nAnne\nCompagnie\nSouvent\nexplique-t-il\nofficielle\nrésolution\nService\ncourses\npari\npousse\nrevendre\ntrace\nabonnés\ncraint\ncroissant\njuger\nrégionale\nsymbole\ntouristes\nRome\nactives\ncommunautaire\ncontraintes\njournaliste\ntraditionnelles\nvariable\namour\natelier\nbudgets\nbudgétaires\nclef\ndétriment\nnationaux\npaquet\nrelatif\nFrancis\nRupo\ndiesel\ngare\nparlent\nrapporte\nregarder\néventuel\nClabecq\ncarrés\npsychologique\nrupture\ntéléphonie\nDanemark\nSauf\ncitoyen\nfour\npermettrait\npuissent\nrapides\nMarketing\nTendances\ndit-il\ndéveloppements\nenregistre\nenvoyé\nintermédiaires\nliquidité\nréagi\nAllemands\nLouise\nconnues\nconsolidation\ncréateur\nidéale\nprofité\nprévus\nrésulte\nsimilaire\nBoeing\nDidier\nDieu\nWilly\nagir\ncoins\nconstaté\ndanse\noccidentale\noptimistes\npensée\nprofessionnelles\nComputer\nTournai\nappliquée\nchanson\ndéroule\nfranchir\nliquidation\nmorts\nnouveauté\nprestigieux\nsuppression\nLaurent\nMercedes\nexistantes\npleinement\nsimultanément\nétablissement\ncercle\ncorruption\ndiscipline\nfamiliales\nlaboratoire\nlivrer\nmontée\nparticipe\nPersonne\nadresse\nfinance\ngénie\nleasing\nversement\nbits\nconcernées\ndents\ninclus\nmaximale\nprécédemment\nroutes\nvariations\néquipements\nDeclerck\nchemins\nconstituée\nglobalement\nlibres\nproposant\nsouligner\nambitions\ncroissante\ndécennies\nlittéralement\nmotivation\nrubrique\nsouvenirs\nsurprises\nvendue\nCelles-ci\nbébé\nplainte\nstockage\nécrire\nénergie\nSpector\nannonceurs\ndébats\nferait\ngrain\nsont-ils\nséparation\ntournant\nvendues\nCompte\nCools\nVolvo\naccessoires\nconstitution\nconsultants\ndommages\noccupé\néchanges\nSeconde\nadresses\nefficacité\nfixée\nfrappe\nmonopole\npanneaux\nrestée\nsentiments\nterminé\nutiles\nBruno\nSeuls\nappliqué\ndonnant\nfondamentaux\nfréquemment\nmétiers\nplanche\nroyale\nsuppose\nMoins\nfourni\njaponaises\npayés\nprofond\nprogrammation\nrésolument\ngolf\npoudre\n"
  },
  {
    "path": "mocodo/resources/lorem/fr5.txt",
    "content": "encore\ngroupe\ndepuis\ncontre\nfrancs\nautres\ncompte\nniveau\npartie\nhausse\nvaleur\nBourse\ntoutes\nnombre\ngrande\npermet\nchaque\nFrance\njamais\naction\nbaisse\nrisque\nbanque\nmoment\nheures\nbelges\nseront\nraison\nDepuis\nquatre\nsemble\nserait\nprojet\ngrands\npoints\nEurope\nmesure\npublic\npartir\nautant\nmettre\ntrouve\nmaison\nsimple\npetite\nsavoir\njeunes\nBanque\nclient\nsommes\nventes\ndollar\npetits\naurait\nchoses\ntandis\nexiste\npropre\nmarque\ndevant\npasser\ndurant\nfemmes\nautour\ncentre\nvendre\nbesoin\naucune\nhommes\ndonner\ntitres\nmoyens\nbureau\nestime\npourra\nfaible\ndroits\nMichel\nmanque\ncharge\nnature\nsecond\nactuel\nlequel\nchacun\ndouble\ncelles\npapier\ntermes\npermis\nguerre\nrendre\nunique\nsuffit\nsoient\nPierre\npresse\nlongue\nrevenu\nretour\ntaille\nparler\npropos\nsuivre\npreuve\nsocial\nbonnes\ndivers\nbudget\nmontre\nrester\nfaudra\nChaque\ndevenu\nrapide\nmilieu\npatron\nactifs\naccord\nlancer\nproche\nvolume\ncoupon\nnouvel\nchange\nlaisse\nmoteur\nsommet\nRobert\nlignes\nfigure\nlivres\ndisque\nquelle\nlimite\ncommun\nwallon\neffets\ndevait\nprofit\ncartes\nfacile\ndevise\nStreet\ncroire\nchoisi\nperdre\ntelles\nouvert\nannuel\narrive\nregard\nBelges\nrachat\nportes\nsortir\nfiscal\npuisse\nrythme\npenser\nfusion\nacquis\ntotale\nvoyage\nCertes\nchemin\nancien\nassure\ngarder\nclimat\nrating\nAnvers\nFortis\nfaveur\ndroite\ndirect\ntonnes\nchance\npertes\nsortie\nSolvay\nactive\nfruits\nvisite\nimages\nenfant\nformes\ncouple\noffrir\npleine\nvision\nretard\ncertes\nporter\nlocaux\ngagner\ntouche\ndevoir\nstatut\nsaison\nSuisse\nobtenu\nrepris\noccupe\ngauche\nmarche\nnormes\nobjets\nreturn\njardin\noption\npartis\nprises\nsecret\navions\nvilles\nservir\nbelles\nsource\nsoleil\npolice\npouvez\nprimes\nauquel\nleader\ncalcul\ncadres\nToutes\ndanger\nlangue\nclasse\nauront\nmarges\nfleurs\nrecord\nSabena\ndehors\nplaces\ntextes\nmembre\nphotos\npointe\nsolide\nentier\ncaisse\nentend\nlettre\nnormal\nCentre\ntourne\najoute\nattend\nlitres\nargent\nQuelle\nglobal\nfameux\nveille\nsamedi\npalais\nemploi\noutils\nhasard\ncourse\nbillet\navenir\nRoyale\nsoumis\nmonter\nItalie\nquinze\nRussie\ndemain\nfortes\nfurent\nplacer\nClaude\nnotion\nvisage\nfirmes\nachats\ndesign\nforces\nsuisse\ntarifs\nfaites\nlocale\ncourte\nmenace\nagents\nparfum\npierre\nsalles\nconnue\nbeurre\nAlbert\ntrafic\nhumain\ntalent\nremise\ntenter\nindice\nneutre\nvoient\nCanada\nentrer\npostes\nsavent\navance\nMorgan\nsignal\ncharme\nfinale\nDaniel\nbroker\ndettes\ngrosse\nallait\nseules\nespace\nrefuse\nEncore\nchasse\nprofil\nconclu\nvendus\ntomber\nerreur\nappris\nGuerre\nrouges\ndevons\nformat\ndisent\nfuture\nDurant\ntrente\nclaire\nfilles\nagence\natouts\nbouche\nquitte\navenue\nbijoux\nconnus\nstocks\njouent\nsignes\nstress\nMartin\nSource\ndessin\nrepose\ncombat\nallant\nvisant\nimpose\nusines\nloyers\nstable\nCompaq\ncourts\nprison\nviande\nesprit\naspect\nmanger\nouvrir\nriches\nsentir\nAutant\nferont\noblige\nfraude\nmobile\nlourde\nMaison\nmandat\nformer\ndirige\npistes\nchimie\nQuatre\navocat\nInvest\nOffice\nauteur\ncivile\ncourbe\ntables\nvivent\nblancs\ncouche\nsurvie\nretenu\nsujets\ncuivre\noffert\nclause\nminute\nlatine\nXVIIIe\nordres\naccrue\nDewaay\nGroupe\noffres\nlourds\nmorale\nparole\nPalais\neffort\nimpact\nSambre\nMarcel\ntissus\ncadeau\nrevoir\ncouvre\nenvers\ncoffre\nfibres\nPascal\nbattre\nvivant\nChacun\nsortes\ntraite\nBruges\nsuivie\nfuturs\ngraves\npommes\nmotifs\nThomas\ntraces\npilote\nBerlin\nsouris\nlevier\nmajeur\nappels\nverser\npousse\ncraint\npaquet\ndiesel\nLouise\nBoeing\nDidier\ncercle\nlivrer\ninclus\nroutes\nlibres\nvendue\nferait\nCompte\nfrappe\nutiles\nroyale\nfourni\npoudre\n"
  },
  {
    "path": "mocodo/resources/lorem/lorem.txt",
    "content": "aberat\nabesset\nabest\nabiit\nabire\nabit\nablatiuo\nabsens\nabsentis\nabsit\nabsolui\nabsolutus\nabstinentia\nabstinere\nabstinuit\nabstulit\nabsunt\nabsurdum\nabunde\naccedat\naccedere\naccedit\naccedunt\naccendit\nacceperit\nacceperunt\naccepimus\naccepisset\naccepit\nacceptam\nacceptis\naccepto\nacceptum\naccesserit\naccessit\nacciderit\naccidisset\naccidit\nacciperent\nacciperet\naccipiat\naccipienda\naccipiendum\naccipiet\naccipimus\naccipitur\naccipiunt\naccius\naccusari\naccusationem\naccusationis\naccusatoris\naccusatus\nacerba\nacerbum\nacerrime\naceto\nacetum\nachaia\nachillis\nacies\nacres\nacrior\nacris\nacriter\nacrius\nactae\nactiones\nactionibus\nactionis\nactis\nactoris\nactum\nacturus\nactus\nactutum\nacuto\naddere\naddidit\naddita\nadditis\naddito\nadditur\nadduci\nadductus\naddunt\nadduxit\nademit\nadempta\nademptum\nadeoque\nadeptus\naderant\naderit\nadesset\nadest\nadfectibus\nadfectus\nadferat\nadferre\nadfert\nadferunt\nadfici\nadfirmat\nadfuit\nadgressus\nadhibenda\nadhiberi\nadhibetur\nadhibita\nadhuc\nadicere\nadicies\nadicitur\nadiciunt\nadiecit\nadiecto\nadiectum\nadierit\nadiit\nadipiscing\nadire\naditam\naditus\nadiuuat\nadloquitur\nadministrationem\nadmirationem\nadmisit\nadmissum\nadmittere\nadmittit\nadmodum\nadmonet\nadmota\nadoptionem\nadortus\nadposita\nadquirere\nadquiritur\nadsentior\nadsequi\nadsidue\nadsit\nadsunt\naduenit\naduentus\naduerbium\naduersariis\naduersariorum\naduersarius\naduersis\naduerso\naduersus\nadulescens\nadulescentis\nadulteriis\nadulterio\nadulterium\nadulterum\naedes\naedibus\naedificare\naedificia\naedificiis\naedificiorum\naedificium\naedilis\naedilium\naedis\naedium\naeger\naegre\naegris\naegritudinem\naegritudo\naegro\naegrum\naegypto\naegyptum\naelius\naemilio\naemilius\naenean\naeneas\naequaliter\naeque\naequinoctium\naequissimum\naequitatem\naequitatis\naequius\naequom\naequore\naequos\naequum\naerario\naerarium\naere\naeris\naestas\naestatem\naestatis\naestimari\naestimationem\naestiuo\naestus\naetas\naetatem\naetatis\naeterna\naeternum\naethere\naetheris\naetolis\naetolorum\naetolos\naeuo\naeuum\naffectus\nafranius\nafricam\nafricanus\nafuit\nagam\nagant\nagas\nagatur\nagebatur\nagedum\nagendo\nagendum\nagens\nagentem\nagerent\nageretur\nagetur\naggere\nagimus\nagis\nagitare\nagitat\nagite\nagitur\nagmen\nagmine\nagnoscere\nago\nagricolae\nagrippa\nagris\nagrorum\nagros\nagrum\naguntur\naiax\naiebat\nait\naiunt\nalas\nalbam\nalbano\nalbis\nalbo\nalbum\nalcides\nalere\nales\nalexander\nalexandriam\nalexandro\nalexandrum\nalfenus\naliam\naliaque\naliarum\nalias\nalibi\nalicuius\nalienam\nalienus\naliisque\nalimenta\nalioquin\naliorum\nalios\naliquam\naliquamdiu\naliquanto\naliquantum\naliquas\naliquem\naliquet\naliquos\naliquotiens\nalis\naliter\naliubi\nalium\naliunde\nalius\nalma\nalpes\nalpibus\naltae\naltaria\nalteram\nalterius\nalterna\nalternis\naltero\nalterum\naltior\naltis\naltitudinem\naltitudinis\naltitudo\naltius\naltus\nalueo\nalui\naluminis\naluo\naluus\namabo\namans\namantes\namanti\namari\namas\namator\namauit\nambiguum\nambitione\nambitus\nambobus\nament\namet\namicam\namice\namicis\namicitias\namicorum\namicos\namictus\namicus\namiserit\namisit\namissa\namissis\namisso\namissum\namittere\namnis\namoris\nampla\namplectitur\namplexus\namplissima\namplissimis\namplius\nanalogia\nanceps\nancillam\nancipiti\nanguis\nangulo\nangusta\nangustiis\nangusto\nangustum\nanimaduertere\nanimaduertit\nanimae\nanimalibus\nanimalium\nanimis\nanimorum\nanimus\nannalibus\nanne\nannis\nannonae\nannorum\nannus\nante\nantea\nantequam\nantiochus\nantiquam\nantiquitus\nantiquos\nantiquum\nantonii\nantoninus\nantonio\nantonius\nantris\nantro\nanulum\nanus\nanxia\nanxius\naperire\naperit\naperte\napertis\naperto\napertum\napes\napibus\napii\napium\napollinem\napollinis\napollo\napparatus\napparent\nappareret\napparet\napparuit\nappellamus\nappellantur\nappellari\nappellata\nappellatione\nappellatus\nappellauit\nappello\nappio\nappius\napte\naptius\naptus\naput\naquam\naquarum\naquas\naquilae\naquiliae\naquis\naras\naratro\narbiter\narbitrabatur\narbitrantur\narbitratu\narbitrium\narbitror\narbitrum\narbores\narboribus\narboris\narborum\narbusta\narcadiae\narcana\narcu\narcus\nardens\nardentem\nardet\nardore\nardua\narduus\narea\nargento\nargentum\nargos\nargumenta\nargumentis\nargumento\nargumentum\narida\naries\naristoteles\narmaque\narmata\narmatis\narmatorum\narmatos\narmatum\narmatura\narmatus\narmenta\narmis\narmorum\nars\nartes\nartibus\nartifex\nartifices\nartificio\nartis\nartium\nartus\narua\naruis\nascendit\nasiam\naspectus\naspera\nasperum\naspexit\naspice\naspicit\nasse\nassidue\nastra\nastris\nastu\nathenas\nathenienses\natheniensibus\natheniensis\natheniensium\nathenis\natilius\natque\nátque\natqui\natra\natris\natrox\nattalus\nattamen\nattico\natticus\nattigit\nattinet\nattingere\nattulit\nauaritiam\nauarus\naucta\nauctores\nauctoribus\nauctoritas\nauctoritatem\nauctoritatis\naudaciam\naudacter\naudax\naudeat\naudeo\nauderet\naudet\naudiat\naudiendum\naudierat\naudio\naudiret\naudiri\naudisset\naudistis\naudite\nauditis\nauditor\nauditus\naudiunt\nauem\nauersa\nauertere\nauertit\naues\nauferre\naufert\naugeri\nauget\naugue\naugures\naugurium\naugusto\naugustus\nauia\nauibus\nauide\nauidus\nauis\nauium\naula\nauo\nauras\nauream\naureis\naurem\naureos\naures\naureus\nauribus\nauris\naurium\naurora\naurum\nausi\nauspiciis\nauspicium\nauster\nausus\nautem\nautumno\nauus\nauxilia\nauxiliis\nauxilio\nauxilium\nauxit\naxe\naxis\nbaccho\nbalbus\nbarbam\nbarbara\nbarbaris\nbarbarorum\nbarbarus\nbeatam\nbeati\nbeatus\nbelle\nbellis\nbellorum\nbellum\nbelua\nbeneficia\nbeneficiis\nbeneficio\nbeneficium\nbeneuolentia\nbenigne\nbestiis\nbibendum\nbibere\nbibitur\nbiduo\nbiduum\nbiennio\nbiennium\nbinos\nbis\nblanda\nblandit\nbonam\nbonis\nbonorum\nbonus\nbos\nboues\nboum\nbracchia\nbrachia\nbreues\nbreuibus\nbreuior\nbreuis\nbreuitate\nbreuiter\nbreuius\nbrumam\nbrundisium\nbruto\nbrutus\nbubus\nbus\ncacumine\ncadat\ncadauera\ncadere\ncadit\ncadunt\ncaeca\ncaecilius\ncaecina\ncaeco\ncaecus\ncaedes\ncaedibus\ncaedis\ncaelestia\ncaelestibus\ncaelestis\ncaelestium\ncaelio\ncaelius\ncaeloque\ncaelumque\ncaerula\ncaesarem\ncaesaris\ncaesus\ncalamitas\ncalamitatem\ncalamitatis\ncalce\ncalida\ncalidis\ncalido\ncalidum\ncaligine\ncallistratus\ncalorem\ncalumniae\ncamillus\ncampaniae\ncampus\ncancer\ncancri\ncandido\ncandidus\ncandore\ncanem\ncanere\ncanes\ncanibus\ncanit\ncantus\ncanum\ncapax\ncaperet\ncapiat\ncapillos\ncapillum\ncapite\ncapitibus\ncapitis\ncapitolio\ncapitolium\ncapitur\ncapiunt\ncaprae\ncaptis\ncaptiua\ncaptiuis\ncaptiuorum\ncaptiuos\ncaptus\ncapuam\ncaput\ncara\ncarcerem\ncardine\ncarent\ncarere\ncaret\ncarinae\ncarissime\ncaritas\ncaritate\ncarmen\ncarmine\ncarminibus\ncarminis\ncarnis\ncaro\ncarthaginem\ncarthaginienses\ncarthaginiensibus\ncarthaginiensium\ncarthaginis\ncarthago\ncarus\ncasibus\ncassio\ncassius\ncasta\ncastellum\ncastra\ncastris\ncastrorum\ncasus\ncatenis\ncatilinam\ncatonem\ncatonis\ncatulus\ncaua\ncaudam\ncauendum\ncaueri\ncauetur\ncauit\ncaule\ncausam\ncausarum\ncausis\ncautionem\ncautum\ncccc\nceciderunt\ncecidisse\ncecidit\ncedat\ncederet\ncedit\ncedo\ncedunt\nceleritatem\nceleriter\ncelerius\ncelerrime\ncella\ncelso\ncelsus\ncenam\ncenset\ncensores\ncensoribus\ncensuit\ncensum\ncensura\ncensus\ncentum\ncenturiones\ncenturionibus\nceperat\nceperunt\ncepisset\ncepit\ncerae\ncerebrum\ncererem\ncereris\nceres\ncernere\ncernimus\ncernis\ncernitur\ncerno\ncertae\ncertamen\ncertamine\ncertaminis\ncertare\ncertatim\ncerte\ncertiorem\ncertis\ncertius\ncertus\nceruicem\nceruicibus\nceruix\ncessare\ncessat\ncesserit\ncessit\ncestius\nceterae\nceteraque\nceterarum\nceteras\nceterisque\nceterorum\nceteros\nceterum\nceu\nchrysippus\ncibaria\ncibus\ncicatrices\nciceronem\nciceronis\nciet\nciliciam\ncineres\ncinis\ncinna\ncirca\ncirciter\ncirco\ncircuitu\ncirculo\ncirculus\ncircumdata\ncircumire\ncitius\ncito\ncitra\nciues\nciuibus\nciuilem\nciuilia\nciuilibus\nciuilis\nciuis\nciuitas\nciuitates\nciuitatibus\nciuitatis\nciuitatium\nciuitatum\nciuium\nclades\ncladibus\ncladis\nclamat\nclamorem\nclamoribus\nclara\nclarissimi\nclarius\nclaro\nclarus\nclasses\nclassibus\nclassis\nclaudio\nclaudius\nclausa\nclaustra\nclausum\nclementiam\nclipeo\nclipeum\nclodio\nclodius\ncoacta\ncoactus\ncocta\ncoctum\ncodicillos\ncoegit\ncoeperat\ncoepere\ncoeperit\ncoeperunt\ncoepisset\ncoepit\ncoepta\ncoeptum\ncoetus\ncoeunt\ncogatur\ncogendus\ncogere\ncogetur\ncogitare\ncogitationes\ncogitationibus\ncogito\ncogitur\ncognita\ncognitionem\ncognitis\ncognito\ncognitum\ncognomen\ncognomine\ncognoscere\ncognoscite\ncognouit\ncoguntur\ncohors\ncohortes\ncohortibus\ncohortium\ncoire\ncoit\ncolere\ncolitur\ncolla\ncollecta\ncollegam\ncolles\ncollibus\ncolligitur\ncollis\ncollo\ncollum\ncolonias\ncolonus\ncolores\ncoloribus\ncoloris\ncolumnis\ncolunt\ncomis\ncomitatus\ncomites\ncomitia\ncomitiis\ncomitiorum\ncomitum\ncommeatus\ncommemorat\ncommendat\ncommendo\ncommentariis\ncomminus\ncommisit\ncommissum\ncommittere\ncommittitur\ncommode\ncommodius\ncommodo\ncommodum\ncommotus\ncommunes\ncommunibus\ncommuniter\ncomparatione\ncomperit\ncompetat\ncompetere\ncompetit\ncomplecti\ncomplexus\ncomplures\ncompluribus\ncomponere\ncomposita\ncompositis\ncomposito\ncompositum\ncomposuit\nconatus\nconcedere\nconceditur\nconceptus\nconcessit\nconcessum\nconcidit\nconcilium\nconcordiam\nconcurrere\nconcurrunt\nconcursus\ncondemnari\ncondemnatus\ncondere\ncondiciones\ncondicionibus\ncondicionis\ncondictionem\ncondidit\nconditum\nconducto\nconfecit\nconfectum\nconferre\nconfert\nconfessus\nconfestim\nconficere\nconficitur\nconfido\nconfirmat\nconfiteor\nconfiteri\nconfugit\nconfusa\ncongue\nconiecturam\nconiugium\nconiuncta\nconiunctionem\nconiunctum\nconiunx\nconiurationis\nconlatis\nconlocauit\nconloquium\nconscia\nconscientiam\nconscius\nconscripti\nconsectetur\nconsecuti\nconsecutus\nconsedit\nconsensus\nconsentire\nconsequat\nconsequatur\nconsequens\nconsequitur\nconsiderandum\nconsiliis\nconsiliorum\nconsilium\nconsistere\nconsistit\nconspectum\nconspexit\nconstabat\nconstanter\nconstantiam\nconstaret\nconstet\nconstitit\nconstituere\nconstituitur\nconstituta\nconstitutione\nconstitutionibus\nconstitutus\nconsuerunt\nconsuetudinem\nconsuetudinis\nconsuetudo\nconsueuit\nconsulares\nconsularibus\nconsularis\nconsulatus\nconsulere\nconsules\nconsulibus\nconsulis\nconsultus\nconsulum\nconsumpta\ncontemnere\ncontemplatione\ncontendere\ncontendit\ncontendunt\ncontentione\ncontentus\ncontestatam\ncontigit\ncontineat\ncontinentia\ncontinentur\ncontineri\ncontinetur\ncontingat\ncontingere\ncontingit\ncontinuis\ncontinuo\ncontionem\ncontionibus\ncontracta\ncontractus\ncontrahit\ncontraque\ncontrariam\ncontrariis\ncontrario\ncontrarium\ncontraxit\ncontrouersiam\ncontulerunt\ncontulit\ncontumeliam\nconubia\nconuenerit\nconueniatur\nconueniens\nconueniet\nconueniri\nconuenisse\nconueniunt\nconuentus\nconuersus\nconuertere\nconuertit\nconuicium\nconuiuiis\nconuiuium\nconvallis\ncopiam\ncopiarum\ncopiis\ncopiose\ncoques\ncoquitur\ncoram\ncordi\ncoriandrum\ncorinthum\ncornelius\ncornibus\ncornua\ncoronis\ncorpore\ncorporibus\ncorporis\ncorporum\ncorpus\ncorrepta\ncorruptum\ncortex\ncortice\ncoss\ncotidiana\ncotidie\ncotta\ncottidie\ncras\ncrassitudine\ncrassitudo\ncrasso\ncrassus\ncreati\ncreatus\ncreauit\ncrebra\ncrebris\ncrebro\ncredat\ncredebant\ncredebat\ncredendum\ncredens\ncrederent\ncrederet\ncredibile\ncrediderit\ncredidit\ncredimus\ncredis\ncredite\ncreditis\ncreditores\ncreditoribus\ncreditoris\ncreditorum\ncreditur\ncredo\ncredunt\ncrescere\ncrescit\ncrescunt\ncretam\ncreuit\ncrimen\ncrimine\ncriminibus\ncriminis\ncriminum\ncrines\ncrinibus\ncroci\ncrucem\ncruciatus\ncruda\ncrudelem\ncrudelitas\ncrudelitatem\ncrudelitatis\ncruenta\ncruorem\ncrura\ncruribus\ncubiculum\ncubile\ncubilia\ncubitorum\ncuicumque\ncuidam\ncuiquam\ncuique\ncuiuscumque\ncuiusdam\ncuiusquam\ncuiusque\nculpam\nculta\ncultum\ncultura\ncultus\ncum\ncúm\ncuminum\ncumque\ncuncta\ncunctos\ncupere\ncupide\ncupidine\ncupiditas\ncupiditates\ncupido\ncupidus\ncupiens\ncupit\ncurabitur\ncurae\ncuram\ncurandum\ncurant\ncurare\ncurarum\ncuras\ncurationem\ncuratores\ncurauit\ncures\ncuriam\ncuris\ncurrere\ncurrit\ncurrus\ncursus\ncuspide\ncustodes\ncustodiam\ncustodibus\ncustos\ncutem\ncutis\ncxx\ncyathis\ncynthia\ndabant\ndabatur\ndabimus\ndabis\ndabitur\ndabo\ndabunt\ndamnari\ndamnata\ndamnationem\ndamnatus\ndamnauit\ndamno\ndamnum\ndamus\ndanai\ndanaum\ndandam\ndando\ndandum\ndantur\ndapes\ndarem\ndarent\ndares\ndaretur\ndari\ndas\ndatas\ndate\ndatos\ndatum\ndaturus\ndatus\ndeam\ndebeam\ndebeant\ndebeas\ndebeatur\ndebebit\ndebebunt\ndebemus\ndebentur\ndebeo\ndeberent\ndeberetur\ndeberi\ndebes\ndebetis\ndebetur\ndebitam\ndebiti\ndebitoris\ndebitum\ndebuerit\ndebuisse\ndebuit\ndeceat\ndecedat\ndecedere\ndecem\ndeceptus\ndecernere\ndecesserit\ndecessisset\ndecessit\ndecet\ndecidit\ndecimo\ndecimum\ndeclarat\ndecocto\ndecoctum\ndecore\ndecoris\ndecorum\ndecreta\ndecretis\ndecreto\ndecretum\ndecreuit\ndecuit\ndecumas\ndecus\ndedecus\ndederat\ndedere\ndederit\ndederunt\ndedimus\ndedissent\ndedisset\ndedisti\ndeditionem\ndeditus\ndeducere\ndeducitur\ndeducto\ndeductus\ndeduxit\ndeerat\ndeesset\ndeest\ndefectionem\ndefendat\ndefenderet\ndefenditur\ndefensionem\ndefensionis\ndefensor\ndeferre\ndefertur\ndeficit\ndefinitio\ndeformis\ndefuisse\ndefuit\ndefunctus\ndehinc\ndeiecit\ndeiectus\ndeinceps\ndeinde\ndeis\ndelata\ndelatus\ndelectant\ndelectat\ndeliciis\ndelictum\ndelubra\ndemens\ndementiae\ndemetrius\ndemissa\ndemocritus\ndemonstrat\ndemosthenes\ndemus\ndenarios\ndenique\ndensa\ndentes\ndentibus\ndentium\ndenuo\ndeorsum\ndeorum\ndeos\ndeponere\ndepositum\ndeposuit\ndeprehensus\ndeque\ndescendere\ndescendit\ndeserit\ndeserta\ndeseruit\ndesiderant\ndesiderare\ndesideret\ndesiderio\ndesiderium\ndesierit\ndesignatus\ndesiit\ndesinat\ndesinere\ndesinit\ndesinunt\ndesit\ndesperatione\ndestitit\ndesunt\ndeteriorem\ndeterius\ndetracto\ndetrahere\ndetrahit\ndetraxit\ndetrimento\ndetulit\ndetur\ndeus\ndexteram\ndextras\ndextro\ndextrum\ndiam\ndianam\ndicamus\ndicantur\ndicas\ndicatur\ndicebantur\ndicebatur\ndicemus\ndicendo\ndicendum\ndicens\ndicentem\ndicentur\ndicerem\ndicerentur\ndiceres\ndiceretur\ndices\ndicetur\ndicimus\ndicis\ndicitis\ndicitur\ndico\ndictam\ndictatorem\ndictatoris\ndictis\ndicto\ndictum\ndicturus\ndictus\ndicuntur\ndidicit\ndido\ndiebus\ndiem\ndierum\ndies\ndifferentia\ndifferre\ndiffert\ndifferunt\ndifficilem\ndifficilis\ndifficilius\ndifficultas\ndifficultatem\ndifficulter\ndigestorum\ndigitis\ndigitorum\ndigitos\ndigitum\ndignam\ndignissim\ndignitatem\ndignitatis\ndignus\ndiis\ndilectus\ndiligenter\ndiligentiam\ndiligentissime\ndiligentius\ndiligit\ndimicare\ndimidiam\ndimidio\ndimidium\ndimisit\ndimissa\ndimissis\ndimisso\ndimittere\ndionysius\ndirae\ndirum\ndiscedere\ndiscere\ndiscessit\ndiscessum\ndisciplinam\ndisciplinis\ndiscipulus\ndiscordia\ndiscrimen\ndiscrimine\ndiscutit\ndispositis\ndisputationum\ndissensio\ndisseruit\ndissimilis\ndissimulare\ndistat\ndistinctio\nditis\ndiua\ndiuersis\ndiuerso\ndiuersum\ndiues\ndiuidere\ndiuiditur\ndiuidundo\ndiuinam\ndiuinis\ndiuinitus\ndiuino\ndiuinum\ndiuisa\ndiuisione\ndiuisit\ndiuites\ndiuitiarum\ndiuitiis\ndiuitis\ndiuortium\ndiuos\ndiutius\ndiuturna\ndiuus\ndixerat\ndixere\ndixerit\ndixero\ndixerunt\ndiximus\ndixisset\ndixisti\ndixit\ndocent\ndocere\ndocet\ndocti\ndoctrinae\ndoctus\ndocuit\ndolabellam\ndolere\ndolet\ndolis\ndolor\ndolores\ndoloribus\ndoloris\ndolus\ndomestica\ndomesticis\ndomibus\ndomicilium\ndominam\ndomine\ndominis\ndominium\ndominorum\ndominus\ndomitio\ndomitius\ndomus\ndonare\ndonata\ndonationem\ndonationis\ndonatus\ndonauit\ndonec\ndonis\ndono\ndonum\ndorso\ndos\ndotem\ndotis\ndrachm\ndruso\ndrusus\nduabus\nduae\nduarum\nduas\ndubie\ndubiis\ndubio\ndubitari\ndubitas\ndubitatione\ndubitauit\ndubitet\ndubito\ndubius\nducat\nducebat\nducem\nducenta\nducentos\nduceret\nduces\nducibus\nducis\nducitur\nducta\nductor\nductus\nducum\nducuntur\ndudum\ndui\nduis\ndulcedine\ndulcis\ndummodo\ndumque\ndumtaxat\nduobus\nduodecimo\nduorum\nduos\nduplex\nduplicem\nduplici\nduplum\ndurare\ndurat\ndurior\nduris\nduritia\ndurius\nduro\ndurus\nduxerit\nduxit\neademque\neaedem\neamque\neamus\neandem\neaque\nearum\neasdem\neasque\neat\nebur\necastor\necce\neccum\necquis\nedepol\nedere\nedicto\nedictum\nedidit\nedito\neditum\nedixit\neduxit\neffecit\neffectus\nefficacius\nefficere\nefficiat\nefficitur\nefficiunt\neffigies\neffudit\neffugere\neffugit\neffuso\negens\negere\negerit\negerunt\negestas\neget\negisset\negit\nego\négo\negomet\negone\negredi\negregie\negregius\negressi\negressus\neho\neidem\neique\neisdem\neiusdem\neiusmodi\neiusque\neleganter\nelegit\neleifend\nelementa\nelementum\nelephanti\nelephantos\neligere\nelit\nelocutio\neloquentiam\nemancipato\nemancipatus\nemendat\nemere\nemerit\neminet\neminus\nemisit\nemisse\nemit\nemolumentum\nemplastrum\nempta\nemptionem\nemptorem\nemptoris\nemptum\nenim\nenimuero\nenixa\nennius\nensis\neodemque\neoque\neorumque\neosdem\neosque\nephesi\nepicurus\nepistulam\nepistularum\nepistulis\nepitheton\nepitomarum\nepitomatorum\nepulis\nequestris\nequidem\nequis\nequitatus\nequites\nequitibus\nequitumque\nequorum\nequus\neram\nerant\nerat\nerciscundae\nerepta\nereptum\nergo\nerimus\neripere\neripi\neripuit\nerit\nero\neros\nerrant\nerrare\nerrat\nerrorem\nerroris\nerumpit\nerunt\nerus\nesse\nésse\nessemus\nessent\nesset\nest\nést\nest”\nestis\nestne\nesto\nét\netenim\netiamne\netiamnunc\netiamsi\netruriam\netsi\neuadere\neuasit\neuenire\neuenit\neuentus\neuismod\neumenes\neumque\neundum\neunt\neuropam\nexacta\nexcedere\nexcedit\nexcepit\nexcepta\nexceptionem\nexceptis\nexcepto\nexceptum\nexcessit\nexcidit\nexcipere\nexcipit\nexcitat\nexclamat\nexcusationem\nexeat\nexegit\nexemplar\nexemplis\nexemplo\nexemplum\nexercere\nexercet\nexercitatione\nexercitibus\nexercitus\nexercuit\nexeunt\nexheredatus\nexhibendum\nexhibuit\nexigat\nexigere\nexigit\nexiguo\nexiguum\nexilio\nexilium\neximia\nexinde\nexire\nexistere\nexistimabat\nexistimant\nexistimari\nexistimas\nexistimationem\nexistimatur\nexistimauit\nexistimes\nexistimo\nexitio\nexitium\nexitus\nexoritur\nexorta\nexortus\nexpectare\nexpectat\nexpediat\nexpedire\nexpedit\nexperimentum\nexperiri\nexpers\nexperti\nexpertus\nexplicare\nexploratum\nexponam\nexponere\nexpositis\nexposuit\nexpressit\nexpressum\nexprimere\nexprimitur\nexpulit\nexspectare\nexspecto\nexstat\nexstiterit\nexstitit\nextat\nextemplo\nexterna\nexternis\nextis\nextiterit\nextitit\nextraneo\nextremam\nextremis\nextremo\nextremum\nextrinsecus\nextulit\nexuit\nexul\nfabae\nfabio\nfabius\nfabulis\nfacem\nfacerem\nfacerent\nfaceret\nfaces\nfaciamus\nfaciant\nfaciat\nfacibus\nfaciebant\nfaciebat\nfaciem\nfaciendam\nfaciendum\nfacient\nfaciet\nfacilis\nfacilius\nfacillime\nfacimus\nfacinoris\nfacinus\nfacis\nfacito\nfaciunt\nfactis\nfactorum\nfactos\nfactum\nfacturus\nfactus\nfacultates\nfacultatibus\nfacundia\nfalce\nfalcidiam\nfallax\nfallere\nfallit\nfalsa\nfalsis\nfalso\nfalsum\nfamam\nfames\nfamiliaris\nfamiliariter\nfamiliarum\nfamilias\nfanum\nfarina\nfasces\nfastidium\nfastigium\nfata\nfateor\nfateri\nfatetur\nfatis\nfatorum\nfatus\nfauces\nfaucibus\nfauorem\nfaxo\nfebris\nfecerant\nfecerat\nfecere\nfecerint\nfecerit\nfecerunt\nfecimus\nfecissent\nfecisset\nfecisti\nfecit\nfecunda\nfefellit\nfelices\nfelicior\nfelicitas\nfelicitatem\nfeliciter\nfelis\nfelix\nfelle\nfeminam\nfeminarum\nfeminis\nferam\nferant\nferarum\nferat\nferebant\nferebatur\nferenda\nferendum\nferens\nferentem\nferit\nferme\nfermentum\nferocem\nferox\nferrea\nferrent\nferret\nferri\nferroque\nferrum\nfertilis\nfertur\nferuntur\nferus\nfessa\nfessus\nfesta\nfetus\nfeugiat\nfiant\nfiat\nfico\nficta\nficus\nfida\nfideicommissi\nfideicommissorum\nfideicommissum\nfideiussores\nfides\nfidius\nfiduciam\nfiebant\nfiebat\nfient\nfierent\nfieret\nfieri\nfiet\nfiguris\nfila\nfiliis\nfiliorum\nfilius\nfimo\nfimum\nfines\nfingere\nfingitur\nfinibus\nfinis\nfinita\nfinitimis\nfinitur\nfinium\nfinxit\nfirma\nfirmum\nfisco\nfiscum\nfistula\nfit\nfiunt\nfixa\nflacco\nflaccus\nflagitium\nflammis\nflatus\nflectere\nflens\nflere\nfletus\nflores\nfloribus\nflos\nfluctibus\nfluctus\nfluere\nfluit\nflumen\nflumine\nfluminibus\nfluminis\nfluminum\nfluuio\nfluuius\nfocos\nfoeda\nfoedere\nfoederis\nfoedus\nfolia\nfoliis\nfoliorum\nfolium\nfons\nfontes\nfontibus\nfontis\nforamina\nforas\nforent\nforet\nforibus\nforis\nformas\nformidine\nformulam\nforo\nforsan\nforsitan\nfortassis\nfortes\nfortia\nfortibus\nfortior\nfortissimi\nfortissimus\nfortiter\nfortitudo\nfortius\nfortuito\nfortunis\nforum\nfossas\nfracta\nfractis\nfragor\nfrangit\nfrater\nfratres\nfratribus\nfratris\nfratrum\nfraudem\nfraudis\nfraus\nfregit\nfrena\nfrenis\nfrequentes\nfrequentia\nfrequentius\nfreto\nfretus\nfrigida\nfrigidus\nfrigore\nfrigoris\nfrigus\nfrondes\nfrondibus\nfrons\nfrontem\nfrontis\nfronto\nfructibus\nfructuario\nfructuarius\nfructus\nfructuum\nfruges\nfrugibus\nfrugum\nfrui\nfrumentum\nfrustra\nfudit\nfuerant\nfuerat\nfuere\nfuerint\nfuerit\nfuero\nfuerunt\nfugam\nfugere\nfugiens\nfugientes\nfugisse\nfugitiuum\nfugiunt\nfuimus\nfuissent\nfuisset\nfuisti\nfuit\nfulmen\nfulmine\nfulminis\nfuluio\nfuluius\nfumo\nfunctus\nfundamenta\nfundis\nfunditus\nfundus\nfunere\nfuneris\nfungi\nfunus\nfurem\nfurens\nfurere\nfuriis\nfuriosi\nfuriosus\nfurit\nfurius\nfurorem\nfuroris\nfurta\nfurtim\nfurto\nfurtum\nfusce\nfusi\nfusus\nfuturam\nfuturus\ngaio\ngaius\ngalbae\ngaleam\ngallias\ngallis\ngallorum\ngallus\ngaudent\ngaudeo\ngaudere\ngaudet\ngaudio\ngaudium\ngelu\ngeminos\ngeminum\ngemitus\ngemmis\ngenas\ngeneraliter\ngenere\ngeneribus\ngeneris\ngenero\ngenerum\ngenetiuus\ngenetrix\ngenibus\ngenitor\ngenitus\ngens\ngentes\ngentibus\ngentis\ngentium\ngenua\ngenuit\ngenus\ngerat\ngerebat\ngerens\ngereret\ngerit\ngermaniae\ngermanici\ngermanorum\ngermanos\ngeruntur\ngesserit\ngessisse\ngessit\ngestae\ngestarum\ngestis\ngestorum\ngestus\ngignitur\ngignuntur\ngladiatores\ngladius\ngloriam\ngloriosum\ngraccho\ngracchus\ngradibus\ngradus\ngraecae\ngraece\ngraeciam\ngraecis\ngraecorum\ngraecus\ngramine\ngrana\ngrande\ngrandis\ngrata\ngrates\ngratias\ngratior\ngratissima\ngratissimum\ngratius\ngratus\ngraues\ngrauia\ngrauiora\ngrauissima\ngrauissimum\ngrauitatem\ngrauiter\ngrauius\ngravida\ngreges\ngremio\ngressus\ngurgite\ngustu\nhabeam\nhabeant\nhabeas\nhabeatur\nhabebam\nhabebant\nhabebatur\nhabebit\nhabebo\nhabebunt\nhabemus\nhabenas\nhabendum\nhabenis\nhabens\nhabentes\nhabenti\nhabentur\nhabeo\nhaberemus\nhaberent\nhaberes\nhaberetur\nhaberi\nhabes\nhabetis\nhabeto\nhabetur\nhabitant\nhabitare\nhabitat\nhabito\nhabitum\nhabiturus\nhabitus\nhabuerat\nhabuere\nhabuerint\nhabuerit\nhabuerunt\nhabuisset\nhabuit\nhactenus\nhadrianus\nhaec\nhaeret\nhaesit\nhanc\nhannibalem\nhannibalis\nharenis\nharum\nharundine\nharuspices\nhasdrubal\nhastis\nhaudquaquam\nhausit\nhaut\nhector\nhemina\nhendrerit\nherbam\nherbarum\nherbis\nhercle\nherculis\nheredes\nheredibus\nheredis\nhereditaria\nhereditas\nhereditatem\nhereditatis\nheredum\nheres\nheri\nhermogenianus\nheros\nheus\nhiatu\nhiberna\nhibernis\nhic\nhiemis\nhiems\nhinc\nhisce\nhispaniam\nhistoriam\nhoc\nhóc\nhodieque\nhomero\nhomerus\nhomines\nhominibus\nhominis\nhominumque\nhomo\nhoneste\nhonestius\nhonesto\nhonestum\nhonores\nhonoribus\nhonoris\nhonorum\nhonos\nhoras\nhoratius\nhordeum\nhoris\nhorret\nhorrida\nhorror\nhortari\nhortatur\nhortensius\nhortos\nhorum\nhospes\nhospita\nhospitium\nhostes\nhostia\nhostibus\nhostili\nhostis\nhostium\nhuc\nhuic\nhuiuscemodi\nhuiusmodi\nhumanae\nhumanarum\nhumanis\nhumanitas\nhumanitate\nhumanitatis\nhumano\nhumanum\nhumilis\nhumo\nhumus\nhunc\niacentem\niacere\niacet\niactare\niactat\niactura\niaculis\niamdudum\niamne\niamque\nianua\niason\niauolenus\nibat\nibidem\nibique\nibit\nibo\nicta\nictibus\nictus\nidcirco\nidemque\nidentidem\nideoque\nidibus\nidonea\nidoneus\nidque\nidus\niecur\nigitur\nignari\nignarus\nignes\nignibus\nignis\nignium\nignominiam\nignorante\nignorantia\nignorare\nignorat\nignorauit\nignoro\nignoscere\nignota\nignotis\nignotum\niidem\niiii\niisdem\nilia\nilico\nilium\nillam\nillarum\nillas\nille\nillic\nillinc\nillis\nillius\nillorum\nillos\nillum\nillyricum\nimagines\nimaginibus\nimago\nimber\nimbres\nimbribus\nimis\nimitari\nimitatus\nimmortales\nimmortalibus\nimmortalis\nimmortalium\nimo\nimpedimento\nimpedit\nimperare\nimperatores\nimperatoribus\nimperatoris\nimperatorum\nimperatum\nimperauit\nimperdiet\nimperia\nimperiis\nimperio\nimperium\nimpetrare\nimpetrauit\nimpetus\nimpia\nimpius\nimplere\nimplet\nimpleuit\nimponere\nimpositum\nimposuit\nimprobe\nimprobus\nimprouiso\nimpuberi\nimpubes\nimpulit\nimpune\nimum\nín\ninanis\nincedit\nincendium\nincepto\nincerta\nincertis\nincerto\nincertus\nincessit\ninciderit\nincidit\nincipere\nincipiat\nincipit\nincipiunt\ninclusa\ninclusum\nincolae\nincolumis\nincommodo\nincommodum\nincredibile\nincredibilis\nincrementum\nindex\nindia\nindicant\nindicat\nindicio\nindicium\nindigna\nindignum\nindos\ninducere\ninducitur\ninductus\ninduit\nindulgentia\nindustria\ninduxit\ninermes\niners\ninertia\ninesse\ninest\ninfamiam\ninfamis\ninfans\ninfantes\ninfecti\ninfelix\ninferes\ninferiores\ninferos\ninferre\ninfert\ninfesto\ninfestus\ninfinitum\ninfra\ningenia\ningeniis\ningenio\ningenium\ningens\ningentes\ningentibus\ningentis\ningrati\ningratus\ningredi\ningressus\ninibi\niniecta\ninimica\ninimicitias\ninimicorum\ninimicus\niniquo\niniquum\ninire\ninitia\ninitiis\ninitio\ninitium\niniuriarum\niniuriis\niniussu\ninlinitur\ninlita\ninlitum\ninmerito\ninmortales\ninmortalibus\ninnocentem\ninnocentiam\ninnumerabiles\ninnumerabilia\ninopiam\ninops\ninponitur\ninpositum\ninposuit\ninpune\ninquam\ninque\ninquies\ninquit\ninrita\ninsaniam\ninscribitur\ninsequenti\ninsequitur\ninsidiarum\ninsidiis\ninsignes\ninsignibus\ninsignis\ninsita\ninstare\ninstat\ninstituere\ninstituerit\ninstituit\ninstituta\ninstitutionum\ninstitutis\ninstituto\ninstitutus\ninstructa\ninstructus\ninstrumento\ninstrumentum\ninstruxit\ninsulis\ninsuper\ninteger\nintegram\nintegris\nintegro\nintegrum\nintellectum\nintellegamus\nintellegas\nintellegatur\nintellegendum\nintellegere\nintellegimus\nintellegis\nintellegitur\nintellego\nintelleguntur\nintellexit\nintendere\nintendit\nintentio\nintentus\nintercessit\ninterdicto\ninterdictum\ninterdiu\ninterdum\ninterea\ninteremit\ninteremptus\ninteresset\ninterest\ninterfecit\ninterfectis\ninterfecto\ninterfectus\ninterficere\ninterfici\ninterfuit\ninterim\ninteriore\ninteritus\ninterposito\ninterque\ninterrogatus\nintersit\ninterualla\ninteruallis\ninteruallo\ninteruallum\ninterueniente\ninteruenit\nintestato\nintestina\nintrare\nintrat\nintrauit\nintro\nintuens\nintueri\nintulit\nintus\ninuadit\ninuasit\ninuectus\ninuenerit\ninuenies\ninuenimus\ninuenio\ninueniri\ninuenisse\ninuenitur\ninueniuntur\ninuenta\ninuentus\ninuicem\ninuidiam\ninuisa\ninuisum\ninuita\ninuitis\ninuito\ninuitus\ninutilem\ninutiliter\nioco\niouem\niouis\nipsam\nipsaque\nipsarum\nipsas\nipse\nipsis\nipsius\nipsorum\nipsos\nipsum\nipsumque\nipsus\niracundiam\niram\nirascitur\nirati\niratus\niret\niri\nisdem\nisque\nisse\nistaec\nistas\niste\nistis\nistius\nistoc\nistorum\nistos\nistum\nitaliam\nitane\nitaque\nitemque\niterumque\nitidem\nitinere\nitineribus\nitineris\nitur\niuba\niubeat\niubebat\niubent\niubeo\niuberet\niubes\niubetur\niucunda\niucundius\niucundum\niudex\niudicari\niudicatae\niudicatus\niudicauit\niudices\niudicia\niudicibus\niudiciis\niudiciorum\niudicis\niudicium\niudico\niudicum\niuga\niugera\niugerum\niugis\niugo\niugum\niugurtha\niuliam\niulianus\niulio\niulius\niumenta\niumentorum\niuncta\niunctis\niungere\niungitur\niunguntur\niunio\niunius\niunonem\niunonis\niunxit\niuppiter\niurando\niurandum\niurare\niurauerit\niurauit\niure\niurgia\niuris\niusiurandum\niussa\niusserit\niusserunt\niussisset\niussit\niussus\niustam\niuste\niustis\niustitiam\niustius\niusto\niustus\niuuant\niuuare\niuuat\niuuenalis\niuuenis\niuuentae\niuuentute\niuuentutis\niuuenum\niuxta\njusto\nkalendis\nlabeonis\nlabitur\nlaborare\nlaborat\nlabores\nlaboribus\nlaboris\nlaborum\nlabra\nlabris\nlacedaemoniis\nlacedaemoniorum\nlacertis\nlacrimis\nlacte\nlactis\nlacus\nlaelius\nlaeta\nlaetitiam\nlaeto\nlaetus\nlaeuo\nlaeuum\nlanae\nlapides\nlapidibus\nlapidis\nlapidum\nlapis\nlapsus\nlares\nlata\nlatebras\nlatenter\nlatere\nlateribus\nlateris\nlaterum\nlatet\nlatine\nlatinis\nlatinorum\nlatinus\nlatis\nlatitudinem\nlatitudo\nlatius\nlato\nlatrones\nlatronum\nlatus\nlaudari\nlaudatur\nlaudes\nlaudibus\nlaudis\nlauro\nlaurus\nlaus\nlecta\nlectica\nlectis\nlecto\nlectulo\nlectus\nlegari\nlegatario\nlegatarius\nlegationis\nlegatis\nlegatorum\nlegatus\nlegauerit\nlegauit\nlegem\nlegere\nleges\nlegetur\nlegibus\nlegimus\nlegiones\nlegionibus\nlegionis\nlegionum\nlegis\nlegitimam\nlegitimum\nlegitur\nlego\nlegum\nlegunt\nlenis\nleniter\nleno\nlento\nlentulo\nlentulus\nlentus\nleo\nleonis\nlepido\nlepidus\nleporem\nleporis\nleto\nletum\nleuat\nleues\nleuia\nleuibus\nleuiora\nleuis\nleuiter\nleuius\nlex\nlibeat\nlibellos\nlibellum\nlibens\nlibenter\nlibentius\nliberae\nliberalis\nliberalitate\nliberam\nliberari\nliberatus\nliberauit\nliberetur\nliberis\nliberius\nlibero\nliberorum\nliberos\nlibertatis\nlibertis\nlibertorum\nlibertus\nliberum\nlibet\nlibidinis\nlibido\nlibris\nlibrorum\nlibros\nlibrum\nlibyae\nliceat\nlicebit\nlicentiam\nliceret\nlicet\nlicinius\nlicuit\nligno\nlignum\nligula\nligures\nligusticum\nlimen\nlimine\nlimites\nlimo\nlinea\nlinguam\nlino\nliquamen\nliquamine\nliquido\nliquor\nlis\nlitis\nlitore\nlitoribus\nlitoris\nlitterarum\nlitteris\nlitus\nliuius\nlobortis\nlocato\nlocauit\nlocis\nlocorum\nlocos\nlocum\nlocupletior\nlocus\nlocuti\nlocutus\nlongas\nlongeque\nlonginqua\nlongior\nlongis\nlongitudinem\nlongitudo\nlongius\nlongus\nloquar\nloquatur\nloquendi\nloqueretur\nloquimur\nloquitur\nloquor\nloquuntur\nlora\nlorem\nlubet\nlubrica\nlucanus\nlucet\nlucilio\nlucilius\nlucis\nlucius\nlucos\nlucretius\nlucro\nlucrum\nluctus\nlucus\nludere\nludis\nludorum\nludos\nludum\nlumen\nlumine\nluminibus\nluminis\nlunam\nlupi\nlupus\nlustra\nlusus\nluto\nluxuriam\nlxxx\nlydia\nlyra\nmacedones\nmacedoniam\nmacedonum\nmacer\nmaecenas\nmaerore\nmaesta\nmaeuio\nmaeuius\nmagisque\nmagister\nmagistratibus\nmagistratus\nmagistratuum\nmagistrum\nmagna\nmagnam\nmagnaque\nmagnas\nmagne\nmagnis\nmagnitudinem\nmagnitudinis\nmagnitudo\nmagnopere\nmagnoque\nmagnorum\nmagnus\nmago\nmaiestatem\nmaiestatis\nmaiora\nmaiores\nmaioribus\nmaioris\nmaiorum\nmaius\nmalam\nmale\nmalit\nmallet\nmalorum\nmalos\nmaluit\nmalum\nmalunt\nmalus\nmancipium\nmandare\nmandata\nmandatis\nmandatum\nmandauit\nmaneat\nmanebit\nmanente\nmaneret\nmanet\nmanibus\nmanifesto\nmanifestum\nmanlio\nmanlius\nmansit\nmanumiserit\nmanumissus\nmanumittere\nmanusque\nmarcellus\nmarcianus\nmarcio\nmarcius\nmarco\nmarcus\nmares\nmaria\nmarina\nmario\nmarique\nmaris\nmaritimis\nmarito\nmaritus\nmarius\nmarmore\nmars\nmartem\nmartis\nmasculino\nmassa\nmateriam\nmateries\nmatres\nmatrimonio\nmatrimonium\nmatris\nmatronae\nmature\nmaturius\nmatutino\nmauors\nmauris\nmaximas\nmaximeque\nmaximus\nmaxume\nmé\nmeam\nmearum\nmeas\nmecum\nmedea\nmedentur\nmederi\nmedetur\nmedias\nmedicamenta\nmedicamentis\nmedicamento\nmedicamentum\nmedicinam\nmedicis\nmedico\nmedicus\nmediis\nmediocris\nmediocriter\nmedius\nmedulla\nmehercules\nmeis\nmeliora\nmelioris\nmelius\nmelle\nmellis\nmembra\nmembris\nmembrorum\nmembrum\nmemento\nmeminisse\nmeminit\nmemorabile\nmemores\nmemoriam\nmendacium\nmenses\nmensibus\nmensis\nmensuram\nmentam\nmentes\nmentibus\nmentionem\nmentiri\nmentis\nmeorum\nmeos\nmeque\nmercedem\nmerces\nmercurius\nmereri\nmeretricem\nmeretrix\nmeridiem\nmerita\nmeritis\nmerito\nmeritum\nmero\nmeruisse\nmeruit\nmerum\nmetello\nmetellus\nmetri\nmetuens\nmetuit\nmetus\nmeus\nmihi\nmíhi\nmihique\nmiles\nmilia\nmilibus\nmilitarem\nmilitaria\nmilitaribus\nmilitaris\nmilites\nmilitiam\nmilitibus\nmilitis\nmilitum\nmilium\nmille\nmilonis\nminas\nminatur\nmineruam\nminimo\nminimum\nministerio\nministerium\nministros\nminora\nminores\nminoribus\nminoris\nminucius\nminuit\nminus\nmirabile\nmiraculo\nmirandum\nmirantur\nmiraris\nmiratur\nmire\nmirifice\nmiror\nmirum\nmiscentur\nmiscere\nmiscetur\nmiscuit\nmiserabile\nmiserat\nmiserere\nmisericordiam\nmiseros\nmiserum\nmiserunt\nmisisset\nmisit\nmissae\nmissus\nmitis\nmittam\nmitteret\nmittis\nmittitur\nmitto\nmittunt\nmixto\nmixtus\nmoderatione\nmodestinus\nmodice\nmodicis\nmodico\nmodicum\nmodios\nmodus\nmoenia\nmoenibus\nmolem\nmoleste\nmolestia\nmolestie\nmolestus\nmoliri\nmolles\nmollia\nmollibus\nmollior\nmollis\nmolliter\nmollius\nmomento\nmomentum\nmoneo\nmonere\nmonet\nmonstrat\nmonstrum\nmontes\nmontibus\nmontis\nmontium\nmonumenta\nmonumentis\nmonumentum\nmoram\nmorari\nmoras\nmoratus\nmorbi\nmorbis\nmorborum\nmorbus\nmorem\nmoreretur\nmores\nmoriar\nmoriatur\nmoribus\nmoriens\nmorietur\nmoris\nmoritur\nmoror\nmorsus\nmortales\nmortalibus\nmortalium\nmortem\nmortis\nmortua\nmortuus\nmorum\nmos\nmota\nmotibus\nmotus\nmoueat\nmouentur\nmoueri\nmouetur\nmouit\nmox\nmucius\nmuliebri\nmulieres\nmulieribus\nmulieris\nmulierum\nmulso\nmultam\nmultaque\nmultarum\nmultas\nmultisque\nmultitudinem\nmultitudinis\nmultitudo\nmultoque\nmultorum\nmultos\nmultumque\nmultus\nmundo\nmundus\nmunere\nmuneribus\nmuneris\nmunia\nmunimenta\nmunitiones\nmunus\nmuris\nmurmure\nmuros\nmurrae\nmurus\nmusae\nmusti\nmustum\nmutari\nmutata\nmutatio\nmutato\nmutatur\nmutauit\nmutuam\nmutuo\nnactus\nnaeuius\nnamque\nnanctus\nnares\nnaribus\nnarrare\nnarratio\nnascatur\nnascens\nnascitur\nnascuntur\nnaso\nnatae\nnatalis\nnatam\nnate\nnationes\nnationibus\nnatos\nnatum\nnaturae\nnaturalis\nnaturaliter\nnaturam\nnatus\nnaualibus\nnaues\nnaufragio\nnaufragium\nnauibus\nnauigia\nnauis\nnauita\nnauium\nnautae\nnautis\nnec\nnecat\nnecdum\nnecem\nnecessariam\nnecessariis\nnecessario\nnecessarius\nnecessest\nnecessitas\nnecessitatem\nnecne\nnedum\nnefarium\nnefas\nnegant\nnegare\nnegat\nnegauit\nneget\nneglegentiam\nnegotia\nnegotiis\nnegotiorum\nnegotium\nneminem\nnemini\nnemora\nnemorum\nnempe\nnemus\nnepos\nnepotes\nnepotibus\nnepotis\nneptis\nneptuno\nneptunus\nnequam\nnequaquam\nnequeo\nnequiquam\nneratius\nneronem\nneronis\nnerua\nneruis\nneruorum\nneruos\nnesciat\nnescio\nnescire\nnescit\nnescius\nneue\nneuter\nneutro\nneutrum\nnibh\nniger\nnigrae\nnigris\nnigro\nnigrum\nnihilominus\nnihilque\nnilo\nnilus\nnimiam\nnimio\nnimirum\nnimis\nnimius\nnisl\nnisu\nnititur\nnitro\nniues\nnobilis\nnobilitas\nnobilitatem\nnobilitatis\nnobilium\nnobiscum\nnoceat\nnocens\nnocentes\nnocere\nnocet\nnoctemque\nnoctesque\nnoctibus\nnoctis\nnocturnis\nnocturno\nnocuit\nnolite\nnolle\nnolo\nnoluerit\nnolunt\nnomenque\nnominantur\nnominatim\nnominatiuo\nnominatiuus\nnominatur\nnominauit\nnomine\nnominibus\nnominis\nnominum\nnon\nnón\nnondum\nnonne\nnonnulli\nnonnumquam\nnono\nnonummy\nnoscere\nnosmet\nnosse\nnoster\nnosti\nnostris\nnostrorum\nnostros\nnostrum\nnotam\nnotandum\nnotat\nnotis\nnotitiam\nnotus\nnouas\nnouem\nnouercam\nnouimus\nnouissime\nnouissimum\nnouitate\nnouus\nnoxae\nnoxia\nnubem\nnubere\nnubes\nnubibus\nnubila\nnuces\nnuda\nnudis\nnudo\nnudus\nnulla\nnullis\nnullius\nnullus\nnuma\nnumen\nnumerare\nnumerus\nnumidae\nnumine\nnuminis\nnuminum\nnummis\nnummorum\nnummos\nnummum\nnumquam\nnumquid\nnunc\nnúnc\nnunquam\nnuntiatum\nnuntius\nnuper\nnupta\nnuptiae\nnuptiarum\nnuptiis\nnurus\nnusquam\nnutrix\nnutu\nnymphae\nobesse\nobicere\nobicitur\nobiecit\nobiecta\nobiectum\nobiit\noblata\nobligari\nobligationem\nobligatus\noblita\noblitus\nobnoxia\nobruit\nobscuro\nobscurum\nobsecro\nobsequium\nobseruandum\nobseruari\nobseruatio\nobsides\nobsidionem\nobstare\nobstat\nobtinere\nobtinuit\nobtulit\nobuiam\nobuius\noccasionem\noccasus\noccidentem\nocciderat\nocciderit\noccidisset\noccidit\nocciso\noccisus\nocculto\noccultum\noccupare\noccupatus\noccupauit\noccurrere\noccurrit\noceano\noceanus\nocius\noctauius\noctauo\noctoginta\noculis\noculorum\noculos\noculum\nodio\nodisse\nodit\nodium\nodoris\noffendit\nofferre\nofficia\nofficiis\nofficiorum\nofficium\noleae\noleo\noleum\nolim\noliuae\nolympo\nomen\nomine\nomissa\nomissis\nomisso\nomittam\nomitto\nomnemque\nomnesque\nomniaque\nomnibusque\nomnimodo\nomnino\nomnipotens\nomnisque\nomnium\nonere\noneris\nonus\nopem\noperam\noperarum\noperas\nopere\noperibus\noperis\noperum\nopes\nopibus\nopiniones\nopinionum\nopinor\nopis\noporteat\noportebit\noporteret\noportet\noportuit\noppida\noppidis\noppido\noppidum\nopportune\nopposita\noppressit\noppressus\noppugnare\noptare\noptat\noptauit\noptime\noptimis\noptimo\noptimus\noptio\nopto\noptume\nopum\nopust\noraculum\noram\norare\noras\norationes\norationibus\norationis\noratores\noratoribus\noratoris\noratorum\norbis\norci\nordines\nordinibus\nordinis\nordinum\nordo\nore\noriens\norientem\norientis\noriginem\norigo\norion\noris\noritur\noriuntur\nornamenta\nornamentis\nornamentum\nornare\nornata\nornatus\noro\norsus\norta\nortus\noscula\nossa\nossibus\nostendat\nostenderet\nostendimus\nostenditur\nostendunt\nostia\nostium\notio\notium\noua\nouis\nouium\npabulo\npabulum\npacem\npacis\npacto\npactus\npaene\npaeniteat\npaenitentia\npaenitet\npalam\npalatio\npalatium\npallas\npallida\npalmis\npaludes\npalus\npamphilum\npanem\npanis\npansa\npapaueris\npapiam\npapinianus\npapirius\nparabat\nparant\nparati\nparatus\nparcere\nparcius\nparem\nparens\nparentes\nparentibus\nparentium\nparentum\nparere\nparet\nparia\nparibus\nparietes\nparietibus\nparis\npariterque\npariunt\nparricida\nparricidio\nparricidium\npars\nparta\npartes\nparthis\nparthorum\nparthos\npartibus\nparticeps\nparticipium\nparticula\npartis\npartium\npartus\nparuae\nparuis\nparumper\nparuo\nparuum\npascua\npassa\npassim\npasso\npassus\npassuum\npastores\npatent\npaterentur\npateretur\npaternae\npaternis\npaternum\npatet\npatiantur\npatiar\npatiatur\npatiens\npatientiam\npatietur\npatior\npatitur\npatiuntur\npatres\npatrias\npatribus\npatriis\npatrimonio\npatrimonium\npatrios\npatris\npatrium\npatronis\npatrono\npatronus\npatruo\npatruus\npauca\npauciores\npaucis\npaucorum\npaucos\npaulatim\npaulisper\npaulo\npaululum\npaulus\npauore\npauperem\npauperis\npaupertas\npaupertatem\npax\npeccare\npeccata\npeccatum\npecore\npecoris\npecorum\npectore\npectoris\npectus\npecudes\npecudum\npeculio\npeculium\npecuniis\npecus\npede\npedes\npedibus\npedis\npedites\npeditum\npedum\npeior\npeius\npelago\npelagus\npelle\npellentesque\npellibus\npenates\npenatibus\npendente\npendere\npendet\npenes\npenitus\npennis\npeperit\nperacta\npercipi\npercussit\npercussus\nperdere\nperdidisse\nperdidit\nperdit\nperduxit\npereat\nperegre\nperegrina\npereunt\nperfectum\nperferre\nperfidia\npergama\nperge\npergit\npericulis\npericulorum\npericulosum\npericulum\nperierit\nperierunt\nperiit\nperinde\nperire\nperisse\nperitus\npermisit\npermissum\npermittendum\npermittere\npermittitur\npermixta\nperniciem\nperperam\nperpeti\nperpetuam\nperpetuum\nperquam\nperque\npersae\npersarum\npersas\npersea\npersecutus\npersequitur\nperseus\npersonarum\npersonis\nperspicere\nperspicuum\npersuadere\npertinacia\npertinax\npertineant\npertineat\npertinebit\npertinent\npertineret\npertinet\npertulit\nperuenerit\nperuenerunt\nperueniat\nperueniret\nperuenisset\nperueniunt\nperuentum\npessimum\npestem\npestilentia\npestis\npetam\npetatur\npetebant\npetebat\npetenda\npetendum\npetens\npetentes\npetentibus\npeterent\npeteretur\npetet\npetierit\npetiit\npetimus\npetisse\npetita\npetitionem\npetitur\npetiuit\npeto\npetunt\npharetra\nphilippus\nphilosophiam\nphilosophis\nphilosophorum\nphilosophus\nphoebo\nphoebus\nphrygiae\npia\npice\npicta\npicturae\npietas\npietatem\npietatis\npiget\npignore\npignoris\npignus\npii\npila\npilis\npingue\npinguis\npinnis\npinus\npio\npipere\npiperis\npiratis\npisces\npiscibus\npiscis\npiscium\npisonem\npisonis\npius\nplaceat\nplacebat\nplacent\nplacerat\nplaceret\nplacet\nplacido\nplacuisse\nplacuit\nplagis\nplano\nplanum\nplatonem\nplatonis\nplautium\nplautus\nplebis\nplebs\nplenam\nplenis\nplenius\npleno\nplenus\npleraque\nplerique\nplerisque\nplerosque\nplerumque\nplinius\nplurali\nplures\npluribus\nplurimos\nplurimum\npluris\nplurium\nplus\npluuiae\npocula\npoenam\npoenarum\npoenis\npoenorum\npoenus\npoetam\npoetarum\npoetis\npolenta\npollicetur\npollicitus\npollio\npolo\npoma\npomis\npompa\npompeio\npompeius\npomponius\nponam\npondere\nponderis\npondo\npondus\nponere\nponitur\npontem\npontifex\npontifices\npontificum\nponto\npontus\nponuntur\npopularis\npopulique\npopulis\npopuloque\npopulorum\npopulus\nporro\nportat\nporticus\nportionem\nporttitor\nportus\nposcere\nposcit\npositis\nposito\npositus\npossedit\npossemus\npossent\npossessionis\npossessorem\nposset\npossideat\npossideret\npossidet\npossimus\npossint\npossit\npossumus\npossunt\nposteaquam\npostera\nposteriore\nposterioribus\nposterius\nposteros\nposterum\nposthac\npostliminio\npostquam\npostremum\npostridie\npostulabat\npostulare\npostulauit\npostulo\npostumius\npostumus\nposuere\nposuerunt\nposuisse\nposuit\npota\npotens\npotentem\npotentiam\npoteram\npoterant\npoterit\npotero\npoterunt\npotestatem\npotestatis\npotestis\npotionem\npotior\npotissimum\npotitus\npotius\npotuerint\npotuerit\npotuerunt\npotuissent\npotuisset\npotuisti\npotuit\npotus\npraebent\npraebere\npraebet\npraebuit\npraecedit\npraecepit\npraecepta\npraeceptis\npraeceptum\npraecipere\npraecipites\npraecipiti\npraecipue\npraecipuum\npraeclare\npraeclarum\npraecordia\npraedam\npraedia\npraediis\npraediorum\npraedium\npraedonum\npraeerat\npraefecti\npraefectus\npraeiudicium\npraemia\npraemiis\npraemio\npraemium\npraepositio\npraepositus\npraesent\npraesentes\npraesentia\npraesentibus\npraesentis\npraesertim\npraeses\npraesides\npraesidia\npraesidiis\npraesidis\npraesidium\npraestabit\npraestanda\npraestandum\npraestant\npraestaret\npraestari\npraestat\npraestetur\npraestiterit\npraestitit\npraesto\npraeterea\npraeterito\npraeteritum\npraeterquam\npraetores\npraetoria\npraetoribus\npraetoris\npraetorium\npraetorum\npraeturam\npraua\nprecario\npreces\nprecibus\nprecor\npremit\npremunt\npressa\npressit\npretio\npretium\npriami\npridem\npridie\nprimis\nprimordia\nprimores\nprimoribus\nprimus\nprinceps\nprincipatum\nprincipes\nprincipia\nprincipibus\nprincipiis\nprincipis\nprincipium\nprincipum\npriora\npriores\nprioribus\nprioris\npriorum\nprisco\npristinum\npriuata\npriuatis\npriuatorum\npriuatus\npriuilegium\npriusquam\nprobandum\nprobant\nprobari\nprobata\nprobatio\nprobatur\nprobetur\nprobo\nprobus\nprocedere\nprocedit\nproceres\nprocessit\nproconsulis\nproculus\nprocuratorem\nproderit\nprodesse\nprodest\nprodidit\nprodigia\nprodita\nproditionis\nproditum\nproducitur\nproducta\nproelia\nproeliis\nproelio\nproelium\nprofectus\nproferre\nprofessus\nproficere\nproficiscitur\nproficit\nprofugit\nprofuit\nprofundum\nprogenies\nprogredi\nprogressus\nprohiberi\nprohibetur\nprohibitus\nprohibuit\nproin\nproinde\nproles\npromiserit\npromisit\npromissum\npromittere\npromittit\npromptu\npromunturium\nprona\npronepos\npronuntiatum\npronuntiauit\npropemodum\npropere\npropinqua\npropinquos\npropinquum\npropior\npropius\nproponerentur\nproponitur\nproposito\npropositum\nproposuit\nproprias\nproprietas\nproprietatem\nproprietatis\npropriis\nproprio\nproprium\npropterea\nprorsus\nprosit\nprospere\nprosunt\nprotinus\nprotulit\nprouidentia\nprouinciae\nprouinciale\nprouinciam\nprouinciarum\nprouinciis\nprout\nproximam\nproxime\nproximus\nprudens\nprudenter\nprudentiam\npubertatem\npubes\npublicas\npublice\npublicis\npublicorum\npublicus\npudeat\npudet\npudicitiam\npudorem\npudoris\npuellis\npueris\npueritia\npuerorum\npueros\npuerum\npugnam\npugnandi\npugnare\npugnas\npugnatum\npugnauit\npulcherrima\npulcherrimum\npulchre\npulchritudinem\npulchrum\npulli\npullos\npulsi\npulsus\npuluerem\npuluis\npulvinar\npunico\npunicum\npupillo\npupillus\npuppis\npure\npurgare\npurgat\npuro\npurpura\npurpureo\npurum\npurus\npus\nputabam\nputabant\nputabat\nputamus\nputant\nputaret\nputas\nputatis\nputatur\nputauerunt\nputauit\nputem\nputent\nputes\nputetis\nputo\nquacumque\nquadam\nquadragensimo\nquadragesimo\nquadraginta\nquadrantem\nquadrato\nquaecumque\nquaedam\nquaenam\nquaeque\nquaeramus\nquaeras\nquaeratur\nquaerebatur\nquaerenda\nquaerendum\nquaereretur\nquaerimus\nquaeris\nquaeritis\nquaeritur\nquaero\nquaerunt\nquaesitum\nquaesiuit\nquaeso\nquaestiones\nquaestionibus\nquaestionis\nquaestionum\nquaestores\nquaestus\nquales\nqualia\nqualibet\nqualis\nqualitate\nqualiter\nquam\nquám\nquamdiu\nquamlibet\nquamquam\nquamque\nquamuis\nquandam\nquandoque\nquanquam\nquantis\nquantitatem\nquanto\nquantumque\nquantus\nquapropter\nquaque\nquare\nquartam\nquarto\nquartus\nquarum\nquasdam\nquasi\nquasque\nquatenus\nquater\nquatit\nquattuordecim\nqueat\nquemadmodum\nquemcumque\nquemquam\nquemque\nquendam\nquercus\nqueritur\nqueror\nquestus\nquí\nquia\nquibusdam\nquibusque\nquicquam\nquicquid\nquicumque\nquid\nquíd\nquidam\nquiddam\nquidem\nquidnam\nquidni\nquidque\nquidquid\nquidue\nquiduis\nquies\nquieta\nquietem\nquietis\nquinariae\nquinctius\nquindecim\nquinquagensimo\nquinquaginta\nquinquennium\nquinto\nquintus\nquippe\nquique\nquirites\nquiritium\nquis\nquisnam\nquispiam\nquisquam\nquisque\nquisquis\nquiuis\nquoad\nquocirca\nquocumque\nquod\nquód\nquodammodo\nquodcumque\nquoddam\nquodque\nquodsi\nquoius\nquolibet\nquominus\nquomodo\nquonam\nquondam\nquoniam\nquoquam\nquoquo\nquorum\nquorundam\nquosdam\nquosque\nquotannis\nquotienscumque\nquouis\nquousque\nrabies\nradices\nradicibus\nradicis\nradios\nradix\nramos\nrapere\nrapido\nrapit\nrapta\nraptim\nraptor\nraptus\nrapuit\nraro\nrarum\nratam\nrates\nrationes\nrationibus\nrationis\nratus\nrebus\nrecens\nrecentes\nrecentibus\nreceperunt\nrecepit\nrecepto\nreceptus\nrecessit\nrecipere\nrecipiat\nrecipit\nrecipiunt\nrecte\nrectissime\nrectius\nrector\nrectum\nrecuperatores\nrecusare\nreddam\nreddatur\nredderet\nreddidit\nreddita\nredditur\nreddunt\nredeat\nredegit\nredemit\nredeo\nredeunt\nredierunt\nrediit\nrediret\nredisse\nreditus\nreduxit\nreferat\nreferens\nreferri\nrefertur\nreferuntur\nreficere\nrefugit\nregem\nregere\nreges\nregiam\nregibus\nregiis\nregina\nregiones\nregionibus\nregionis\nregionum\nregit\nregium\nregnare\nregnauit\nregnis\nregno\nregnum\nregulam\nregularum\nregulus\nregum\nreis\nrelata\nrelatum\nrelicta\nrelictis\nrelicto\nrelictus\nreligionis\nreligiosum\nrelinquatur\nrelinqueret\nrelinquitur\nrelinquunt\nreliquas\nreliquerit\nreliquerunt\nreliquias\nreliquisset\nreliquit\nreliquorum\nreliquos\nreliquum\nremanere\nremanet\nremansit\nremedia\nremediis\nremedio\nremedium\nremisit\nremissa\nremittere\nremittit\nremota\nremotis\nremoto\nreos\nrepente\nrepentino\nreperiri\nreperiuntur\nreperta\nrepertum\nrepetere\nrepetita\nrepetundarum\nrepperit\nrerumque\nrescripserunt\nrescripsit\nrescripto\nrescriptum\nresinae\nresistere\nrespexit\nrespice\nrespicit\nrespondent\nrespondere\nresponderit\nresponderunt\nrespondet\nrespondisse\nrespondit\nresponsorum\nresponsum\nrestat\nrestitit\nrestituat\nrestitueret\nrestituit\nrestituta\nrestitutionem\nrestitutus\nretia\nretinent\nretineri\nretinet\nretro\nrettulit\nreuerentia\nreuersus\nreuertitur\nreum\nreuocari\nreuocauit\nreus\nrex\nrhenum\nrhodiis\nrhoncus\nridiculum\nripis\nrisus\nrite\nritus\nrobore\nroboris\nrobur\nrogare\nrogas\nrogationem\nrogatus\nrogauit\nrogo\nrogum\nromam\nromanis\nromanorum\nromanus\nromulo\nromulus\nrore\nrosaceo\nrosae\nroscius\nrostra\nrostris\nrostro\nrota\nrudis\nruere\nrufo\nrufus\nruinis\nruit\nrumore\nrumpere\nrumpit\nrupes\nrupit\nrupta\nruptis\nrure\nruris\nrursum\nrursusque\nrustica\nrusticus\nrutam\nrutrum\nruunt\nsabinis\nsabino\nsabinus\nsacerdotes\nsacrae\nsacramento\nsacras\nsacrificio\nsacrificium\nsacris\nsacrorum\nsacros\nsacrum\nsaecula\nsaeculis\nsaeculo\nsaepe\nsaepissime\nsaepius\nsaepta\nsaeua\nsaeuis\nsaeuitiam\nsaeuo\nsaeuus\nsagittis\nsalem\nsalis\nsallustius\nsalsa\nsaltem\nsaltus\nsaluam\nsalue\nsaluos\nsalus\nsalutare\nsalutem\nsalutis\nsaluum\nsamnites\nsamnitibus\nsamnitium\nsanari\nsanat\nsancta\nsanctum\nsane\nsanguinem\nsanguinis\nsanguis\nsanitatem\nsanus\nsapere\nsapien\nsapiens\nsapientes\nsapientiam\nsapientis\nsaporem\nsardiniam\nsata\nsatin\nsatisdare\nsatius\nsaturnia\nsaucius\nsaxa\nsaxis\nsaxo\nsaxum\nscaenam\nscaeuola\nscaurus\nscelere\nsceleribus\nsceleris\nscelerisque\nscelerum\nscelus\nsceptra\nschema\nsciamus\nsciant\nsciat\nsciebat\nsciendum\nsciens\nsciente\nscientiam\nsciet\nscilicet\nscimus\nscio\nscipionem\nscipionis\nscirent\nsciret\nscis\nscitis\nscito\nsciunt\nscopulos\nscribas\nscribendo\nscribendum\nscriberet\nscribis\nscribitur\nscribo\nscribunt\nscripserit\nscripserunt\nscripsisset\nscripsisti\nscripsit\nscriptam\nscriptis\nscriptores\nscriptura\nscriptus\nscuta\nsecat\nsecreto\nsecretum\nsecum\nsecundis\nsecundo\nsecundus\nsecuntur\nsecura\nsecuritatem\nsecurus\nsecus\nsecuti\nsecutus\nsed\nsedecim\nsedem\nsedens\nsedere\nsedet\nsedibus\nsedis\nseditionem\nseditionis\nsedulo\nseges\nsegetes\nsegnis\nsegnius\nseio\nseius\nsella\nsem\nsemet\nsemine\nseminibus\nseminis\nsemper\nsemperque\nsempronio\nsempronius\nsenatores\nsenatorum\nsenatus\nseneca\nsenectae\nsenectutem\nsenectutis\nsenex\nsenibus\nsenior\nsenis\nsenserit\nsensibus\nsensim\nsensisse\nsensit\nsensus\nsententiam\nsententiarum\nsententiis\nsentiat\nsentio\nsentiret\nsentit\nsentiunt\nseparatim\nseptem\nseptentrionem\nseptimo\nseptimum\nseptuagensimo\nseptuaginta\nsepulchrum\nsepulcrum\nsequantur\nsequar\nsequatur\nsequebantur\nsequebatur\nsequens\nsequentem\nsequentia\nsequentibus\nsequentis\nsequerentur\nsequeretur\nsequetur\nsequitur\nsequor\nsequuntur\nsera\nsereno\nserito\nseritur\nserius\nsermones\nsermonibus\nsermonis\nsero\nserpens\nserpentes\nserpentibus\nserpentium\nserta\nseruandum\nseruant\nseruari\nseruata\nseruatur\nseruauit\nseruet\nseruiat\nseruilius\nseruio\nseruire\nseruis\nseruitutem\nseruitutis\nseruius\nserum\nseruom\nseruorum\nseruus\nsese\nsestertium\nset\nseuere\nseueritas\nseueritatem\nseuero\nseuerus\nsexagensimo\nsexaginta\nsextarios\nsexto\nsextus\nsexus\nsí\nsibimet\nsicca\nsiccis\nsicco\nsiccum\nsiciliam\nsiculis\nsicuti\nsidere\nsideribus\nsiderum\nsidus\nsiet\nsigna\nsignificant\nsignificari\nsignificationem\nsignificatur\nsignificet\nsignis\nsignorum\nsignum\nsilentium\nsiluas\nsiluestris\nsiluis\nsimiles\nsimilia\nsimilibus\nsimilis\nsimiliter\nsimilitudinem\nsimilitudo\nsimplex\nsimpliciter\nsimulacra\nsimulacrum\nsimulatione\nsimulque\nsimus\nsine\nsingularem\nsingularis\nsingulis\nsingulorum\nsingulos\nsinistrum\nsinit\nsint\nsinus\nsiqua\nsiquidem\nsiquis\nsistit\nsit\nsita\nsitus\nsiue\nsocero\nsocerum\nsocietatem\nsocietatis\nsociis\nsociorum\nsocius\nsocrates\nsodales\nsolacia\nsolacium\nsolam\nsoleant\nsoleat\nsolebant\nsolebat\nsolemus\nsolent\nsoleo\nsolere\nsolet\nsolido\nsolidum\nsolis\nsoliti\nsolitos\nsolitudines\nsolitus\nsollemnia\nsollertia\nsollicitudin\nsollicitudinem\nsollicitus\nsolos\nsolstitium\nsoluatur\nsoluendo\nsoluerit\nsoluitur\nsolus\nsoluta\nsolutis\nsoluto\nsolutus\nsomnus\nsonant\nsonat\nsonitus\nsono\nsonus\nsopor\nsordes\nsordibus\nsordida\nsororis\nsororum\nsors\nsortis\nsortitus\nspargere\nsparsa\nspatia\nspatiis\nspatio\nspatium\nspecialiter\nspecies\nspecimen\nspectaculo\nspectaculum\nspectant\nspectari\nspectet\nspeculum\nspecus\nspem\nsperare\nsperat\nspero\nspes\nspicula\nspina\nspiritus\nsplendore\nspolia\nspoliis\nspondes\nsponte\nspuma\nstabat\nstabulis\nstadia\nstagna\nstantem\nstaret\nstatimque\nstationes\nstatius\nstatuas\nstatuere\nstatuit\nstatus\nstellae\nstellarum\nstellis\nstercus\nsterilis\nstetit\nsticho\nstichus\nstilo\nstipendia\nstipendium\nstipulari\nstipulationem\nstipulationis\nstipulatus\nstipuletur\nstirpem\nstirpis\nstoici\nstomachum\nstrage\nstrepitu\nstudia\nstudiis\nstudiorum\nstudiose\nstudium\nstulte\nstultitia\nstultus\nstupet\nstupro\nstuprum\nsuadere\nsuadet\nsuam\nsuaque\nsuarum\nsuas\nsubegit\nsubest\nsubeunt\nsubiecit\nsubiecta\nsubinde\nsubire\nsubito\nsublata\nsublatis\nsublato\nsublatum\nsublime\nsublimis\nsubsidium\nsubstituto\nsubstitutus\nsubter\nsubtiliter\nsuccedere\nsuccedit\nsuccessit\nsuccessorem\nsuccurrere\nsuccurrit\nsuco\nsucus\nsudore\nsues\nsufficere\nsufficiat\nsufficit\nsuffragiis\nsuffragium\nsuis\nsullam\nsulpicius\nsumere\nsumitur\nsummas\nsumme\nsummus\nsumpsit\nsumpta\nsumptibus\nsumptus\nsumus\nsunto\nsuom\nsuorum\nsuos\nsuperare\nsuperauit\nsuperba\nsuperbiam\nsuperbo\nsuperbus\nsuperesse\nsuperest\nsuperiora\nsuperiores\nsuperioribus\nsuperioris\nsuperiorum\nsuperis\nsuperius\nsuperne\nsuperos\nsuperque\nsupersit\nsuperstes\nsupersunt\nsuperuacua\nsuperuacuum\nsuperum\nsupplementum\nsupplex\nsupplicatio\nsupplicio\nsupplicium\nsupra\nsuprema\nsupremum\nsurgere\nsurgit\nsursum\nsuscepit\nsusceptum\nsuscipere\nsuscipit\nsuspectam\nsuspectus\nsuspendisse\nsuspensa\nsuspicari\nsuspicionem\nsuspicor\nsustineri\nsustinet\nsustinuit\nsustulit\nsuus\nsyllabam\nsyllabis\nsyracusis\nsyriam\ntabellas\ntabulam\ntabularum\ntabulis\ntacere\ntacito\ntacitus\ntactu\ntaedio\ntalem\ntalenta\ntales\ntalia\ntalibus\ntalis\ntalium\ntamdiu\ntamen\ntametsi\ntamquam\ntamque\ntandem\ntangere\ntangit\ntantam\ntantaque\ntantos\ntantummodo\ntantumque\ntantundem\ntantus\ntarde\ntardius\ntarentum\ntarquinius\ntartara\ntauri\ntaurus\nté\ntecta\ntectis\ntecto\ntectum\ntecum\ntegit\ntela\ntelis\ntellure\ntelluris\ntellus\ntelorum\ntelum\ntemere\ntemeritatem\ntemperantia\ntemperat\ntempestas\ntempestates\ntempestatibus\ntempla\ntemplis\ntemplorum\ntemplum\ntempor\ntempore\ntemporibus\ntemporis\ntemporum\ntemptare\ntemptat\ntempus\ntendere\ntendit\nteneant\nteneatur\ntenebant\ntenebat\ntenebitur\ntenebris\ntenens\ntenentur\nteneo\ntenera\nteneretur\nteneris\ntenero\ntenes\ntenetur\ntenuem\ntenuere\ntenuerunt\ntenues\ntenuisse\ntenuit\ntenus\nteque\nterentius\nteres\ntergo\ntergum\nteritur\nterminos\nterna\nternos\nterraeque\nterram\nterraque\nterrarum\nterras\nterret\nterribilis\nterris\nterrorem\ntertiam\ntertio\ntertius\ntestamento\ntestamentum\ntestatorem\ntestatoris\ntestatus\ntestes\ntestibus\ntestimonio\ntestimonium\ntestis\ntestium\ntestor\ntetigit\nteucros\ntexit\nthalamos\ntheatro\ntheatrum\nthebis\ntheophrastus\ntheseus\nthessaliae\nthraciae\ntiberis\ntiberius\ntibia\ntigris\ntimendum\ntiment\ntimeo\ntimeri\ntimet\ntimorem\ntimoris\ntimuit\ntincidunt\ntiro\ntitan\ntitio\ntitius\ntitulo\ntitulus\ntogam\ntolerare\ntollere\ntollitur\ntollunt\ntoris\ntormentis\ntoros\ntorqueri\ntorquet\ntortor\ntorum\ntotas\ntotidemque\ntotiens\ntotis\ntotius\ntotos\ntotumque\ntotus\ntrabes\ntractari\ntractatus\ntractus\ntradere\ntradiderit\ntradiderunt\ntradidit\ntradita\ntraditus\ntraduntur\ntrahens\ntrahere\ntrahit\ntrahunt\ntraiano\ntraianus\ntraiecit\ntranseat\ntranseunt\ntransferri\ntransgressus\ntransiit\ntransire\ntransisse\ntransitus\ntranslata\ntranslatum\ntranstulit\ntraxit\ntrebatius\ntrecentos\ntrepida\ntres\ntria\ntribuit\ntribunali\ntribunatum\ntribunis\ntribunorum\ntribunus\ntribus\ntributa\ntributum\ntriduo\ntriduum\ntriennium\ntrigensimo\ntrigesimo\ntriginta\ntriplex\ntristique\ntristis\ntristitia\ntrita\ntritici\ntriticum\ntritum\ntriumphauit\ntriumphus\ntroiam\ntroianis\ntroianorum\ntroianos\ntruces\ntrunco\ntú\ntuam\ntuarum\ntuas\ntuba\ntubero\ntuenda\ntueri\ntuetur\ntuis\ntulerit\ntulerunt\ntulisset\ntulit\ntullio\ntullius\ntumor\ntumulo\ntumultus\ntumulum\ntune\ntunicam\ntuom\ntuorum\ntuos\ntuque\ntura\nturbam\nturbata\nturbidus\nturbine\nture\nturis\nturmas\nturno\nturnus\nturpem\nturpis\nturpiter\nturpius\nturres\nturribus\nturris\ntusculano\ntusculanum\ntussim\ntuta\ntutelam\ntutius\ntutores\ntutoribus\ntutoris\ntutus\ntuus\ntyranno\ntyrannus\nubera\nubicumque\nubique\nulcera\nulceribus\nulcus\nulixes\nullam\nullamcorper\nullis\nullius\nullo\nullus\nulpianus\nulterius\nultimam\nultimis\nultimo\nultimus\nultionem\nultor\nultrices\nultro\numbris\numeros\numida\numorem\numoris\numquam\nunam\nuncia\nundas\nundecimo\nundique\nundis\nungues\nunguibus\nunicum\nuniuersam\nuniuersos\nuniuersum\nunius\nuno\nunquam\nunum\nunusquisque\nurbana\nurbanis\nurbes\nurbibus\nurbis\nurbium\nurbs\nurget\nurinam\nurit\nurna\nusibus\nusquam\nusque\nusucapere\nusum\nusurae\nusurarum\nusuris\nusurum\nusus\nút\nutamur\nutar\nutatur\nutcumque\nutebantur\nutebatur\nutendum\nuterentur\nuteretur\nutero\nuterque\nutetur\nutiles\nutilia\nutilior\nutilissimum\nutilitatis\nutiliter\nutilius\nutimur\nutinam\nutique\nutitur\nutor\nutpote\nutque\nutramque\nutraque\nutrimque\nutrique\nutrisque\nutriusque\nutroque\nutrumne\nutrumque\nutuntur\nuxoris\nvacare\nvacat\nvacuam\nvacuo\nvacuum\nvada\nvadis\nvado\nvae\nvaga\nvagus\nvalde\nvaleant\nvaleat\nvalebit\nvalent\nvaleret\nvalerio\nvalerius\nvaletudinem\nvaletudinis\nvaletudo\nvalido\nvallo\nvallum\nvaluit\nvana\nvapore\nvarias\nvarietate\nvarius\nvarronem\nvarus\nvasa\nvasis\nvasto\nvatis\nvatum\nvectigalia\nvectigalibus\nvectus\nvehementer\nvehementius\nvehicula\nveios\nvel\nvela\nvelimus\nvelint\nvelit\nvellem\nvellent\nvellere\nvellet\nvelox\nveluti\nvenas\nvendere\nvendiderit\nvendidit\nvenditionem\nvenditorem\nvenditoris\nvenena\nvenenis\nveneno\nvenenum\nvenerant\nvenerat\nvenerem\nvenerint\nvenerit\nvenerunt\nveniamus\nveniant\nveniat\nveniebat\nveniens\nvenientem\nveniet\nvenimus\nvenio\nvenirent\nveniret\nvenissent\nvenisset\nvenit\nveniunt\nventer\nventis\nventorum\nventos\nventrem\nventris\nventum\nventura\nventurum\nventus\nvenus\nveram\nverba\nverbera\nverberibus\nverbis\nverborum\nverbum\nverecundiam\nvereor\nvereri\nvergilius\nverisimile\nveritas\nveritatem\nveritatis\nveritus\nverius\nverno\nvero\nverres\nversantur\nversari\nversatus\nversibus\nverso\nversus\nvertere\nverticem\nvertitur\nverus\nvesicae\nvesperi\nvestae\nvestes\nvestibulo\nvestibulum\nvestibus\nvestigiis\nvestigium\nvestimenta\nvestis\nvestros\nvestrum\nvetant\nvetat\nvetera\nveteres\nveteribus\nveteris\nveterum\nvetuit\nvetustate\nviam\nviarum\nvias\nvicem\nvicensimo\nvicesimo\nvicina\nvicinis\nvicino\nvicinus\nvicisse\nvicissim\nvicit\nvicta\nvictima\nvictis\nvictores\nvictoriam\nvictoriati\nvictoribus\nvictoris\nvictus\nvideamus\nvideantur\nvideas\nvideatur\nvidebam\nvidebantur\nvidebatur\nvidebimus\nvidebis\nvidebitur\nvidebo\nvidebuntur\nvidelicet\nvidemus\nvidendum\nvidentur\nvideor\nviderat\nviderem\nviderentur\nvideres\nvideretur\nviderit\nvidero\nviderunt\nvides\nvidete\nvidetis\nvidetur\nvidimus\nvidisset\nvidisti\nvidit\nvigilia\nviginti\nvigor\nviiii\nvilis\nvillam\nvim\nvina\nvincat\nvincere\nvincitur\nvincla\nvinclis\nvinctum\nvincula\nvinculis\nvinculum\nvindicari\nvindicat\nvindicta\nvineis\nvino\nvinum\nviolentia\nvires\nvirga\nvirginis\nvirgis\nvirgo\nvirgulta\nviribus\nviridis\nvirilem\nvirilis\nviris\nviritim\nvirium\nvirorum\nviros\nvirtus\nvirtutes\nvirtutibus\nvirtutis\nvirtutum\nvirus\nvisam\nviscera\nvisceribus\nvisere\nviso\nvisus\nvitae\nvitam\nvitare\nvitellius\nvites\nvitia\nvitibus\nvitiis\nvitiorum\nvitiosa\nvitiosum\nvitis\nvitium\nviuat\nviuendi\nviuendum\nviueret\nviuit\nviuos\nviuum\nviuunt\nviuus\nvivamus\nvixdum\nvixisse\nvixit\nvixque\nvobiscum\nvocabant\nvocabatur\nvocabulis\nvocabulum\nvocalis\nvocamus\nvocantur\nvocari\nvocas\nvocatus\nvocauit\nvoces\nvocibus\nvocis\nvoco\nvolat\nvolebant\nvolebat\nvolens\nvolentem\nvolentibus\nvolet\nvolgo\nvolgus\nvolnere\nvolneribus\nvolnus\nvolo\nvoltus\nvolucres\nvolucrum\nvoluerit\nvoluerunt\nvoluisset\nvoluisti\nvoluit\nvolumine\nvolumus\nvoluntatem\nvoluntatis\nvoluptates\nvoluptatibus\nvoluptatis\nvolutpat\nvomere\nvos\nvota\nvotis\nvoto\nvotum\nvox\nvuas\nvulgo\nvulgus\nvulnere\nvulneribus\nvulneris\nvulnus\nvultus\n"
  },
  {
    "path": "mocodo/resources/pristine_sandbox.mcd",
    "content": "AYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/1_input.mcd",
    "content": "Bureau: num. bureau\nRattacher, 11 [?] Bureau, 1N [?] Département\nDépartement: num. département, budget département\nDépendre, 11 [?] Projet, 1N [?] Département\nProjet: num. projet, nom projet, budget projet\n\nSe Situer, 11 [?]  Téléphone, 1N [?] Bureau\n:\nDiriger, 11 [?] Département, 01 [?] Employé\nTravailler, 1N [?] Projet, 01 [?] Employé\n\nTéléphone: num. téléphone\nJoindre, 1N [?] Téléphone, 11 [?] Employé\nEmployé: matricule, nom employé, adr. employé\nAssumer, 1N [?] Employé, 1N [?] Fonction: date début, date fin\nFonction: num. fonction, salaire\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/1_output.mcd",
    "content": "Bureau: num. bureau\nRattacher, 11 [Tout bureau est rattaché à un département.] Bureau, 1N [Tout département compte au moins un bureau.] Département\nDépartement: num. département, budget département\nDépendre, 11 [Un projet dépend d'un et un seul département.] Projet, 1N [Il y a au moins un projet par département.] Département\nProjet: num. projet, nom projet, budget projet\n\nSe Situer, 11 [Le téléphone d'un employé se situe dans son bureau.]  Téléphone, 1N [Il y a un ou plusieurs téléphones par bureau.] Bureau\n:\nDiriger, 11 [Tout département a un directeur.] Département, 01 [Un employé peut être le directeur d'au plus un département.] Employé\nTravailler, 1N [Plusieurs employés peuvent travailler sur un même projet.] Projet, 01 [Un employé travaille sur au plus un projet.] Employé\n\nTéléphone: num. téléphone\nJoindre, 1N [Un téléphone peut être attribué à plusieurs employés du même bureau.] Téléphone, 11 [Un employé n'a qu'un seul téléphone.] Employé\nEmployé: matricule, nom employé, adr. employé\nAssumer, 1N [Un employé peut avoir assumé différentes fonctions.] Employé, 1N [Une même fonction peut avoir été remplie par différents employés.] Fonction: date début, date fin\nFonction: num. fonction, salaire\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/2_input.mcd",
    "content": "Rejoindre, 01 [?] Rivière, 0N [?] Rivière\nRivière: pos. source, nom rivière, longueur, position fin\nSe Jeter, 01 [?] Rivière, 1N [?] Mer\nMer: nom mer, surface mer\n:\n\nCrue, 1N [?] Date, 0N [?] Ville, 0N [?] Rivière: durée crue, hauteur atteinte\nTraverser, 0N [?] Rivière, 0N [?] Ville: ordre traversée\nArroser, 1N [?] Rivière, 0N [?] Pays\nBaigner, 1N [?] Mer, 0N [?] Pays: longueur côte\n:\n\nDate: date\nVille: pos. ville, nom ville\nDF, 11 [?] Ville, 1N [?] Pays\nPays: nom pays, surface pays\nToucher, 0N [?] Pays, 0N [?] Pays\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/2_output.mcd",
    "content": "Rejoindre, 01 [Une rivière peut rejoindre au plus une autre rivière.] Rivière, 0N [Une rivière a un nombre quelconque d'affluents.] Rivière\nRivière: pos. source, nom rivière, longueur, position fin\nSe Jeter, 01 [Une rivière peut se jeter dans au plus une mer.] Rivière, 1N [Une mer reçoit au moins un fleuve.] Mer\nMer: nom mer, surface mer\n:\n\nCrue, 1N [À toute date répertoriée dans la base, il y a au moins une crue.] Date, 0N [Une ville peut subir un nombre quelconque de crues.] Ville, 0N [Une rivière peut avoir des crues.] Rivière: durée crue, hauteur atteinte\nTraverser, 0N [Une rivière peut traverser un nombre quelconque de villes.] Rivière, 0N [Une ville peut être traversée par un nombre quelconque de rivières.] Ville: ordre traversée\nArroser, 1N [Une rivière arrose au moins un pays.] Rivière, 0N [Un pays peut être arrosé par un nombre quelconque de rivières.] Pays\nBaigner, 1N [Une mer baigne au moins un pays.] Mer, 0N [Un pays peut avoir des côtes.] Pays: longueur côte\n:\n\nDate: date\nVille: pos. ville, nom ville\nDF, 11 [Une ville appartient à exactement un pays.] Ville, 1N [Un pays compte au moins une ville.] Pays\nPays: nom pays, surface pays\nToucher, 0N [Un pays peut être limitrophe à un nombre quelconque d'autres pays.] Pays, 0N [Un pays peut être limitrophe à un nombre quelconque d'autres pays.] Pays\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/3_input.mcd",
    "content": ":\n:\nDF2, 11 Ville, 0N Pays\nVille: code ville, nom ville, population, code postal\nDF1, 0N Ville, 11 Producteur\n\nLangue: code_langue, nom_langue, famille\nParler, 0N Langue, 1N Pays\nPays: code pays, nom pays, capitale, population, monnaie\nDF3, 0N Ville, 11 Distributeur\nProducteur: id producteur, nom commercial, date de création, site web\n\nAka, 0N Langue, 1N Film: titre localisé, statut titre\nDF6, 01 Film, 0N Langue\nDistribuer, 0N Pays, 0N Distributeur, 0N Film: date de sortie, nombre de copies, nombre d'entrées\nDistributeur: id distributeur, nom distributeur, type, site web\nProduire, 1N Producteur, 1N Film: budget, date de début, date de fin\n\nGenre: id genre, nom genre, descriptif\nDF4, 1N Genre, 11 Film\nFilm: num. d'exploitation, titre original, durée, procédé couleur, procédé son, synopsis, restriction âge\nParticiper, 0N Fonction, 1N Film, 1N Personne: rang dans la fonction, salaire\nFonction: id fonction, intitulé, département\n\nÊtre sous-genre, 0N Genre, 01 Genre\nDF5, 1N Prise de Vues, 11 Film\n:\nJouer, 0N Film, 0N Personne, 11 Personnage: importance du rôle, cachet\nPersonne: id personne, nom, prénom, genre, date de naissance, biographie, photo, téléphone, adresse\n\n:\nPrise de Vues: procédé, format, largeur, définition\nÊtre en lien avec, 0N Personnage, 0N Personnage: nature de la relation\nPersonnage: id personnage, nom, âge, genre, description\n:\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_examples/3_output.mcd",
    "content": ":\n:\nDF2, 11 [Une ville appartient à un et un seul pays.] Ville, 0N [Un pays peut avoir un nombre quelconque de villes.] Pays\nVille: code ville, nom ville, population, code postal\nDF1, 0N [Une ville peut accueillir un nombre quelconque de producteurs.] Ville, 11 [Un producteur est basé dans une et une seule ville.] Producteur\n\nLangue: code_langue, nom_langue, famille\nParler, 0N [Une langue est parlée dans zéro (langue morte), un ou plusieurs pays.] Langue, 1N [Un pays parle au moins une langue.] Pays\nPays: code pays, nom pays, capitale, population, monnaie\nDF3, 0N [Une ville peut accueillir un nombre quelconque de distributeurs.] Ville, 11 [Un distributeur est basé dans une et une seule ville.] Distributeur\nProducteur: id producteur, nom commercial, date de création, site web\n\nAka, 0N [Une langue peut être associée à un nombre quelconque de films.] Langue, 1N [Un film peut avoir des titres dans plusieurs langues.] Film: titre localisé, statut titre\nDF6, 01 [Un film a une langue originale ou pas (film muet).] Film, 0N [Une langue peut être la langue originale de plusieurs films.] Langue\nDistribuer, 0N [Un pays peut être concerné par un nombre quelconque de distributions.] Pays, 0N [Un distributeur peut distribuer un nombre quelconque de films dans différents pays.] Distributeur, 0N [Un film peut être distribué dans un nombre quelconque de pays.] Film: date de sortie, nombre de copies, nombre d'entrées\nDistributeur: id distributeur, nom distributeur, type, site web\nProduire, 1N [Un producteur produit au moins un film.] Producteur, 1N [Un film est produit par au moins un producteur.] Film: budget, date de début, date de fin\n\nGenre: id genre, nom genre, descriptif\nDF4, 1N [Un genre peut caractériser plusieurs films.] Genre, 11 [Tout film appartient à un et un seul genre.] Film\nFilm: num. d'exploitation, titre original, durée, procédé couleur, procédé son, synopsis, restriction âge\nParticiper, 0N [Une fonction peut être remplie sur plusieurs films.] Fonction, 1N [Un film ne peut se faire sans participants.] Film, 1N [Une personne peut participer à plusieurs films.] Personne: rang dans la fonction, salaire\nFonction: id fonction, intitulé, département\n\nÊtre sous-genre, 0N [Un genre peut avoir zéro ou plusieurs sous-genres.] Genre, 01 [Un genre peut être sous-genre d'au plus un autre genre.] Genre\nDF5, 1N [Un procédé de prise de vues peut être utilisé pour plusieurs films.] Prise de Vues, 11 [Un film utilise une et une seule prise de vues.] Film\n:\nJouer, 0N [Un film peut comporter plusieurs personnages.] Film, 0N [Une personne peut jouer dans plusieurs films.] Personne, 11 [Un personnage est incarné par un seul acteur dans un seul film.] Personnage: importance du rôle, cachet\nPersonne: id personne, nom, prénom, genre, date de naissance, biographie, photo, téléphone, adresse\n\n:\nPrise de Vues: procédé, format, largeur, définition\nÊtre en lien avec, 0N [Un personnage peut être en relation avec plusieurs autres personnages.] Personnage, 0N [Un personnage peut être en relation avec plusieurs autres personnages.] Personnage: nature de la relation\nPersonnage: id personnage, nom, âge, genre, description\n:\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/cards_fr.md",
    "content": "Tu es un enseignant spécialiste des Modèles Conceptuels de Données (MCD) de la méthode MERISE.\n\n# Syntaxe de Mocodo\n\nPour décrire les MCD, tu utilises le langage Mocodo :\n\n- Chaque ligne définit une entité ou une association.\n- L'ordre des lignes, ainsi que les sauts de ligne, sont importants pour le plongement.\n- Une entité E avec les attributs a1, ..., an est définie par la ligne :\n  ```mocodo\n  E: a1, ..., an\n  ```\n- Une association A entre les entités E1, ..., Em avec les attributs a1, ..., an est définie par la ligne:\n  ```mocodo\n  A, XX E1, ..., XX EM: a1, ... am\n  ```\n  ... où les XX sont des couples de cardinalités minimale et maximale en notation _look here_. Ils peuvent être: `01`, `0N`, `11` et `1N`. Ils peuvent être suivis d'un chevron `>` ou `<` pour indiquer une flèche.\n- Les cardinalités sont en notation _look here_, c'est-à-dire que `A, 01 E1, 1N E2` se lira : pour une occurrence de E1, il peut y avoir 0 ou 1 occurrence de E2 ; pour une occurrence de E2, il peut y avoir 1 ou plusieurs occurrences de E1.\n- Entre une cardinalité et l'entité qu'elle distingue, on peut insérer entre crochets droits une courte explication de la cardinalité, p. ex.:\n  ```mocodo\n  A, 01 [Pour une occurrence de E1, il y au plus une occcurence de E2.] E1, 1N [Pour une occurrence de E2, il y au moins une occurrence de E1.] E2\n  ```\n- Si les cardinalités sont erronées, fais comme si elles étaient correctes : une explication absurde rendra évident le problème.\n- Les associations ont pour nom, en général un verbe, mais parfois un substantif et parfois « DF » pour « dépendance fonctionnelle ».\n\n# Instructions\n\n- Remplace les `[?]` par de courtes explications de cardinalités.\n- Utilise la langue du MCD.\n- Renvoie-le comme un code Markdown.\n- Ne modifie en aucun cas le reste du code.\n- En particulier, respecte les sauts de ligne.\n- N'écris rien avant le code complété.\n- N'écris rien après le code complété.\n\n# Exemples de données et de résultats attendus\n \n{examples}\n\n# MCD à compléter\n\n{question}\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/types_examples/1_input.mcd",
    "content": "Recevoir, 01 Rivière, 0N Rivière\nRivière: pos. source, nom rivière, longueur, position fin\nSe Jeter, 01 Rivière, 1N Mer\nMer: nom mer, surface mer\n:\n\nCrue, 1N Date, 0N Ville, 0N Rivière: durée crue, hauteur atteinte\nTraverser, 0N Rivière, 0N Ville: ordre traversée\nArroser, 1N Rivière, 0N Pays\nBaigner, 1N Mer, 0N Pays: longueur côte\n:\n\nDate: date\nVille: pos. ville, nom ville\nDF, 11 Ville, 1N Pays\nPays: nom pays, surface pays\nToucher, 0N Pays, 0N Pays"
  },
  {
    "path": "mocodo/resources/prompts/chat/types_examples/1_output.mcd",
    "content": "Recevoir, 01 Rivière, 0N Rivière\nRivière: pos. source [POINT], nom rivière [VARCHAR(255)], longueur [INTEGER], position fin [POINT]\nSe Jeter, 01 Rivière, 1N Mer\nMer: nom mer [VARCHAR(255)], surface mer [DECIMAL(15,2)]\n:\n\nCrue, 1N Date, 0N Ville, 0N Rivière: durée crue [INTEGER], hauteur atteinte [DECIMAL(5,2)]\nTraverser, 0N Rivière, 0N Ville: ordre traversée [INTEGER]\nArroser, 1N Rivière, 0N Pays\nBaigner, 1N Mer, 0N Pays: longueur côte [INTEGER]\n:\n\nDate: date [DATE]\nVille: pos. ville [POINT], nom ville [VARCHAR(255)]\nDF, 11 Ville, 1N Pays\nPays: nom pays [VARCHAR(255)], surface pays [DECIMAL(15,2)]\nToucher, 0N Pays, 0N Pays"
  },
  {
    "path": "mocodo/resources/prompts/chat/types_examples/2_input.mcd",
    "content": ":\n:\nDF2, 11 Ville, 0N Pays\nVille: code ville, nom ville, population, code postal\nDF1, 0N Ville, 11 Producteur\n\nLangue: code_langue, nom_langue, famille\nParler, 0N Langue, 1N Pays\nPays: code pays, nom pays, capitale, population, monnaie\nDF3, 0N Ville, 11 Distributeur\nProducteur: id producteur, nom commercial, date de création, site web\n\nAka, 0N Langue, 1N Film: titre localisé, statut titre\nDF6, 01 Film, 0N Langue\nDistribuer, 0N Pays, 0N Distributeur, 0N Film: date de sortie, nombre de copies, nombre d'entrées\nDistributeur: id distributeur, nom distributeur, type, site web\nProduire, 1N Producteur, 1N Film: budget, date de début, date de fin\n\nGenre: id genre, nom genre, descriptif\nDF4, 1N Genre, 11 Film\nFilm: num. d'exploitation, titre original, durée, procédé couleur, procédé son, synopsis, restriction âge\nParticiper, 0N Fonction, 1N Film, 1N Personne: rang dans la fonction, salaire\nFonction: id fonction, intitulé, département\n\nÊtre sous-genre, 0N Genre, 01 Genre\nDF5, 1N Prise de Vues, 11 Film\n:\nJouer, 0N Film, 0N Personne, 11 Personnage: importance du rôle, cachet\nPersonne: id personne, nom, prénom, genre, date de naissance, biographie, photo, téléphone, adresse\n\n:\nPrise de Vues: procédé, format, largeur, définition\nÊtre en lien avec, 0N Personnage, 0N Personnage: nature de la relation\nPersonnage: id personnage, nom, âge, genre, description\n:\n"
  },
  {
    "path": "mocodo/resources/prompts/chat/types_examples/2_output.mcd",
    "content": ":\n:\nDF2, 11 Ville, 0N Pays\nVille: code ville [VARCHAR(10)], nom ville [VARCHAR(255)], population [INTEGER], code postal [VARCHAR(10)]\nDF1, 0N Ville, 11 Producteur\n\nLangue: code_langue [CHAR(2)], nom_langue [VARCHAR(50)], famille [VARCHAR(50)]\nParler, 0N Langue, 1N Pays\nPays: code pays [CHAR(2)], nom pays [VARCHAR(100)], capitale [VARCHAR(100)], population [INTEGER], monnaie [VARCHAR(50)]\nDF3, 0N Ville, 11 Distributeur\nProducteur: id producteur [VARCHAR(20)], nom commercial [VARCHAR(255)], date de création [DATE], site web [VARCHAR(255)]\n\nAka, 0N Langue, 1N Film: titre localisé [VARCHAR(255)], statut titre [VARCHAR(50)]\nDF6, 01 Film, 0N Langue\nDistribuer, 0N Pays, 0N Distributeur, 0N Film: date de sortie [DATE], nombre de copies [INTEGER], nombre d'entrées [INTEGER]\nDistributeur: id distributeur [VARCHAR(20)], nom distributeur [VARCHAR(255)], type [VARCHAR(50)], site web [VARCHAR(255)]\nProduire, 1N Producteur, 1N Film: budget [DECIMAL(15,2)], date de début [DATE], date de fin [DATE]\n\nGenre: id genre [VARCHAR(20)], nom genre [VARCHAR(100)], descriptif [TEXT]\nDF4, 1N Genre, 11 Film\nFilm: num. d'exploitation [VARCHAR(20)], titre original [VARCHAR(255)], durée [INTEGER], procédé couleur [VARCHAR(50)], procédé son [VARCHAR(50)], synopsis [TEXT], restriction âge [VARCHAR(10)]\nParticiper, 0N Fonction, 1N Film, 1N Personne: rang dans la fonction [INTEGER], salaire [DECIMAL(12,2)]\nFonction: id fonction [VARCHAR(20)], intitulé [VARCHAR(100)], département [VARCHAR(100)]\n\nÊtre sous-genre, 0N Genre, 01 Genre\nDF5, 1N Prise de Vues, 11 Film\n:\nJouer, 0N Film, 0N Personne, 11 Personnage: importance du rôle [VARCHAR(50)], cachet [DECIMAL(12,2)]\nPersonne: id personne [VARCHAR(20)], nom [VARCHAR(100)], prénom [VARCHAR(100)], genre [CHAR(1)], date de naissance [DATE], biographie [TEXT], photo [BLOB], téléphone [VARCHAR(20)], adresse [VARCHAR(255)]\n\n:\nPrise de Vues: procédé [VARCHAR(100)], format [VARCHAR(50)], largeur [DECIMAL(5,2)], définition [INTEGER]\nÊtre en lien avec, 0N Personnage, 0N Personnage: nature de la relation [VARCHAR(100)]\nPersonnage: id personnage [VARCHAR(20)], nom [VARCHAR(100)], âge [INTEGER], genre [CHAR(1)], description [TEXT]\n:"
  },
  {
    "path": "mocodo/resources/prompts/chat/types_fr.md",
    "content": "Tu es un enseignant spécialiste des Modèles Conceptuels de Données (MCD) de la méthode MERISE.\n\n# Syntaxe de Mocodo\n\nPour décrire les MCD, tu utilises le langage Mocodo :\n\n- Chaque ligne définit une entité ou une association.\n- L'ordre des lignes, ainsi que les sauts de ligne, sont importants pour le plongement.\n- Une entité E avec les attributs a1, ..., an est définie par la ligne :\n  ```mocodo\n  E: a1, ..., an\n  ```\n- Une association A entre les entités E1, ..., Em avec les attributs a1, ..., an est définie par la ligne:\n  ```mocodo\n  A, XX E1, ..., XX EM: a1, ... am\n  ```\n  ... où les XX définissent les cardinalités minimale et maximale.\n- Après chaque attribut, on peut insérer entre crochets droits son type de données SQL, principalement : BINARY(n), BLOB, BOOLEAN, CHAR(n), DATE, DATETIME, DECIMAL(m,n), INTEGER, JSON, POINT, SMALLINT, TEXT, TIME, TIMESTAMP, VARCHAR(n).\n\n# Instructions\n\n- Remplace les `[?]` par le type approprié.\n- Renvoie le MCD complété comme un code Markdown.\n- Ne modifie en aucun cas le reste du code.\n- En particulier, respecte les sauts de ligne.\n- N'écris rien avant le code complété.\n- N'écris rien après le code complété.\n\n# Exemples de données et de résultats attendus\n \n{examples}\n\n# MCD à compléter\n\n{question}\n"
  },
  {
    "path": "mocodo/resources/relation_templates/_index.json",
    "content": "{\n  \"d2\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in D2 format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format D2\",\n    \"help_zh\": \"将概念模型转换为 D2 格式的关系模式\",\n    \"aliases\": []\n  },\n  \"dbml\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in DBML format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format DBML\",\n    \"help_zh\": \"将概念模型转换为 DBML 格式的关系模式\",\n    \"aliases\": [],\n    \"fr_examples\": {\n      \"dbml\": \"version de base\", \"dbml:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"sql\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for SQL\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour SQL\",\n    \"help_zh\": \"将概念模型转换为 SQL 的物理模型\",\n    \"aliases\": [\"ddl\"]\n  },\n  \"debug\": {\n    \"category\": \"cv\",\n    \"help_en\": \"list internal informations relative to the conversion into relational schema\",\n    \"help_fr\": \"liste des informations internes relatives à la conversion en schéma relationnel\",\n    \"help_zh\": \"列出与转换为关系模式相关的内部信息\",\n    \"aliases\": []\n  },\n  \"dependencies\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a dependency graph\",\n    \"help_fr\": \"convertit le modèle conceptuel en un graphe de dépendances\",\n    \"help_zh\": \"将概念模型转换为依赖图\",\n    \"aliases\": []\n  },\n  \"diagram\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational diagram in Mocodo syntax\",\n    \"help_fr\": \"convertit le modèle conceptuel en un diagramme relationnel au format Mocodo\",\n    \"help_zh\": \"将概念模型转换为 Mocodo 格式的关系图\",\n    \"aliases\": [],\n    \"fr_examples\": {\n      \"diagram\": \"version de base\", \"diagram:c\": \"avec contraintes d'unicité et d'optionalité\"\n    }\n  },\n  \"html\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in HTML format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format HTML\",\n    \"help_zh\": \"将概念模型转换为 HTML 格式的关系模式\",\n    \"aliases\": [],\n    \"fr_examples\": {\n      \"html\": \"version de base\", \"html:b\": \"avec _boilerplate_\", \"html:c\": \"avec contraintes d'unicité et d'optionalité\", \"html:e\": \"avec explications\", \"html:bce\": \"avec _boilerplate_, contraintes et explications\"\n    }\n  },\n  \"latex\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in LaTeX format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format LaTeX\",\n    \"help_zh\": \"将概念模型转换为 LaTeX 格式的关系模式\",\n    \"aliases\": [\"tex\"],\n    \"fr_examples\": {\n      \"latex\": \"version de base\", \"latex:b\": \"avec _boilerplate_\", \"latex:c\": \"avec contraintes d'unicité et d'optionalité\", \"latex:e\": \"avec explications\", \"latex:bce\": \"avec _boilerplate_, contraintes et explications\"\n    }\n  },\n  \"markdown\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in Markdown format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format Markdown\",\n    \"help_zh\": \"将概念模型转换为 Markdown 格式的关系模式\",\n    \"aliases\": [\"md\", \"mld\"],\n    \"fr_examples\": {\n      \"markdown\": \"version de base\", \"markdown:c\": \"avec contraintes d'unicité et d'optionalité\", \"markdown:e\": \"avec explications\", \"markdown:ce\": \"avec contraintes et explications\"\n    }\n  },\n  \"mssql\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for Microsoft SQL Server\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server\",\n    \"help_zh\": \"将概念模型转换为 Microsoft SQL Server 的物理模型\",\n    \"aliases\": [\"ms_sql\", \"sql_server\", \"sqlserver\"],\n    \"fr_examples\": {\n      \"mssql\": \"version de base\", \"mssql:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"mysql\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for MySQL\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour MySQL\",\n    \"help_zh\": \"将概念模型转换为 MySQL 物理模型\",\n    \"aliases\": [],\n    \"fr_examples\": {\n      \"mysql\": \"version de base\", \"mysql:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"oracle\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for Oracle DB\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour Oracle DB\",\n    \"help_zh\": \"将概念模型转换为 Oracle DB 的物理模型\",\n    \"aliases\": [\"oracle_db\"],\n    \"fr_examples\": {\n      \"oracle\": \"version de base\", \"oracle:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"postgresql\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for PostgreSQL\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour PostgreSQL\",\n    \"help_zh\": \"将概念模型转换为 PostgreSQL 的物理模型\",\n    \"aliases\": [\"postgres\"],\n    \"fr_examples\": {\n      \"postgresql\": \"version de base\", \"postgresql:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"sqlite\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a physical model for SQLite\",\n    \"help_fr\": \"convertit le modèle conceptuel en un modèle physique pour SQLite\",\n    \"help_zh\": \"将概念模型转换为 SQLite 的物理模型\",\n    \"aliases\": [],\n    \"fr_examples\": {\n      \"sqlite\": \"version de base\", \"sqlite:b\": \"avec _boilerplate_\"\n    }\n  },\n  \"text\": {\n    \"category\": \"cv\",\n    \"help_en\": \"convert the conceptual model into a relational schema in text format\",\n    \"help_fr\": \"convertit le modèle conceptuel en un schéma relationnel au format texte\",\n    \"help_zh\": \"将概念模型转换为文本格式的关系模式\",\n    \"aliases\": [\"txt\"],\n    \"fr_examples\": {\n      \"text\": \"version de base\", \"text:c\": \"avec contraintes d'unicité et d'optionalité\", \"html:e\": \"avec explications\", \"html:ce\": \"avec contraintes et explications\"\n    }\n  }\n}\n"
  },
  {
    "path": "mocodo/resources/relation_templates/d2.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in D2 format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format D2'\nhelp_zh: '将概念模型转换为 D2 格式的关系模式'\nstem_suffix: '_ddl'\nextension: 'd2'\nto_defer: true\nhighlight: 'text'\ntransform_datatype:\n  - order: 100\n    comment: 'Fill in empty data types with the default one.'\n    search: '^\\s*$'\n    replace: 'VARCHAR(42)'\n  - order: 300\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'UNSIGNED INT'\n  - order: 400\n    search: 'BOOLEAN_PLACEHOLDER'\n    replace: 'BOOLEAN'\ntransform_optionality:\n  - order: 100\n    comment: 'Replace BANG with NOT NULL.'\n    search: '^!$'\n    replace: 'NOT NULL'\n  - order: 200\n    comment: 'Replace QMARK with NULL. NB: without the double quotes, NULL is not rendered (https://github.com/terrastruct/d2/issues/1655)'\n    search: '^\\?$'\n    replace: '\"NULL\"'\ncompose_primary_key: '  \"{label}\":{filler}{datatype} OPENING_BRACE constraint: [PK] CLOSING_BRACE'\ncompose_normal_attribute: '  \"{label}\":{filler}{datatype} OPENING_BRACE constraint: [{optionality}] CLOSING_BRACE'\ncompose_primary_foreign_key: '  \"{label}\":{filler}{datatype} OPENING_BRACE constraint: [PK; FK] CLOSING_BRACE\\nADD_FOREIGN_KEY \"{this_relation_name}\".(\"{label}\") -> \"{outer_source}\".(\"{non_disambiguated_label}\")'\ncompose_foreign_key: '  \"{label}\":{filler}{datatype} OPENING_BRACE constraint: [FK; {optionality}] CLOSING_BRACE\\nADD_FOREIGN_KEY \"{this_relation_name}\".(\"{label}\") -> \"{outer_source}\".(\"{non_disambiguated_label}\")'\nadd_unicity_constraints:\n  - order: 100\n    search: '(  .+)$'\n    replace: '\\1; UNQ{unicities}'\ncolumn_separator: '\\n'\ncompose_relation: '\"{this_relation_name}\": {{ shape: sql_table\\n{columns}\\n}}'\ntransform_relation:\n  - order: 100\n    comment: 'Replace brace placeholders'\n    search: 'OPENING_BRACE (.+?) CLOSING_BRACE'\n    replace: '{\\1}'\n  - order: 200\n    search: '(UNQ\\d)(\\d+)'\n    replace: '\\1; UNQ\\2'\n    iterated: true\n  - order: 300\n    search: '(\\]\\})((?:; UNQ\\d)+)'\n    replace: '\\2\\1'\n  - order: 400\n    comment: 'Suppress useless UNQ constraint separator'\n    search: '(?m)({constraint: \\[); '\n    replace: '\\1'\n  - order: 500\n    comment: 'Suppress brackets with no semi-colon inside.'\n    search: '\\[([^\\];\\n]*)\\]'\n    replace: '\\1'\n  - order: 600\n    comment: 'Suppress empty constraints'\n    search: '(?m){constraint: }$'\n    replace: ''\nrelation_separator: '\\n\\n'\ncompose_relational_schema: '{relations}\\n'\ntransform_relational_schema:\n  - order: 100\n    comment: 'Move the foreign keys to the end of the document.'\n    search: '(?sm)^ADD_FOREIGN_KEY ([^\\n]+\\n)(.+)'\n    replace: '\\2\\nRef:\\1'\n    iterated: true\n  - order: 250\n    comment: 'Suppress multiple newlines between Ref lines.'\n    search: '(?m)^(Ref:.+)\\n+(?=Ref:)'\n    replace: '\\1\\n'\n  - order: 300\n    comment: 'Clean up the useless parenthesis (without comma inside).'\n    search: '(?m)^(Ref:.+)\\.\\((.+?)\\) -> (.+)\\.\\((.+?)\\)'\n    replace: '\\1.\\2 -> \\3.\\4'\n  - order: 400\n    comment: 'Suppress Ref:'\n    search: '(?m)^Ref:'\n    replace: ''\n"
  },
  {
    "path": "mocodo/resources/relation_templates/dbml-b.yaml",
    "content": "parent: 'dbml'\ncompose_relational_schema: 'Project \"{title}\" {{\\n  Note: ''Generated by Mocodo {version}''\\n}}\\n\\n{relations}\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/dbml.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in DBML format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format DBML'\nhelp_zh: '将概念模型转换为 DBML 格式的关系模式'\nfr_examples:\n  - order: 1\n    example: 'dbml'\n    explanation: 'version de base'\n  - order: 2\n    example: 'dbml:b'\n    explanation: 'avec _boilerplate_'\nstem_suffix: '_ddl'\nextension: 'dbml'\nto_defer: false\nhighlight: 'text'\ntransform_datatype:\n  - order: 100\n    comment: 'Fill in empty data types with the default one.'\n    search: '^\\s*$'\n    replace: 'VARCHAR(42)'\n  - order: 200\n    comment: 'Remove all spaces in the data type.'\n    search: ' +'\n    replace: '_'\n  - order: 300\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'UNSIGNED_INT'\n  - order: 400\n    search: 'BOOLEAN_PLACEHOLDER'\n    replace: 'BOOLEAN'\ntransform_optionality:\n  - order: 100\n    comment: 'Replace BANG with NOT NULL.'\n    search: '^!$'\n    replace: 'NOT NULL'\n  - order: 200\n    comment: 'Replace QMARK with NULL.'\n    search: '^\\?$'\n    replace: 'NULL'\ncompose_primary_key: '  \"{label}\"{filler}{datatype} [{optionality}] [pk]\\nADD_PRIMARY_KEY \"{label}\"'\ncompose_normal_attribute: '  \"{label}\"{filler}{datatype} [{optionality}]'\ncompose_primary_foreign_key: '  \"{label}\"{filler}{datatype} [{optionality}] [pk]\\nADD_PRIMARY_KEY \"{label}\"\\nADD_FOREIGN_KEY \"{this_relation_name}\".(\"{label}\") > \"{outer_source}\".(\"{non_disambiguated_label}\")'\ncompose_foreign_key: '  \"{label}\"{filler}{datatype} [{optionality}]\\nADD_FOREIGN_KEY \"{this_relation_name}\".(\"{label}\") > \"{outer_source}\".(\"{non_disambiguated_label}\")'\nadd_unicity_constraints:\n  - order: 100\n    search: '$'\n    replace: '\\nADD_CONSTRAINT u{unicities} \"{label}\"'\ncolumn_separator: '\\n'\ncompose_relation: 'Table \"{this_relation_name}\" {{\\n{columns}\\n  Indexes {{\\n    [pk] \\n  }}\\n}}'\ntransform_relation:\n  - order: 400\n    comment: 'Move the primary keys inside ''Indexes'' clause.'\n    search: '(?sm)^ADD_PRIMARY_KEY ([^\\n]+)\\n(.+?^    \\[pk\\] [^\\n]*)\\n'\n    replace: '\\2\\1, \\n'\n    iterated: true\n  - order: 500\n    comment: 'Accumulate the composite unique constraints inside ''Indexes'' clause.'\n    search: '(?sm)(^ADD_CONSTRAINT u\\d+)(\\d)( [^\\n]+)(\\n.+?)(^  \\})'\n    replace: '\\1\\3\\4    [unique] u\\2\\3\\n\\5'\n    iterated: true\n  - order: 600\n    comment: 'Accumulate the single unique constraints inside ''Indexes'' clause.'\n    search: '(?sm)^ADD_CONSTRAINT (u\\d [^\\n]+\\n)(.+?)(^  \\})'\n    replace: '\\2    [unique] \\1\\3'\n    iterated: true\n  - order: 700\n    comment: 'Group the constraints having the same number.'\n    search: '(?sm)^(    \\[unique\\] u\\d )([^\\n]+)(\\n.*?)\\1([^\\n]+)\\n'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 800\n    comment: 'Remove the pk lines which contain no comma, except a trailing comma.'\n    search: '(?m)^    \\[pk\\] [^\\n,]+, \\n'\n    replace: ''\n  - order: 900\n    comment: 'Remove the [pk] suffixes when it still exists a [pk] line.'\n    search: '(?ms) \\[pk\\](.+?^    \\[pk\\] )'\n    replace: '\\1'\n    iterated: true\n  - order: 1000\n    comment: 'Finalize Indexes'' line format.'\n    search: '(?m)^    (\\[\\w+\\]) (?:u\\d )?(.+\")(?:, )?'\n    replace: '    (\\2) \\1'\n  - order: 1100\n    comment: 'Clean up the useless parenthesis (without comma inside).'\n    search: '(?sm)^    \\(([^,\\n]+)\\) (\\[\\w+\\])'\n    replace: '    \\1 \\2'\n  - order: 1200\n    comment: 'Clean up the empty Indexes.'\n    search: '(?sm)^  Indexes \\{\\n  \\}\\n'\n    replace: ''\n  - order: 1300\n    comment: 'Merge brackets and reverse their contents.'\n    search: '\\[(.+?)\\] \\[(.+?)\\]'\n    replace: '[\\2, \\1]'\n    iterated: true\n  - order: 1400\n    comment: 'Suppress empty brackets.'\n    search: ' \\[\\]'\n    replace: ''\nrelation_separator: '\\n\\n'\ncompose_relational_schema: '{relations}\\n'\ntransform_relational_schema:\n  - order: 100\n    comment: 'Move the foreign keys to the end of the document.'\n    search: '(?sm)^ADD_FOREIGN_KEY ([^\\n]+\\n)(.+)'\n    replace: '\\2\\nRef:\\1'\n    iterated: true\n  - order: 200\n    comment: 'Group the foreign keys having the same origin and target.'\n    search: '(?m)^(Ref:.+)\\.\\((.+)\\) > (.+)\\.\\((.+)\\)\\n((?:.*\\n)*)^\\1\\.\\((.+)\\) > \\3\\.\\((.+)\\)'\n    replace: '\\1.(\\2, \\6) > \\3.(\\4, \\7)\\5'\n    iterated: true\n  - order: 250\n    comment: 'Suppress multiple newlines between Ref lines.'\n    search: '(?m)^(Ref:.+)\\n+(?=Ref:)'\n    replace: '\\1\\n'\n  - order: 300\n    comment: 'Clean up the useless parenthesis (without comma inside).'\n    search: '(?m)^(Ref:.+)\\.\\(([^,\\n]+)\\) > (.+)\\.\\(([^,\\n]+)\\)'\n    replace: '\\1.\\2 > \\3.\\4'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/ddl.yaml",
    "content": "parent: 'sql'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/debug.yaml",
    "content": "help_en: 'list internal informations relative to the conversion into relational schema'\nhelp_fr: 'liste des informations internes relatives à la conversion en schéma relationnel'\nhelp_zh: '列出与转换为关系模式相关的内部信息'\nstem_suffix: '_debug'\nextension: 'tsv'\nto_defer: false\nhighlight: 'tsv'\ncolumn_separator: ''\ncompose_relation: '{columns}'\nrelation_separator: ''\ntransform_relation:\n  - order: 100\n    search: '\\tNone'\n    replace: '\\t'\ncompose_relational_schema: 'this relation name\\tattribute\\toptionality\\tunicities\\tnature\\tis primary\\tadjacent source\\touter source\\tassociation name\\tdatatype\\tleg note\\n{relations}'\ncompose_foreign_key: '{this_relation_name}\\t{attribute}\\t{optionality}\\t{unicities}\\t{nature}\\t{is_primary}\\t{adjacent_source}\\t{outer_source}\\t{association_name}\\t{datatype}\\t{leg_note}\\n'\ncompose_normal_attribute: '{this_relation_name}\\t{attribute}\\t{optionality}\\t{unicities}\\t{nature}\\t{is_primary}\\t{adjacent_source}\\t{outer_source}\\t{association_name}\\t{datatype}\\t{leg_note}\\n'\ncompose_primary_foreign_key: '{this_relation_name}\\t{attribute}\\t{optionality}\\t{unicities}\\t{nature}\\t{is_primary}\\t{adjacent_source}\\t{outer_source}\\t{association_name}\\t{datatype}\\t{leg_note}\\n'\ncompose_primary_key: '{this_relation_name}\\t{attribute}\\t{optionality}\\t{unicities}\\t{nature}\\t{is_primary}\\t{adjacent_source}\\t{outer_source}\\t{association_name}\\t{datatype}\\t{leg_note}\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/dependencies.yaml",
    "content": "help_en: 'convert the conceptual model into a dependency graph'\nhelp_fr: 'convertit le modèle conceptuel en un graphe de dépendances'\nhelp_zh: '将概念模型转换为依赖图'\nstem_suffix: '_dependencies'\nextension: 'gv'\nto_defer: true\nhighlight: 'graphviz'\ncompose_primary_key: ''\ncompose_normal_attribute: ''\ncompose_foreign_key: '<-\"{outer_source}\"'\ncompose_primary_foreign_key: '<-\"{outer_source}\"'\ncolumn_separator: ''\ncompose_relation: '\"{this_relation_name}\"{columns}'\nrelation_separator: '\\n'\ntransform_relation:\n  - order: 100\n    comment: 'Present all the dependencies of the same relation on multiple lines'\n    search: '(\".+?\")<-(\".+?\")(.*)'\n    replace: '\\1\\3\\n  \\2 -> \\1'\n    iterated: true\ncompose_relational_schema: '// Generated by Mocodo {version}<DOUBLE_CR_PLACEHOLDER>digraph {{\\n  node [shape=box]\\n\\n{relations}\\n}}'\ntransform_relational_schema:\n  - order: 100\n    comment: 'Remove the independant relations'\n    search: '(?m)^\".+'\n    replace: ''\n  - order: 200\n    comment: 'Remove the empty lines'\n    search: '\\n+'\n    replace: '\\n'\n  - order: 300\n    comment: 'Remove the duplicated consecutive lines'\n    search: '(?m)^(.+\\n)\\1+'\n    replace: '\\1'\n  - order: 400\n    search: '<DOUBLE_CR_PLACEHOLDER>'\n    replace: '\\n\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/diagram-c.yaml",
    "content": "stem_suffix: '_mld'\nextension: 'mcd'\nto_defer: false\nhighlight: 'plain'\ncompose_primary_key: '_{label}'\ncompose_foreign_key: '#{label} > {outer_source} > {non_disambiguated_label}'\ncompose_normal_attribute: '{label}'\ncompose_primary_foreign_key: '_#{label} > {outer_source} > {non_disambiguated_label}'\ncompose_relation: '{this_relation_name}: {columns}'\nadd_optionality_constraints:\n  - order: 100\n    search: '^([^_][^>]+)$'\n    replace: '\\1{optionality}'\n  - order: 200\n    search: '^([^_].+?)( >)'\n    replace: '\\1{optionality}\\2'\ntransform_relation:\n  - order: 100\n    comment: 'By default, the first attribute is an identifier'\n    search: ': _'\n    replace: ': '\ncompose_relational_schema: '%%mocodo\\n{relations}'\ntransform_relational_schema:\n  - order: 100\n    search: '(?m)^:\\n(?=:)'\n    replace: ':'\n  - order: 200\n    search: '\\n\\n:+\\n\\n'\n    replace: '\\n\\n'\n    iterated: true\n  - order: 300\n    search: '^%%mocodo\\n\\n?:+\\n\\n'\n    replace: ''\n  - order: 400\n    search: '\\n\\n:+\\n?$'\n    replace: ''\n"
  },
  {
    "path": "mocodo/resources/relation_templates/diagram.yaml",
    "content": "help_en: 'convert the conceptual model into a relational diagram in Mocodo syntax'\nhelp_fr: 'convertit le modèle conceptuel en un diagramme relationnel au format Mocodo'\nhelp_zh: '将概念模型转换为 Mocodo 格式的关系图'\nfr_examples:\n  - order: 1\n    example: 'diagram'\n    explanation: 'version de base'\n  - order: 2\n    example: 'diagram:c'\n    explanation: 'avec contraintes d''unicité et d''optionalité'\nparent: 'diagram-c'\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-b.yaml",
    "content": "parent: 'html-bc'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-bc.yaml",
    "content": "parent: 'html-c'\ncompose_relational_schema: '<!-- Generated by Mocodo {version}-->\\n\\n<html>\\n<head>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\\n<meta charset=\"utf-8\">\\n<style>\\n  .mld .relation {{ font-variant: small-caps; font-weight: bold }}\\n  .mld .primary {{ text-decoration: underline }}\\n  .mld .foreign {{ font-style: oblique }}\\n  .mld strong {{ font-weight: bold }}\\n  .mld i {{ font-style: italic }}\\n  .mld ul {{ list-style-type:square; margin: 0 0 1em 2em }}\\n</style>\\n</head>\\n<body>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\\n<main>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"{stem}.svg\"/></center><figcaption>MCD <i>{title}</i></figcaption></figure>\\n<div class=\"mld\">\\n{relations}{deleted_relations}\\n</div>\\n</main>\\n</body>\\n</html>'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-bce.yaml",
    "content": "parent: 'html-ce'\ncompose_relational_schema: '<!-- Generated by Mocodo {version}-->\\n\\n<html>\\n<head>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\\n<meta charset=\"utf-8\">\\n<style>\\n  .mld .relation {{ font-variant: small-caps; font-weight: bold }}\\n  .mld .primary {{ text-decoration: underline }}\\n  .mld .foreign {{ font-style: oblique }}\\n  .mld strong {{ font-weight: bold }}\\n  .mld i {{ font-style: italic }}\\n  .mld ul {{ list-style-type:square; margin: 0 0 1em 2em }}\\n</style>\\n</head>\\n<body>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\\n<main>\\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"{stem}.svg\"/></center><figcaption>MCD <i>{title}</i></figcaption></figure>\\n<div class=\"mld\">\\n{relations}{deleted_relations}\\n</div>\\n</main>\\n</body>\\n</html>'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-be.yaml",
    "content": "parent: 'html-bce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-c.yaml",
    "content": "stem_suffix: '_mld'\nextension: 'html'\nto_defer: false\nhighlight: 'html'\ntransform_attribute:\n  - order: 100\n    search: '&'\n    replace: '&amp;'\n  - order: 200\n    search: '>'\n    replace: '&gt;'\n  - order: 300\n    search: '<'\n    replace: '&lt;'\ntransform_relation_name:\n  - order: 100\n    search: '&'\n    replace: '&amp;'\n  - order: 200\n    search: '>'\n    replace: '&gt;'\n  - order: 300\n    search: '<'\n    replace: '&lt;'\ncompose_association_attribute: '<span class=''normal''>{label}</span>'\ncompose_association_primary_key: '<span class=''primary''>{label}</span>'\ncompose_deleted_child_attribute: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_discriminator_: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_discriminator_T: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_discriminator_X: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_discriminator_XT: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_entity_name: '<span class=''normal''>{label}</span>'\ncompose_deleted_child_foreign_key: '<span class=''foreign''>#{label}</span>'\ncompose_deleted_child_ex_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_attribute: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_discriminator_: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_discriminator_T: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_discriminator_X: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_discriminator_XT: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_foreign_key: '<span class=''foreign''>#{label}</span>'\ncompose_deleted_parent_ex_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_deleted_parent_primary_key: '<span class=''primary''>{label}</span>'\ncompose_foreign_key: '<span class=''foreign''>#{label}</span>'\ncompose_ex_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_normal_attribute: '<span class=''normal''>{label}</span>'\ncompose_outer_attribute: '<span class=''normal''>{label}</span>'\ncompose_outer_primary_key: '<span class=''primary''>{label}</span>'\ncompose_parent_primary_key: '<span class=''foreign primary''>#{label}</span>'\ncompose_primary_foreign_key: '<span class=''foreign primary''>#{label}</span>'\ncompose_primary_key: '<span class=''primary''>{label}</span>'\ncompose_primary_ex_foreign_key: '<span class=''primary''>{label}</span>'\ncompose_stopped_foreign_key: '<span class=''foreign''>#{label}</span>'\ncompose_stopped_ex_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_strengthening_primary_foreign_key: '<span class=''foreign primary''>#{label}</span>'\ncompose_strengthening_primary_ex_foreign_key: '<span class=''primary''>{label}</span>'\ncompose_unsourced_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_unsourced_ex_foreign_key: '<span class=''normal''>{label}</span>'\ncompose_unsourced_primary_foreign_key: '<span class=''primary''>{label}</span>'\ncompose_unsourced_primary_ex_foreign_key: '<span class=''primary''>{label}</span>'\nadd_unicity_constraints:\n  - order: 100\n    search: '</span>'\n    replace: '</span> <sup>u{unicities}</sup>'\nadd_optionality_constraints:\n  - order: 100\n    search: '^(<span class=''(?:normal|foreign)''>.+)(</span>)'\n    replace: '\\1{optionality}\\2'\ncolumn_separator: ',\\n    '\ncompose_relation: '<div>\\n  <span class=''relation''>{this_relation_name}</span> (\\n    {columns}\\n  )\\n</div>'\ntransform_relation:\n  - order: 100\n    search: '(<sup>u\\d+)(\\d)'\n    replace: '\\1 u\\2'\n    iterated: true\ncompose_relational_schema: '<!-- Generated by Mocodo {version} -->\\n\\n<div class=\"mld\">\\n{relations}\\n</div>'\ntransform_relational_schema:\n  - order: 10000\n    search: '\\s+$'\n    replace: ''\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-ce.yaml",
    "content": "parent: 'html-c'\ncompose_association_attribute: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> était déjà un simple attribut de l''association <i>{this_relation_name}</i>.</item>'\ncompose_association_primary_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. C''était déjà un « identifiant » de l''association <i>{this_relation_name}</i>. <strong>Attention</strong> : la notion d''identifiant d''association n''existe pas en Merise ; il s''agit d''une commodité introduite par Mocodo pour éviter d''inclure dans l''association une entité réduite à cet identifiant.</item>'\ncompose_deleted_child_attribute: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré à partir de l''entité-fille <i>{adjacent_source}</i> (supprimée).</item>'\ncompose_deleted_child_discriminator_: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l''absence de contrainte de totalité.</item>'\ncompose_deleted_child_discriminator_T: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</item>'\ncompose_deleted_child_discriminator_X: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l''absence de contrainte de totalité.</item>'\ncompose_deleted_child_discriminator_XT: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</item>'\ncompose_deleted_child_entity_name: '<span class=''normal''>{label}</span><item>Un champ booléen <i>{label}</i> est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.</item>'\ncompose_deleted_child_foreign_key: '<span class=''foreign''>#{label}</span><item>Le champ <i>{label}</i> est une clé étrangère. Il a migré à partir de l''entité-fille <i>{adjacent_source}</i> (supprimée) dans laquelle il avait déjà migré à partir de l''entité <i>{outer_source}</i>.</item>'\ncompose_deleted_child_ex_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré à travers l''entité-fille <i>{adjacent_source}</i> (supprimée) dans laquelle il avait déjà migré à partir de l''entité <i>{outer_source}</i> (également supprimée).</item>'\ncompose_deleted_parent_attribute: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> est un simple attribut. Il était simple attribut de l''entité-mère <i>{adjacent_source}</i> (supprimée).</item>'\ncompose_deleted_parent_discriminator_: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l''absence de contrainte de totalité.</item>'\ncompose_deleted_parent_discriminator_T: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</item>'\ncompose_deleted_parent_discriminator_X: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l''absence de contrainte de totalité.</item>'\ncompose_deleted_parent_discriminator_XT: '<span class=''normal''>{label}</span><item>Un discriminateur <i>{label}</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</item>'\ncompose_deleted_parent_foreign_key: '<span class=''foreign''>#{label}</span><item>Le champ <i>{label}</i> est une clé étrangère. Il a migré à travers l''entité-mère <i>{adjacent_source}</i> (supprimée), et réfère maintenant directement à l''entité <i>{outer_source}</i>.</item>'\ncompose_deleted_parent_ex_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré à travers l''entité-mère <i>{adjacent_source}</i> (supprimée) dans laquelle il avait déjà migré à partir de l''entité <i>{outer_source}</i> (également supprimée).</item>'\ncompose_deleted_parent_primary_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Il était clé primaire de l''entité-mère <i>{adjacent_source}</i> (supprimée).</item>'\ncompose_foreign_key: '<span class=''foreign''>#{label}</span><item>Le champ <i>{label}</i> est une clé étrangère. Il a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{outer_source}</i> en perdant son caractère identifiant.</item>'\ncompose_ex_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> est un simple attribut. Il a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{outer_source}</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n''est pas considéré comme clé étrangère.</item>'\ncompose_normal_attribute: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> était déjà un simple attribut de l''entité <i>{this_relation_name}</i>.</item>'\ncompose_outer_attribute: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré à partir de l''association de dépendance fonctionnelle <i>{association_name}</i>.</item>'\ncompose_outer_primary_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Il a migré à partir de l''association de dépendance fonctionnelle <i>{association_name}</i> dont il était « identifiant ». <strong>Attention</strong> : la notion d''identifiant d''association n''existe pas en Merise ; il s''agit d''une tolérance introduite par Mocodo, mais vous devriez vraisemblablement placer cet identifiant dans l''entité <primary></primary>.</item>'\ncompose_parent_primary_key: '<span class=''foreign primary''>#{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. C''est une clé étrangère qui a migré à partir de l''entité-mère <i>{outer_source}</i>.</item>'\ncompose_primary_foreign_key: '<span class=''foreign primary''>#{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. C''est une clé étrangère qui a migré directement à partir de l''entité <i>{outer_source}</i>.</item>'\ncompose_primary_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. C''était déjà un identifiant de l''entité <i>{this_relation_name}</i>.</item>'\ncompose_primary_ex_foreign_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Sa table d''origine (<i>{outer_source}</i>) ayant été supprimée, il n''est pas considéré comme clé étrangère.</item>'\ncompose_stopped_foreign_key: '<span class=''foreign''>#{label}</span><item>Le champ <i>{label}</i> est une clé étrangère. Il a migré directement à partir de l''entité <i>{outer_source}</i> en perdant son caractère identifiant.</item>'\ncompose_stopped_ex_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> est un simple attribut. Il a migré directement à partir de l''entité <i>{outer_source}</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n''est pas considéré comme clé étrangère.</item>'\ncompose_strengthening_primary_foreign_key: '<span class=''foreign primary''>#{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. C''est une clé étrangère qui a migré à partir de l''entité <i>{outer_source}</i> pour renforcer l''identifiant.</item>'\ncompose_strengthening_primary_ex_foreign_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Il a migré à partir de l''entité <i>{outer_source}</i> pour renforcer l''identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n''est pas considéré comme clé étrangère.</item>'\ncompose_unsourced_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{adjacent_source}</i> (supprimée). <strong>Attention</strong> : aucune contrainte d''intégrité référentielle n''est plus assurée.</item>'\ncompose_unsourced_ex_foreign_key: '<span class=''normal''>{label}</span><item>Le champ <i>{label}</i> a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{adjacent_source}</i> (supprimée). <strong>Attention</strong> : aucune contrainte d''intégrité référentielle n''est plus assurée.</item>'\ncompose_unsourced_primary_foreign_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Il a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{adjacent_source}</i> (supprimée). <strong>Attention</strong> : aucune contrainte d''intégrité référentielle n''est plus assurée.</item>'\ncompose_unsourced_primary_ex_foreign_key: '<span class=''primary''>{label}</span><item>Le champ <i>{label}</i> fait partie de la clé primaire de la table<primary></primary>. Il a migré par l''association de dépendance fonctionnelle <i>{association_name}</i> à partir de l''entité <i>{adjacent_source}</i> (supprimée). <strong>Attention</strong> : aucune contrainte d''intégrité référentielle n''est plus assurée.</item>'\ncompose_relation: '<div>\\n  <details><summary><span class=''relation''>{this_relation_name}</span> (\\n    {columns}\\n  )</summary>\\n</div>'\ncompose_deleted_relation: 'La table <i>{this_relation_name}</i> a été supprimée car elle était réduite à la clé primaire de son entité d''origine. Pour conserver de telles tables, préfixez d''un « + » la définition des entités d''origine.'\nadd_unicity_constraints:\n  - order: 100\n    search: '</span>'\n    replace: '</span> <sup>u{unicities}</sup>'\n  - order: 200\n    search: '</item>'\n    replace: ' Il obéit en outre à la contrainte d''unicité {unicities}.</item>'\n  - order: 300\n    search: '(déjà un simple attribut.+) en outre'\n    replace: '\\1'\n  - order: 400\n    search: '(pas considéré comme clé.+) en outre'\n    replace: '\\1 par contre'\nadd_optionality_constraints:\n  - order: 100\n    search: '^(<span class=''(?:normal|foreign)''>.+?)(</span><item>.+? (?:champ .*?|discriminateur ))(<i>)'\n    replace: '\\1{optionality}\\2OPTIONALITY_SYMBOL''{optionality}''\\3'\ntransform_forced_relation:\n  - order: 100\n    search: '(?s)(.+)$'\n    replace: '\\1\\n    <li><strong>Avertissement.</strong> Table résultant de la conversion forcée d''une association DF.</li>'\ntransform_relation:\n  - order: 800\n    search: 'OPTIONALITY_SYMBOL''\\?'''\n    replace: 'à saisie facultative '\n  - order: 900\n    search: 'OPTIONALITY_SYMBOL''!'''\n    replace: 'à saisie obligatoire '\n  - order: 1000\n    comment: 'All header attributes are followed by their description. We must gather all the descriptions after the header.'\n    search: '(?s)<item>(.+?)</item>(.+)'\n    replace: '\\2\\n    <li>\\1</li>'\n    iterated: true\n  - order: 1050\n    comment: 'Suppress the numerical suffixes of the DF associations.'\n    search: '(association de dépendance fonctionnelle <i>[^<]+)\\d+(</i>)'\n    replace: '\\1\\2'\n  - order: 1100\n    search: '(    <li>Le champ .*?)(<i>.+?</i>)( était déjà un simple attribut de .+?.)\\n\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 1150\n    search: '    <li>Le champ (.+), (.+?) était déjà un simple attribut( de .+?.)'\n    replace: '    <li>Les champs \\1 et \\2 étaient déjà de simples attributs\\3'\n  - order: 1200\n    search: '(    <li>Le champ .*?)(<i>.+?</i>)( est un simple attribut\\. Il a migré .+? pas considéré comme clé étrangère.+)\\n\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 1250\n    search: '    <li>Le champ (.+), (.+?) est un simple attribut\\. Il a migré (.+?) en perdant son caractère identifiant. (.+?), il n''est pas considéré comme clé étrangère.'\n    replace: '    <li>Les champs \\1 et \\2 sont de simples attributs. Ils ont migré \\3 en perdant leur caractère identifiant. \\4, ils ne sont pas considérés comme clés étrangères.'\n  - order: 1300\n    search: '(    <li>Le champ .*?)(<i>.+?</i>)( est une clé étrangère\\. Il a migré .+? l''association de dépendance fonctionnelle .+? en perdant son caractère identifiant.+)\\n\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 1350\n    search: '    <li>Le champ (.+), (.+?) est une clé étrangère\\. Il a (migré .+ l''association de dépendance fonctionnelle .+ en perdant) son (caractère identifiant)\\. Il obéit'\n    replace: '    <li>Les champs \\1 et \\2 sont des clés étrangères. Ils ont \\3 leur \\4. Ils obéissent'\n  - order: 1400\n    search: '    <li>Le champ (.+), (.+?) est une clé étrangère\\. Il a (migré .+ l''association de dépendance fonctionnelle .+ en perdant) son (caractère identifiant)'\n    replace: '    <li>Les champs \\1 et \\2 sont des clés étrangères. Ils ont \\3 leur \\4'\n  - order: 1500\n    search: '(    <li>Le champ .*?)(<i>.+?</i>)( fait partie de la clé primaire de la table<primary></primary>. Sa table d''origine .+?)\\n\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 1600\n    search: '    <li>Le champ (.+), (.+?) fait partie de la clé primaire de la table<primary></primary>. Sa table d''origine (.+?) ayant été supprimée, il n''est pas considéré comme clé étrangère.'\n    replace: '    <li>Les champs \\1 et \\2 font partie de la clé primaire de la table<primary></primary>. Leur table d''origine \\3 ayant été supprimée, ils ne sont pas considérés comme clés étrangères.'\n  - order: 1700\n    search: '(    <li>Le champ .*?)(<i>.+?</i>)( fait partie de la clé primaire de la table<primary></primary>.+?)\\n\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 1800\n    search: '    <li>Le champ (.+), (.+?) fait partie de la clé primaire de la table<primary></primary>. C''est une clé étrangère qui a (migré directement à partir de l''entité .+?)'\n    replace: '    <li>Les champs \\1 et \\2 font partie de la clé primaire de la table<primary></primary>. Ce sont des clés étrangères qui ont \\3'\n  - order: 1900\n    search: '    <li>Le champ (.+), (.+?) fait partie de la clé primaire de la table<primary></primary>. C''était déjà un identifiant (de l''entité .+?)'\n    replace: '    <li>Les champs \\1 et \\2 font partie de la clé primaire de la table<primary></primary>. C''étaient déjà des identifiants \\3'\n  - order: 2000\n    search: '    <li>Le champ (.+), (.+?) fait partie de la clé primaire de la table<primary></primary>. Il a (migré .+?)'\n    replace: '    <li>Les champs \\1 et \\2 font partie de la clé primaire de la table<primary></primary>. Ils ont \\3'\n  - order: 2100\n    search: '    <li>Les champs (.+). Il fait partie'\n    replace: '    <li>Les champs \\1. Ils font partie'\n  - order: 2200\n    search: '$'\n    replace: '<primary_count></primary_count>'\n  - order: 2300\n    search: '(?s)<primary></primary>(.+)</primary_count>'\n    replace: '\\1I</primary_count>'\n    iterated: true\n  - order: 2400\n    search: '(?s)fait partie de( la clé primaire de la table.+)<primary_count>I</primary_count>'\n    replace: 'constitue\\1'\n  - order: 2500\n    search: '(?s)font partie de( la clé primaire de la table.+)<primary_count>I</primary_count>'\n    replace: 'constituent\\1'\n  - order: 2600\n    search: '<primary_count>I+</primary_count>'\n    replace: ''\n  - order: 2700\n    search: '(?s)</div>(\\n    <li>.+)'\n    replace: '  <ul>\\1\\n  </ul></details>\\n</div>'\n  - order: 2800\n    search: '$'\n    replace: '\\n'\n  - order: 2900\n    comment: 'Develop the multiple unicity constraints'\n    search: '(contrainte d''unicité) (\\d)(\\d)'\n    replace: '\\1 \\2 \\1 \\3'\n    iterated: true\n  - order: 3000\n    comment: 'Mark any duplicated unicity constraint, except the first one.'\n    search: '(?s)(contrainte d''unicité )(\\d)(.+)\\1\\2'\n    replace: '\\1\\2\\3\\1DUPLICATED_ALT_GROUP:\\2'\n    iterated: true\n  - order: 3100\n    comment: 'Mark the remaining duplicated unicity constraints'\n    search: '(?s)(contrainte d''unicité )(\\d+)(.+\\1DUPLICATED_ALT_GROUP:\\2)'\n    replace: '\\1DUPLICATED_ALT_GROUP:\\2\\3'\n    iterated: true\n  - order: 3400\n    comment: 'Remove the mark'\n    search: 'DUPLICATED_ALT_GROUP:'\n    replace: ''\n  - order: 3500\n    comment: 'Remove the repetitions'\n    search: '(contrainte d''unicité) (\\d+) \\1 (\\d)'\n    replace: '\\1 \\2\\3'\n    iterated: true\n  - order: 3600\n    search: '(contrainte d''unicité \\d+)(\\d)'\n    replace: '\\1, \\2'\n    iterated: true\n  - order: 3700\n    search: 'à la contrainte d''unicité (.+), (\\d)'\n    replace: 'aux contraintes d''unicité \\1 et \\2'\n    iterated: true\ncompose_deleted_relations: '<br><hr>\\n\\n<div>\\n  <span><strong>NB.</strong> {deleted_relation_lines}</span>\\n</div>'\ncompose_relational_schema: '<!-- Generated by Mocodo {version} -->\\n\\n<div class=\"mld\">\\n{relations}\\n{deleted_relations}\\n</div>'\ntransform_relational_schema:\n  - order: 100\n    search: '(La table )(.+?)( a été supprimée .+)\\1(.+?)\\3'\n    replace: '\\1\\2, \\4\\3'\n    iterated: true\n  - order: 200\n    search: 'La table (.+), (.+?) a été supprimée car elle était réduite à la clé primaire de son entité d''origine'\n    replace: 'Les tables \\1 et \\2 ont été supprimées car elles étaient réduites à la clé primaire de leur entité d''origine'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html-e.yaml",
    "content": "parent: 'html-ce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/html.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in HTML format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format HTML'\nhelp_zh: '将概念模型转换为 HTML 格式的关系模式'\nfr_examples:\n  - order: 1\n    example: 'html'\n    explanation: 'version de base'\n  - order: 2\n    example: 'html:b'\n    explanation: 'avec _boilerplate_'\n  - order: 3\n    example: 'html:c'\n    explanation: 'avec contraintes d''unicité et d''optionalité'\n  - order: 4\n    example: 'html:e'\n    explanation: 'avec explications'\n  - order: 5\n    example: 'html:bce'\n    explanation: 'avec _boilerplate_, contraintes et explications'\nparent: 'html-c'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-b.yaml",
    "content": "parent: 'latex-bc'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-bc.yaml",
    "content": "parent: 'latex-c'\ncompose_relational_schema: '% Generated by Mocodo {version}\\n\\n\\documentclass[a4paper]{{article}}\\n\\usepackage[normalem]{{ulem}}\\n\\usepackage[T1]{{fontenc}}\\n\\usepackage[french]{{babel}}\\n\\frenchsetup{{StandardLayout=true}}\\n\\n\\\\newcommand{{\\relat}}[1]{{\\\\textsc{{#1}}}}\\n\\\\newcommand{{\\attr}}[1]{{#1}}\\n\\\\newcommand{{\\prim}}[1]{{\\uline{{#1}}}}\\n\\\\newcommand{{\\foreign}}[1]{{\\#\\\\textsl{{#1}}}}\\n\\n\\\\title{{Conversion en relationnel\\\\du MCD \\emph{{{title}}}}}\\n\\author{{\\emph{{Généré par Mocodo}}}}\\n\\n\\begin{{document}}\\n\\maketitle\\n\\n\\begin{{itemize}}\\n{relations}\\n\\end{{itemize}}\\n\\n\\end{{document}}\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-bce.yaml",
    "content": "parent: 'latex-ce'\ncompose_relational_schema: '% Generated by Mocodo {version}\\n\\n\\documentclass[a4paper]{{article}}\\n\\usepackage[normalem]{{ulem}}\\n\\usepackage[T1]{{fontenc}}\\n\\usepackage[french]{{babel}}\\n\\frenchsetup{{StandardLayout=true}}\\n\\n\\\\newcommand{{\\relat}}[1]{{\\\\textsc{{#1}}}}\\n\\\\newcommand{{\\attr}}[1]{{#1}}\\n\\\\newcommand{{\\prim}}[1]{{\\uline{{#1}}}}\\n\\\\newcommand{{\\foreign}}[1]{{\\#\\\\textsl{{#1}}}}\\n\\n\\\\title{{Conversion en relationnel\\\\du MCD \\emph{{{title}}}}}\\n\\author{{\\emph{{Généré par Mocodo}}}}\\n\\n\\begin{{document}}\\n\\maketitle\\n\\n\\begin{{itemize}}\\n{relations}\\n\\end{{itemize}}\\n\\n\\end{{document}}\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-be.yaml",
    "content": "parent: 'latex-bce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-c.yaml",
    "content": "parent: 'html-c'\nextension: 'tex'\nhighlight: 'latex'\ncolumn_separator: ', '\ncompose_relation: '  \\item \\relat{{{this_relation_name}}} ({columns})'\ncompose_relational_schema: '% Generated by Mocodo {version}\\n\\n\\begin{{itemize}}\\n{relations}\\n\\end{{itemize}}\\n'\ntransform_relation:\n  - order: 1000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\\\attr{\\1}'\n  - order: 1100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '\\\\prim{\\1}'\n  - order: 1200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>#(.+?)</span>'\n    replace: '\\\\foreign{\\\\prim{\\1}}'\n  - order: 1300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>#(.+?)</span>'\n    replace: '\\\\foreign{\\1}'\n  - order: 1400\n    comment: 'Exponents'\n    search: '(<sup>.*u)(\\d)(.*</sup>)'\n    replace: '\\1_\\2\\3'\n    iterated: true\n  - order: 1500\n    comment: 'Exponents'\n    search: ' <sup>(.+?)</sup>'\n    replace: '$^{\\1}$'\n  - order: 1600\n    comment: 'Escape underlines'\n    search: '_'\n    replace: '\\_'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-ce.yaml",
    "content": "parent: 'html-ce'\nextension: 'tex'\nhighlight: 'latex'\ncolumn_separator: ', '\ncompose_relation: '  \\item \\relat{{{this_relation_name}}} ({columns})'\ncompose_relational_schema: '% Generated by Mocodo {version}\\n\\n\\begin{{itemize}}\\n{relations}\\n\\end{{itemize}}{deleted_relations}\\n'\ntransform_relation:\n  - order: 10000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\\\attr{\\1}'\n  - order: 10100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '\\\\prim{\\1}'\n  - order: 10200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>#(.+?)</span>'\n    replace: '\\\\foreign{\\\\prim{\\1}}'\n  - order: 10300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>#(.+?)</span>'\n    replace: '\\\\foreign{\\1}'\n  - order: 10400\n    comment: 'Exponents'\n    search: '(<sup>.*u)(\\d)(.*</sup>)'\n    replace: '\\1_\\2\\3'\n    iterated: true\n  - order: 10500\n    comment: 'Exponents'\n    search: ' <sup>(.+?)</sup>'\n    replace: '$^{\\1}$'\ntransform_relational_schema:\n  - order: 1000\n    comment: 'Process italics'\n    search: '<i>(.+?)</i>'\n    replace: '\\\\emph{\\1}'\n  - order: 1100\n    comment: 'Process strong'\n    search: '<strong>(.+?)</strong>'\n    replace: '\\\\paragraph{\\1}'\n  - order: 1200\n    comment: 'Format lists'\n    search: '    <li>(.+?)</li>'\n    replace: '    \\\\item \\1'\n  - order: 1300\n    search: '<hr>'\n    replace: '\\n\\n'\n  - order: 1400\n    search: '<div>\\n  <span>(.+?)</span>\\n</div>'\n    replace: '\\1'\n  - order: 1500\n    search: '((    \\\\item .+\\n)+)'\n    replace: '  \\\\begin{itemize}\\n\\1  \\\\end{itemize}\\n'\n  - order: 1600\n    comment: 'Escape underlines'\n    search: '_'\n    replace: '\\_'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex-e.yaml",
    "content": "parent: 'latex-ce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/latex.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in LaTeX format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format LaTeX'\nhelp_zh: '将概念模型转换为 LaTeX 格式的关系模式'\nfr_examples:\n  - order: 1\n    example: 'latex'\n    explanation: 'version de base'\n  - order: 2\n    example: 'latex:b'\n    explanation: 'avec _boilerplate_'\n  - order: 3\n    example: 'latex:c'\n    explanation: 'avec contraintes d''unicité et d''optionalité'\n  - order: 4\n    example: 'latex:e'\n    explanation: 'avec explications'\n  - order: 5\n    example: 'latex:bce'\n    explanation: 'avec _boilerplate_, contraintes et explications'\nparent: 'latex-c'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-b.yaml",
    "content": "parent: 'markdown-bc'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-bc.yaml",
    "content": "parent: 'markdown-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-bce.yaml",
    "content": "parent: 'markdown-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-be.yaml",
    "content": "parent: 'markdown-bce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-c.yaml",
    "content": "parent: 'html-c'\nextension: 'md'\nhighlight: 'markdown'\ncolumn_separator: ', '\ncompose_relation: '- **{this_relation_name}** ({columns})'\ncompose_relational_schema: '<!-- Generated by Mocodo {version} -->\\n\\n{relations}'\ntransform_relation:\n  - order: 1000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\1'\n  - order: 1100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '<u>\\1</u>'\n  - order: 1200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>(.+?)</span>'\n    replace: '<u>_\\1_</u>'\n  - order: 1300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>(.+?)</span>'\n    replace: '_\\1_'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-ce.yaml",
    "content": "parent: 'html-ce'\nextension: 'md'\nhighlight: 'markdown'\ncolumn_separator: ', '\ncompose_relation: '- **{this_relation_name}** ({columns})'\ncompose_relational_schema: '<!-- Generated by Mocodo {version} -->\\n\\n{relations}{deleted_relations}'\ntransform_relation:\n  - order: 10000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\1'\n  - order: 10100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '<u>\\1</u>'\n  - order: 10200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>(.+?)</span>'\n    replace: '<u>_\\1_</u>'\n  - order: 10300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>(.+?)</span>'\n    replace: '_\\1_'\ntransform_relational_schema:\n  - order: 1000\n    comment: 'Process italics'\n    search: '</?i>'\n    replace: '_'\n  - order: 1100\n    comment: 'Process strong'\n    search: '</?strong>'\n    replace: '**'\n  - order: 1200\n    comment: 'Format lists'\n    search: '    <li>(.+?)</li>'\n    replace: '  - \\1'\n  - order: 1300\n    search: '<hr>'\n    replace: '\\n----\\n'\n  - order: 1400\n    search: '<div>\\n  <span>(.+?)</span>\\n</div>'\n    replace: '\\1'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown-e.yaml",
    "content": "parent: 'markdown-ce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/markdown.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in Markdown format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format Markdown'\nhelp_zh: '将概念模型转换为 Markdown 格式的关系模式'\nfr_examples:\n  - order: 1\n    example: 'markdown'\n    explanation: 'version de base'\n  - order: 2\n    example: 'markdown:c'\n    explanation: 'avec contraintes d''unicité et d''optionalité'\n  - order: 3\n    example: 'markdown:e'\n    explanation: 'avec explications'\n  - order: 5\n    example: 'markdown:ce'\n    explanation: 'avec contraintes et explications'\nparent: 'markdown-c'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-b.yaml",
    "content": "parent: 'markdown-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-bc.yaml",
    "content": "parent: 'markdown-bc'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-bce.yaml",
    "content": "parent: 'markdown-bce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-be.yaml",
    "content": "parent: 'markdown-be'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-c.yaml",
    "content": "parent: 'markdown-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-ce.yaml",
    "content": "parent: 'markdown-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md-e.yaml",
    "content": "parent: 'markdown-e'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/md.yaml",
    "content": "parent: 'markdown'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-b.yaml",
    "content": "parent: 'markdown-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-bc.yaml",
    "content": "parent: 'markdown-bc'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-bce.yaml",
    "content": "parent: 'markdown-bce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-be.yaml",
    "content": "parent: 'markdown-be'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-c.yaml",
    "content": "parent: 'markdown-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-ce.yaml",
    "content": "parent: 'markdown-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld-e.yaml",
    "content": "parent: 'markdown-e'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mld.yaml",
    "content": "parent: 'markdown'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/ms_sql-b.yaml",
    "content": "parent: 'mssql-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/ms_sql.yaml",
    "content": "parent: 'mssql'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mssql-b.yaml",
    "content": "parent: 'mssql'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\nCREATE DATABASE [{title}]\\n<MOCODO_INDENT_PLACEHOLDER>CONTAINMENT = NONE\\n<MOCODO_INDENT_PLACEHOLDER>ON PRIMARY (\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>NAME = ''{title}'',\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>FILENAME = ''C:\\path\\\\to\\{title}.mdf'',\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>SIZE = 100MB,\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>MAXSIZE = UNLIMITED,\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>FILEGROWTH = 10MB\\n<MOCODO_INDENT_PLACEHOLDER>)\\n<MOCODO_INDENT_PLACEHOLDER>LOG ON (\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>NAME = ''{title}_log'',\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>FILENAME = ''C:\\path\\\\to\\{title}_log.ldf'',\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>SIZE = 50MB,\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>MAXSIZE = 2048GB,\\n<MOCODO_INDENT_PLACEHOLDER><MOCODO_INDENT_PLACEHOLDER>FILEGROWTH = 5MB\\n<MOCODO_INDENT_PLACEHOLDER>)\\nGO\\nUSE [{title}]\\nGO\\n\\n{relations}\\n'\ntransform_relational_schema:\n  - order: 30000\n    comment: 'The indent placeholders in the _boilerplate_ where used to protect it from the addition of trailing commas. Transform them into double spaces.'\n    search: '<MOCODO_INDENT_PLACEHOLDER>'\n    replace: '  '\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mssql.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for Microsoft SQL Server'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server'\nhelp_zh: '将概念模型转换为 Microsoft SQL Server 的物理模型'\nfr_examples:\n  - order: 1\n    example: 'mssql'\n    explanation: 'version de base'\n  - order: 4\n    example: 'mssql:b'\n    explanation: 'avec _boilerplate_'\nparent: 'sql'\nstem_suffix: '_ddl_mssql'\ntransform_label:\n  - order: 1100\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ARE|ARRAY|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTOINCREMENT|AVG|BEFORE|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|CALL|CASCADED|CAST|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CLUSTER|COLLATION|COMMENT|COMPRESS|CONCAT|CONCURRENTLY|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CORRESPONDING|COUNT|CUBE|CUME_DIST|CURRENT_CATALOG|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DEC|DECIMAL|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DIV|DO|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|ENUM|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXPLAIN|EXTRACT|FALSE|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOUND|FREEZE|FULLTEXT|GENERATED|GET|GLOB|GLOBAL|GO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IGNORE|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INFILE|INITIAL|INITIALLY|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTEVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISNULL|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEYS|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEVEL|LIMIT|LINEAR|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATURAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCOMPRESS|NONE|NOTHING|NOTNULL|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLS|NUMBER|NUMERIC|NVARCHAR|OFFLINE|OFFSET|ONLINE|ONLY|OPTIMIZE|OPTIMIZER_COSTS|OPTIONALLY|OUT|OUTFILE|OUTPUT|OVERLAPS|PAD|PARTIAL|PARTITION|PCTFREE|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PLACING|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRIOR|PRIVILEGES|PURGE|RAISE|RANGE|RANK|RAW|READS|READ_WRITE|REAL|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RETURNING|RLIKE|ROLLUP|ROW|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SENSITIVE|SEPARATOR|SESSION|SHARE|SHOW|SIGNAL|SIMILAR|SIZE|SMALLINT|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM|TEMPORARY|TERMINATED|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TRAILING|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUE|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNSIGNED|UPPER|USAGE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARIADIC|VAR_POP|VAR_SAMP|VERBOSE|VIRTUAL|WHENEVER|WINDOW|WITHIN|WITHOUT|WORK|WRITE|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '[\\1]'\ntransform_relation_name:\n  - order: 1000\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ARE|ARRAY|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTOINCREMENT|AVG|BEFORE|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|CALL|CASCADED|CAST|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CLUSTER|COLLATION|COMMENT|COMPRESS|CONCAT|CONCURRENTLY|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CORRESPONDING|COUNT|CUBE|CUME_DIST|CURRENT_CATALOG|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DEC|DECIMAL|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DIV|DO|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|ENUM|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXPLAIN|EXTRACT|FALSE|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOUND|FREEZE|FULLTEXT|GENERATED|GET|GLOB|GLOBAL|GO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IGNORE|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INFILE|INITIAL|INITIALLY|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISNULL|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEYS|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEVEL|LIMIT|LINEAR|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATURAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCOMPRESS|NONE|NOTHING|NOTNULL|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLS|NUMBER|NUMERIC|NVARCHAR|OFFLINE|OFFSET|ONLINE|ONLY|OPTIMIZE|OPTIMIZER_COSTS|OPTIONALLY|OUT|OUTFILE|OUTPUT|OVERLAPS|PAD|PARTIAL|PARTITION|PCTFREE|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PLACING|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRIOR|PRIVILEGES|PURGE|RAISE|RANGE|RANK|RAW|READS|READ_WRITE|REAL|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RETURNING|RLIKE|ROLLUP|ROW|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SENSITIVE|SEPARATOR|SESSION|SHARE|SHOW|SIGNAL|SIMILAR|SIZE|SMALLINT|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM|TEMPORARY|TERMINATED|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TRAILING|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUE|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNSIGNED|UPPER|USAGE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARIADIC|VAR_POP|VAR_SAMP|VERBOSE|VIRTUAL|WHENEVER|WINDOW|WITHIN|WITHOUT|WORK|WRITE|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '[\\1]'\ntransform_datatype:\n  - order: 200\n    search: 'BOOLEAN_PLACEHOLDER'\n    replace: 'BIT'\n  - order: 300\n    comment: '(Meant to replace the parent''s transformation)'\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'TINYINT'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mysql-b.yaml",
    "content": "parent: 'mysql'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\nCREATE DATABASE IF NOT EXISTS `{title}`\\n<MOCODO_INDENT_PLACEHOLDER>CHARACTER SET utf8mb4\\n<MOCODO_INDENT_PLACEHOLDER>COLLATE utf8mb4_general_ci\\n;\\nUSE `{title}`;\\n\\n{relations}\\n'\ntransform_relational_schema:\n  - order: 20000\n    comment: 'The indent placeholders in the _boilerplate_ where used to protect it from the addition of trailing commas. Transform them into double spaces.'\n    search: '<MOCODO_INDENT_PLACEHOLDER>'\n    replace: '  '\n"
  },
  {
    "path": "mocodo/resources/relation_templates/mysql.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for MySQL'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour MySQL'\nhelp_zh: '将概念模型转换为 MySQL 物理模型'\nfr_examples:\n  - order: 1\n    example: 'mysql'\n    explanation: 'version de base'\n  - order: 4\n    example: 'mysql:b'\n    explanation: 'avec _boilerplate_'\nparent: 'sql'\nstem_suffix: '_ddl_mysql'\ntransform_label:\n  - order: 1100\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ALLOCATE|ANALYSE|ANY|ARE|ARRAY|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTHORIZATION|AUTOINCREMENT|AVG|BACKUP|BEGIN|BIT|BOOLEAN|BREAK|BROWSE|BULK|CASCADED|CAST|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COLLATION|COMMENT|COMMIT|COMPRESS|COMPUTE|CONCAT|CONCURRENTLY|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CORRESPONDING|COUNT|CURRENT|CURRENT_CATALOG|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|DATE|DAY|DAYS|DBCC|DEALLOCATE|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DENY|DIAGNOSTICS|DISCONNECT|DISTRIBUTED|DO|END|ENUM|ERRLVL|ESCAPE|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXTERNAL|EXTRACT|FILE|FILLFACTOR|FILTER|FIRST|FOLLOWING|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|GLOB|GLOBAL|GO|GOTO|HASH|HOLDLOCK|HOUR|HOURS|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INITIAL|INITIALLY|INPUT|INVOKER|ISNULL|ISOLATION|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|LAST|LEVEL|LINENO|LOWER|LTRIM|MAX|MAXEXTENTS|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIN|MINUS|MINUTE|MINUTES|MLSLABEL|MODE|MODIFY|MONTH|MONTHS|NATIONAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOTHING|NOTNULL|NOWAIT|NULLIF|NULLS|NUMBER|NVARCHAR|OFF|OFFLINE|OFFSET|OFFSETS|ONLINE|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OUTPUT|OVERLAPS|PAD|PARTIAL|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PUBLIC|RAISE|RAISERROR|RAW|READTEXT|RECONFIGURE|RELATIVE|REPLICATION|RESOURCE|RESPECT|RESTORE|RETURNING|REVERT|ROLLBACK|ROLLUP|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|RTRIM|RULE|SAVE|SCROLL|SECOND|SECONDS|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SESSION|SESSION_USER|SETUSER|SHARE|SHUTDOWN|SIMILAR|SIZE|SOME|SOUNDS|SPACE|SQLCODE|SQLERROR|SQLID|SQL_BUFFER_RESULT|SQL_CACHE|SQL_NO_CACHE|START|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TOP|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNKNOWN|UNNEST|UNPIVOT|UPDATETEXT|UPPER|USER|VALIDATE|VALUE|VARCHAR2|VARIADIC|VAR_POP|VAR_SAMP|VERBOSE|VIEW|WAITFOR|WHENEVER|WITHIN|WITHOUT|WORK|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|YEAR|YEARS)$'\n    replace: '`\\1`'\ntransform_relation_name:\n  - order: 1000\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ALLOCATE|ANALYSE|ANY|ARE|ARRAY|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTHORIZATION|AUTOINCREMENT|AVG|BACKUP|BEGIN|BIT|BOOLEAN|BREAK|BROWSE|BULK|CASCADED|CAST|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COLLATION|COMMENT|COMMIT|COMPRESS|COMPUTE|CONCAT|CONCURRENTLY|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CORRESPONDING|COUNT|CURRENT|CURRENT_CATALOG|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|DATE|DAY|DAYS|DBCC|DEALLOCATE|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DENY|DIAGNOSTICS|DISCONNECT|DISTRIBUTED|DO|END|ENUM|ERRLVL|ESCAPE|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXTERNAL|EXTRACT|FILE|FILLFACTOR|FILTER|FIRST|FOLLOWING|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|GLOB|GLOBAL|GO|GOTO|HASH|HOLDLOCK|HOUR|HOURS|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INITIAL|INITIALLY|INPUT|INVOKER|ISNULL|ISOLATION|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|LAST|LEVEL|LINENO|LOWER|LTRIM|MAX|MAXEXTENTS|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIN|MINUS|MINUTE|MINUTES|MLSLABEL|MODE|MODIFY|MONTH|MONTHS|NATIONAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOTHING|NOTNULL|NOWAIT|NULLIF|NULLS|NUMBER|NVARCHAR|OFF|OFFLINE|OFFSET|OFFSETS|ONLINE|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OUTPUT|OVERLAPS|PAD|PARTIAL|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PUBLIC|RAISE|RAISERROR|RAW|READTEXT|RECONFIGURE|RELATIVE|REPLICATION|RESOURCE|RESPECT|RESTORE|RETURNING|REVERT|ROLLBACK|ROLLUP|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|RTRIM|RULE|SAVE|SCROLL|SECOND|SECONDS|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SESSION|SESSION_USER|SETUSER|SHARE|SHUTDOWN|SIMILAR|SIZE|SOME|SOUNDS|SPACE|SQLCODE|SQLERROR|SQLID|SQL_BUFFER_RESULT|SQL_CACHE|SQL_NO_CACHE|START|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TOP|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNKNOWN|UNNEST|UNPIVOT|UPDATETEXT|UPPER|USER|VALIDATE|VALUE|VARCHAR2|VARIADIC|VAR_POP|VAR_SAMP|VERBOSE|VIEW|WAITFOR|WHENEVER|WITHIN|WITHOUT|WORK|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|YEAR|YEARS)$'\n    replace: '`\\1`'\ntransform_datatype:\n  - order: 300\n    comment: '(Meant to replace the parent''s transformation)'\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'TINYINT UNSIGNED'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/oracle-b.yaml",
    "content": "parent: 'oracle'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\nCREATE DATABASE \"{title}\"\\n<MOCODO_INDENT_PLACEHOLDER>USER SYS IDENTIFIED BY your_sys_password\\n<MOCODO_INDENT_PLACEHOLDER>USER SYSTEM IDENTIFIED BY your_system_password\\n<MOCODO_INDENT_PLACEHOLDER>MAXLOGFILES 5\\n<MOCODO_INDENT_PLACEHOLDER>MAXLOGMEMBERS 5\\n<MOCODO_INDENT_PLACEHOLDER>MAXDATAFILES 100\\n<MOCODO_INDENT_PLACEHOLDER>MAXINSTANCES 1\\n<MOCODO_INDENT_PLACEHOLDER>MAXLOGHISTORY 100\\n<MOCODO_INDENT_PLACEHOLDER>CHARACTER SET AL32UTF8\\n<MOCODO_INDENT_PLACEHOLDER>NATIONAL CHARACTER SET AL16UTF16\\n<MOCODO_INDENT_PLACEHOLDER>DATAFILE ''/path/to/{{title}}.dbf'' SIZE 100M\\n<MOCODO_INDENT_PLACEHOLDER>EXTENT MANAGEMENT LOCAL\\n<MOCODO_INDENT_PLACEHOLDER>DEFAULT TABLESPACE your_tablespace\\n<MOCODO_INDENT_PLACEHOLDER>DEFAULT TEMPORARY TABLESPACE your_temp_tablespace\\n;\\nCONNECT \"{title}\";\\n\\n{relations}\\n'\ntransform_relational_schema:\n  - order: 20000\n    comment: 'The indent placeholders in the _boilerplate_ where used to protect it from the addition of trailing commas. Transform them into double spaces.'\n    search: '<MOCODO_INDENT_PLACEHOLDER>'\n    replace: '  '\n"
  },
  {
    "path": "mocodo/resources/relation_templates/oracle.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for Oracle DB'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour Oracle DB'\nhelp_zh: '将概念模型转换为 Oracle DB 的物理模型'\nfr_examples:\n  - order: 1\n    example: 'oracle'\n    explanation: 'version de base'\n  - order: 4\n    example: 'oracle:b'\n    explanation: 'avec _boilerplate_'\nparent: 'sql'\nstem_suffix: '_ddl_oracle'\ntransform_label:\n  - order: 1100\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ARE|ARRAY|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUTHORIZATION|AUTOINCREMENT|AVG|BACKUP|BEFORE|BEGIN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|BREAK|BROWSE|BULK|CALL|CASCADE|CASCADED|CASE|CAST|CHANGE|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLLATION|COMMIT|COMPUTE|CONCAT|CONCURRENTLY|CONDITION|CONNECTION|CONSTRAINT|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CROSS|CUBE|CUME_DIST|CURRENT_CATALOG|CURRENT_DATE|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECLARE|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DENY|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DO|DOUBLE|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|END|ENUM|ERRLVL|ESCAPE|ESCAPED|EXCEPTION|EXCLUDE|EXEC|EXECUTE|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FALSE|FETCH|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOREIGN|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|ILIKE|INDEXED|INDICATOR|INFILE|INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISNULL|ISOLATION|ITERATE|JOIN|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEFT|LIMIT|LINEAR|LINENO|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MOD|MODIFIES|MONTH|MONTHS|NATIONAL|NATURAL|NCHAR|NEW|NEXT|NO|NOCHECK|NONCLUSTERED|NONE|NOTHING|NOTNULL|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMERIC|NVARCHAR|OFF|OFFSET|OFFSETS|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTIONALLY|OUT|OUTER|OUTFILE|OUTPUT|OVER|OVERLAPS|PAD|PARALLEL|PARTIAL|PARTITION|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRIMARY|PRINT|PRIVILEGES|PROC|PROCEDURE|PURGE|RAISE|RAISERROR|RANGE|RANK|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REFERENCES|REGEXP|RELATIVE|RELEASE|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESPECT|RESTORE|RESTRICT|RETURN|RETURNING|REVERT|RIGHT|RLIKE|ROLLBACK|ROLLUP|ROWCOUNT|ROWGUIDCOL|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION_USER|SETUSER|SHOW|SHUTDOWN|SIGNAL|SIMILAR|SOME|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUM|SYMMETRIC|SYSTEM|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAILING|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUE|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATETEXT|UPPER|USAGE|USE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALUE|VARBINARY|VARCHARACTER|VARIADIC|VARYING|VAR_POP|VAR_SAMP|VERBOSE|VIRTUAL|WAITFOR|WHEN|WHILE|WINDOW|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_relation_name:\n  - order: 1000\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ARE|ARRAY|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUTHORIZATION|AUTOINCREMENT|AVG|BACKUP|BEFORE|BEGIN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|BREAK|BROWSE|BULK|CALL|CASCADE|CASCADED|CASE|CAST|CHANGE|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLLATION|COMMIT|COMPUTE|CONCAT|CONCURRENTLY|CONDITION|CONNECTION|CONSTRAINT|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CROSS|CUBE|CUME_DIST|CURRENT_CATALOG|CURRENT_DATE|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECLARE|DEFERRABLE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DENY|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DO|DOUBLE|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|END|ENUM|ERRLVL|ESCAPE|ESCAPED|EXCEPTION|EXCLUDE|EXEC|EXECUTE|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FALSE|FETCH|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOREIGN|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|ILIKE|INDEXED|INDICATOR|INFILE|INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISNULL|ISOLATION|ITERATE|JOIN|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEFT|LIMIT|LINEAR|LINENO|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MOD|MODIFIES|MONTH|MONTHS|NATIONAL|NATURAL|NCHAR|NEW|NEXT|NO|NOCHECK|NONCLUSTERED|NONE|NOTHING|NOTNULL|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMERIC|NVARCHAR|OFF|OFFSET|OFFSETS|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTIONALLY|OUT|OUTER|OUTFILE|OUTPUT|OVER|OVERLAPS|PAD|PARALLEL|PARTIAL|PARTITION|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRIMARY|PRINT|PRIVILEGES|PROC|PROCEDURE|PURGE|RAISE|RAISERROR|RANGE|RANK|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REFERENCES|REGEXP|RELATIVE|RELEASE|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESPECT|RESTORE|RESTRICT|RETURN|RETURNING|REVERT|RIGHT|RLIKE|ROLLBACK|ROLLUP|ROWCOUNT|ROWGUIDCOL|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION_USER|SETUSER|SHOW|SHUTDOWN|SIGNAL|SIMILAR|SOME|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUM|SYMMETRIC|SYSTEM|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAILING|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIM|TRUE|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATETEXT|UPPER|USAGE|USE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALUE|VARBINARY|VARCHARACTER|VARIADIC|VARYING|VAR_POP|VAR_SAMP|VERBOSE|VIRTUAL|WAITFOR|WHEN|WHILE|WINDOW|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_datatype:\n  - order: 100\n    comment: '(Meant to replace the parent''s transformation)'\n    search: '^\\s*$'\n    replace: 'VARCHAR2(42)'\n  - order: 200\n    comment: '(Meant to replace the parent''s transformation)'\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'NUMBER(1) UNSIGNED'\n  - order: 300\n    comment: '(Meant to replace the parent''s transformation)'\n    search: 'BOOLEAN_PLACEHOLDER'\n    replace: 'NUMBER(1) DEFAULT 0'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/oracle_db-b.yaml",
    "content": "parent: 'oracle-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/oracle_db.yaml",
    "content": "parent: 'oracle'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/postgres-b.yaml",
    "content": "parent: 'postgresql-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/postgres.yaml",
    "content": "parent: 'postgresql'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/postgresql-b.yaml",
    "content": "parent: 'postgresql'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\nDROP DATABASE IF EXISTS ''{title}'';\\nCREATE DATABASE ''{title}''\\n<MOCODO_INDENT_PLACEHOLDER>ENCODING ''UTF8''\\n<MOCODO_INDENT_PLACEHOLDER>LC_COLLATE ''fr_FR.utf8''\\n<MOCODO_INDENT_PLACEHOLDER>LC_CTYPE ''fr_FR.utf8''\\n;\\nCONNECT ''{title}'';\\n\\n{relations}\\n'\ntransform_relational_schema:\n  - order: 20000\n    comment: 'The indent placeholders in the _boilerplate_ where used to protect it from the addition of trailing commas. Transform them into double spaces.'\n    search: '<MOCODO_INDENT_PLACEHOLDER>'\n    replace: '  '\n"
  },
  {
    "path": "mocodo/resources/relation_templates/postgresql.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for PostgreSQL'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour PostgreSQL'\nhelp_zh: '将概念模型转换为 PostgreSQL 的物理模型'\nfr_examples:\n  - order: 1\n    example: 'postgresql'\n    explanation: 'version de base'\n  - order: 4\n    example: 'postgresql:b'\n    explanation: 'avec _boilerplate_'\nparent: 'sql'\nstem_suffix: '_ddl_postgresql'\ntransform_label:\n  - order: 1100\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ADD|ALLOCATE|ALTER|ARE|ASENSITIVE|ASSERTION|AT|AUDIT|AUTOINCREMENT|AVG|BACKUP|BEFORE|BEGIN|BETWEEN|BIGINT|BIT|BLOB|BOOLEAN|BREAK|BROWSE|BULK|BY|CALL|CASCADE|CASCADED|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COMMENT|COMMIT|COMPRESS|COMPUTE|CONCAT|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CUBE|CUME_DIST|CURRENT|CURRENT_PATH|CURSOR|DATABASE|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFERRED|DEFINE|DEFINER|DELAYED|DELETE|DENSE_RANK|DENY|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DOUBLE|DROP|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|ENUM|ERRLVL|ESCAPE|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXISTS|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FILE|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOUND|FREETEXT|FREETEXTTABLE|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|IMMEDIATE|INCREMENT|INDEX|INDEXED|INDICATOR|INFILE|INITIAL|INOUT|INPUT|INSENSITIVE|INSERT|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LEAD|LEAVE|LEVEL|LINEAR|LINENO|LINES|LOAD|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATIONAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOTHING|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMBER|NUMERIC|NVARCHAR|OF|OFF|OFFLINE|OFFSETS|ONLINE|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTION|OPTIONALLY|OUT|OUTFILE|OUTPUT|OVER|PAD|PARALLEL|PARTIAL|PARTITION|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|RAISE|RAISERROR|RANGE|RANK|RAW|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RESTORE|RESTRICT|RETURN|REVERT|REVOKE|RLIKE|ROLLBACK|ROLLUP|ROW|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION|SET|SETUSER|SHARE|SHOW|SHUTDOWN|SIGNAL|SIZE|SMALLINT|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYNONYM|SYSDATE|SYSTEM|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIGGER|TRIM|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATE|UPDATETEXT|UPPER|USAGE|USE|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VALUES|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARYING|VAR_POP|VAR_SAMP|VIEW|VIRTUAL|WAITFOR|WHENEVER|WHILE|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_relation_name:\n  - order: 1000\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ADD|ALLOCATE|ALTER|ARE|ASENSITIVE|ASSERTION|AT|AUDIT|AUTOINCREMENT|AVG|BACKUP|BEFORE|BEGIN|BETWEEN|BIGINT|BIT|BLOB|BOOLEAN|BREAK|BROWSE|BULK|BY|CALL|CASCADE|CASCADED|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COMMENT|COMMIT|COMPRESS|COMPUTE|CONCAT|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CUBE|CUME_DIST|CURRENT|CURRENT_PATH|CURSOR|DATABASE|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFERRED|DEFINE|DEFINER|DELAYED|DELETE|DENSE_RANK|DENY|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DOUBLE|DROP|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|ENUM|ERRLVL|ESCAPE|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXISTS|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FILE|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FORCE|FOUND|FREETEXT|FREETEXTTABLE|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|IMMEDIATE|INCREMENT|INDEX|INDEXED|INDICATOR|INFILE|INITIAL|INOUT|INPUT|INSENSITIVE|INSERT|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LEAD|LEAVE|LEVEL|LINEAR|LINENO|LINES|LOAD|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATIONAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOTHING|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMBER|NUMERIC|NVARCHAR|OF|OFF|OFFLINE|OFFSETS|ONLINE|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTION|OPTIONALLY|OUT|OUTFILE|OUTPUT|OVER|PAD|PARALLEL|PARTIAL|PARTITION|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|RAISE|RAISERROR|RANGE|RANK|RAW|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RESTORE|RESTRICT|RETURN|REVERT|REVOKE|RLIKE|ROLLBACK|ROLLUP|ROW|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION|SET|SETUSER|SHARE|SHOW|SHUTDOWN|SIGNAL|SIZE|SMALLINT|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYNONYM|SYSDATE|SYSTEM|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAN|TRANSACTION|TRANSLATE|TRANSLATION|TREAT|TRIGGER|TRIM|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATE|UPDATETEXT|UPPER|USAGE|USE|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VALUES|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARYING|VAR_POP|VAR_SAMP|VIEW|VIRTUAL|WAITFOR|WHENEVER|WHILE|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_datatype:\n  - order: 300\n    comment: '(Meant to replace the parent''s transformation)'\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'SMALLINT'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sql.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for SQL'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour SQL'\nhelp_zh: '将概念模型转换为 SQL 的物理模型'\nstem_suffix: '_ddl'\nextension: 'sql'\nto_defer: false\nhighlight: 'sql'\ntransform_attribute:\n  - order: 100\n    comment: 'Ensure there are only letters, digits and underscores in the label.'\n    search: '(?u)\\W+'\n    replace: '_'\ntransform_relation_name:\n  - order: 100\n    comment: 'Ensure there are only letters, digits and underscores in the label.'\n    search: '(?u)\\W+'\n    replace: '_'\ntransform_datatype:\n  - order: 100\n    comment: 'Fill in empty data types with the default one.'\n    search: '^\\s*$'\n    replace: 'VARCHAR(42)'\n  - order: 200\n    search: 'BOOLEAN_PLACEHOLDER'\n    replace: 'BOOLEAN'\n  - order: 300\n    search: 'UNSIGNED_INT_PLACEHOLDER'\n    replace: 'UNSIGNED INT'\ntransform_optionality:\n  - order: 100\n    comment: 'Replace BANG with NOT NULL.'\n    search: '^!$'\n    replace: ' NOT NULL'\n  - order: 200\n    comment: 'Replace QMARK with NULL.'\n    search: '^\\?$'\n    replace: ' NULL'\nlabel_role_separator: '_'\ncompose_primary_key: '{label}{filler}{datatype}{optionality}\\nPRIMARY KEY ({label})'\ncompose_normal_attribute: '{label}{filler}{datatype}{optionality}'\ncompose_foreign_key: '{label}{filler}{datatype}{optionality}\\nFOREIGN KEY ({label}) REFERENCES {outer_source} ({non_disambiguated_label})'\ncompose_primary_foreign_key: '{label}{filler}{datatype}{optionality}\\nPRIMARY KEY ({label})\\nFOREIGN KEY ({label}) REFERENCES {outer_source} ({non_disambiguated_label})'\nadd_unicity_constraints:\n  - order: 100\n    search: '$'\n    replace: '\\nCONSTRAINT {this_relation_name}_u{unicities} UNIQUE ({label})'\ncolumn_separator: '\\n  '\ncompose_relation: 'CREATE TABLE {this_relation_name} (\\n  {columns}\\n);\\n'\ntransform_relation:\n  - order: 100\n    comment: 'Move the primary keys to the end of the table.'\n    search: '(?sm)^(PRIMARY KEY [^\\n]+)\\n(.*)^\\)'\n    replace: '\\2  \\1\\n)'\n    iterated: true\n  - order: 200\n    comment: 'Concatenate them.'\n    search: '(?m)^(  PRIMARY KEY )\\((.+)\\)\\n\\1\\((.+)\\)'\n    replace: '\\1(\\2, \\3)'\n    iterated: true\n  - order: 300\n    comment: 'Move the resulting clause to the beginning of the table.'\n    search: '(?m)^(CREATE TABLE .+\\n)((?:.+\\n)*)(  PRIMARY KEY .+\\n)'\n    replace: '\\1\\3\\2'\n  - order: 1100\n    comment: 'Move the foreign keys to the end of the table.'\n    search: '(?sm)^(FOREIGN KEY [^\\n]+)\\n(.*)^\\)'\n    replace: '\\2  \\1\\n)'\n    iterated: true\n  - order: 1200\n    comment: 'Concatenate them when the reference tables are the same and the foreign column are distinct.'\n    search: '(?sm)^(  FOREIGN KEY )\\(([^\\n]+)\\) (REFERENCES [^\\n]+ )\\(([^\\n]+)\\)\\n(.*?)^\\1\\(([^\\n]+)\\) \\3\\((?!\\4)([^\\n]+)\\)\\n'\n    replace: '\\1(\\2, \\6) \\3(\\4, \\7)\\n\\5'\n    iterated: true\n  - order: 2100\n    comment: 'Move the unique constraints to the end of the table.'\n    search: '(?sm)^(CONSTRAINT [^\\n]+ UNIQUE [^\\n]+)\\n(.*)^\\)'\n    replace: '\\2  \\1\\n)'\n    iterated: true\n  - order: 2200\n    comment: 'Explode the composite constraints, e.g. _u123.'\n    search: '(?m)^(  CONSTRAINT .+)_u(\\d)(\\d+)( UNIQUE .+\\n)'\n    replace: '\\1_u\\2\\4\\1_u\\3\\4'\n    iterated: true\n  - order: 2300\n    comment: 'Concatenate them.'\n    search: '(?sm)^(  CONSTRAINT [^\\n]+ UNIQUE )\\(([^\\n]+)\\)\\n(.*?)^\\1\\(([^\\n]+)\\)\\n'\n    replace: '\\1(\\2, \\4)\\n\\3'\n    iterated: true\n  - order: 2400\n    comment: 'Suppress their number, let the system name them.'\n    search: '(?m)^  CONSTRAINT [^\\n]+ (UNIQUE .+)'\n    replace: '  \\1'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\n{relations}\\n'\ntransform_relational_schema:\n  - order: 1000\n    comment: 'Move all foreign keys constraints to the end of the document.'\n    search: '(?m)(^CREATE TABLE ([^\\n]+) \\(\\n(?:  .+\\n)*)  (FOREIGN KEY .+)\\n((?:.*\\n)*)'\n    replace: '\\1\\4ALTER TABLE \\2 ADD \\3;\\n'\n    iterated: true\n  - order: 1100\n    comment: 'Group the foreign key constraints by table'\n    search: '(?m)^((ALTER TABLE .+?) ADD .+\\n)(?!\\2)'\n    replace: '\\1\\n'\n  - order: 10000\n    comment: 'Add a newline after the last \"^);\" followed by a non-empty line.'\n    search: '(?ms)(.+^\\);\\n)(?!\\n)'\n    replace: '\\1\\n'\n  - order: 10100\n    comment: 'Add a trailing comma to every line starting with two spaces and followed by two spaces.'\n    search: '(\\n  \\S.+)(?=\\n  \\S)'\n    replace: '\\1,'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sql_server-b.yaml",
    "content": "parent: 'mssql-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sql_server.yaml",
    "content": "parent: 'mssql'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sqlite-b.yaml",
    "content": "parent: 'sqlite'\ncompose_relational_schema: '-- Generated by Mocodo {version}\\n\\nCREATE DATABASE IF NOT EXISTS \"{title}\";\\nATTACH DATABASE \"{title}\";\\n\\n{relations}\\n'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sqlite.yaml",
    "content": "help_en: 'convert the conceptual model into a physical model for SQLite'\nhelp_fr: 'convertit le modèle conceptuel en un modèle physique pour SQLite'\nhelp_zh: '将概念模型转换为 SQLite 的物理模型'\nfr_examples:\n  - order: 1\n    example: 'sqlite'\n    explanation: 'version de base'\n  - order: 4\n    example: 'sqlite:b'\n    explanation: 'avec _boilerplate_'\nparent: 'sql'\nstem_suffix: '_ddl_sqlite'\ntransform_label:\n  - order: 1100\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ANY|ARE|ARRAY|ASC|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTHORIZATION|AVG|BACKUP|BEFORE|BEGIN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|BREAK|BROWSE|BULK|BY|CALL|CASCADE|CASCADED|CAST|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COLLATION|COLUMN|COMMENT|COMPRESS|COMPUTE|CONCAT|CONCURRENTLY|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CROSS|CUBE|CUME_DIST|CURRENT|CURRENT_CATALOG|CURRENT_DATE|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DENY|DESC|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DO|DOUBLE|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|END|ENUM|ERRLVL|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FALSE|FETCH|FILE|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FOR|FORCE|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GRANT|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INFILE|INITIAL|INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEFT|LEVEL|LIKE|LINEAR|LINENO|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATIONAL|NATURAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMBER|NUMERIC|NVARCHAR|OF|OFF|OFFLINE|OFFSET|OFFSETS|ONLINE|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTION|OPTIONALLY|OUT|OUTER|OUTFILE|OUTPUT|OVER|OVERLAPS|PAD|PARALLEL|PARTIAL|PARTITION|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|RAISE|RAISERROR|RANGE|RANK|RAW|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RESTORE|RESTRICT|RETURN|REVERT|REVOKE|RIGHT|RLIKE|ROLLBACK|ROLLUP|ROW|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION|SESSION_USER|SETUSER|SHARE|SHOW|SHUTDOWN|SIGNAL|SIMILAR|SIZE|SMALLINT|SOME|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAILING|TRAN|TRANSLATE|TRANSLATION|TREAT|TRIGGER|TRIM|TRUE|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATETEXT|UPPER|USAGE|USE|USER|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARIADIC|VARYING|VAR_POP|VAR_SAMP|VERBOSE|VIEW|VIRTUAL|WAITFOR|WHENEVER|WHILE|WINDOW|WITH|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_relation_name:\n  - order: 1000\n    comment: 'Protect reserved keywords'\n    search: '(?i)^(ACCESS|ACCESSIBLE|ALLOCATE|ANALYSE|ANALYZE|ANY|ARE|ARRAY|ASC|ASENSITIVE|ASSERTION|ASYMMETRIC|AT|AUDIT|AUTHORIZATION|AVG|BACKUP|BEFORE|BEGIN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOTH|BREAK|BROWSE|BULK|BY|CALL|CASCADE|CASCADED|CAST|CHANGE|CHAR|CHARACTER|CHARACTER_LENGTH|CHECKPOINT|CLOSE|CLUSTER|CLUSTERED|COALESCE|COLLATION|COLUMN|COMMENT|COMPRESS|COMPUTE|CONCAT|CONCURRENTLY|CONDITION|CONNECT|CONNECTION|CONSTRAINTS|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CORRESPONDING|COUNT|CROSS|CUBE|CUME_DIST|CURRENT|CURRENT_CATALOG|CURRENT_DATE|CURRENT_PATH|CURRENT_ROLE|CURRENT_SCHEMA|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DATE|DAY|DAYS|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFERRED|DEFINE|DEFINER|DELAYED|DENSE_RANK|DENY|DESC|DESCRIBE|DETERMINISTIC|DIAGNOSTICS|DISCONNECT|DISTINCTROW|DISTRIBUTED|DIV|DO|DOUBLE|DUAL|EACH|ELSEIF|EMPTY|ENCLOSED|END|ENUM|ERRLVL|ESCAPED|EXCEPTION|EXCLUDE|EXCLUSIVE|EXEC|EXECUTE|EXIT|EXPLAIN|EXTERNAL|EXTRACT|FALSE|FETCH|FILE|FILLFACTOR|FILTER|FIRST|FIRST_VALUE|FLOAT|FLOAT4|FLOAT8|FOLLOWING|FOR|FORCE|FOUND|FREETEXT|FREETEXTTABLE|FREEZE|FULL|FULLTEXT|FUNCTION|GENERATED|GET|GLOB|GLOBAL|GO|GOTO|GRANT|GROUPING|GROUPS|HASH|HIGH_PRIORITY|HOLDLOCK|HOUR|HOURS|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IDENTIFIED|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IGNORE|ILIKE|IMMEDIATE|INCREMENT|INDEXED|INDICATOR|INFILE|INITIAL|INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INVOKER|IO_AFTER_GTIDS|IO_BEFORE_GTIDS|ISOLATION|ITERATE|JSON_ARRAYAGG|JSON_EXISTS|JSON_OBJECTAGG|JSON_TABLE|KEY|KEYS|KILL|LAG|LAST|LAST_VALUE|LATERAL|LEAD|LEADING|LEAVE|LEFT|LEVEL|LIKE|LINEAR|LINENO|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOWER|LOW_PRIORITY|LTRIM|MASTER_BIND|MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAX|MAXEXTENTS|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MEMBER|MERGE|MICROSECOND|MICROSECONDS|MIDDLEINT|MIN|MINUS|MINUTE|MINUTES|MINUTE_MICROSECOND|MINUTE_SECOND|MLSLABEL|MOD|MODE|MODIFIES|MODIFY|MONTH|MONTHS|NATIONAL|NATURAL|NCHAR|NEW|NEXT|NO|NOAUDIT|NOCHECK|NOCOMPRESS|NONCLUSTERED|NONE|NOWAIT|NO_WRITE_TO_BINLOG|NTH_VALUE|NTILE|NULLIF|NULLS|NUMBER|NUMERIC|NVARCHAR|OF|OFF|OFFLINE|OFFSET|OFFSETS|ONLINE|ONLY|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTIMIZE|OPTIMIZER_COSTS|OPTION|OPTIONALLY|OUT|OUTER|OUTFILE|OUTPUT|OVER|OVERLAPS|PAD|PARALLEL|PARTIAL|PARTITION|PCTFREE|PERCENT|PERCENTILE_CONT|PERCENTILE_DISC|PERCENT_RANK|PIVOT|PLACING|PLAN|PORTION|POSITION|PRECEDING|PRECISION|PREPARE|PRESERVE|PRINT|PRIOR|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|RAISE|RAISERROR|RANGE|RANK|RAW|READ|READS|READTEXT|READ_WRITE|REAL|RECONFIGURE|RECURSIVE|REGEXP|RELATIVE|RELEASE|RENAME|REPEAT|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESOURCE|RESPECT|RESTORE|RESTRICT|RETURN|REVERT|REVOKE|RIGHT|RLIKE|ROLLBACK|ROLLUP|ROW|ROWCOUNT|ROWGUIDCOL|ROWID|ROWNUM|ROWS|ROW_NUMBER|RTRIM|RULE|SAVE|SCHEMA|SCHEMAS|SCROLL|SECOND|SECONDS|SECOND_MICROSECOND|SEMANTICKEYPHRASETABLE|SEMANTICSIMILARITYDETAILSTABLE|SEMANTICSIMILARITYTABLE|SENSITIVE|SEPARATOR|SESSION|SESSION_USER|SETUSER|SHARE|SHOW|SHUTDOWN|SIGNAL|SIMILAR|SIZE|SMALLINT|SOME|SOUNDS|SPACE|SPATIAL|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLID|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_BUFFER_RESULT|SQL_CACHE|SQL_CALC_FOUND_ROWS|SQL_NO_CACHE|SQL_SMALL_RESULT|SSL|START|STARTING|STATISTICS|STATS_AUTO_RECALC|STATS_PERSISTENT|STATS_SAMPLE_PAGES|STDDEV_POP|STDDEV_SAMP|STORED|STRAIGHT_JOIN|SUBSTRING|SUCCESSFUL|SUM|SYMMETRIC|SYNONYM|SYSDATE|SYSTEM|SYSTEM_USER|TABLESAMPLE|TEMPORARY|TERMINATED|TEXTSIZE|TIMEZONE_HOUR|TIMEZONE_MINUTE|TINYBLOB|TINYINT|TINYTEXT|TOP|TRAILING|TRAN|TRANSLATE|TRANSLATION|TREAT|TRIGGER|TRIM|TRUE|TRUNCATE|TRY_CONVERT|TSEQUAL|UESCAPE|UID|UNBOUNDED|UNDO|UNKNOWN|UNLOCK|UNNEST|UNPIVOT|UNSIGNED|UPDATETEXT|UPPER|USAGE|USE|USER|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALIDATE|VALUE|VARBINARY|VARCHAR|VARCHAR2|VARCHARACTER|VARIADIC|VARYING|VAR_POP|VAR_SAMP|VERBOSE|VIEW|VIRTUAL|WAITFOR|WHENEVER|WHILE|WINDOW|WITH|WITHIN|WITHOUT|WORK|WRITE|WRITETEXT|XML|XMLCAST|XMLEXISTS|XMLFOREST|XMLPARSE|XMLQUERY|XMLROOT|XMLSERIALIZE|XOR|YEAR|YEARS|YEAR_MONTH|ZEROFILL)$'\n    replace: '\"\\1\"'\ntransform_relation:\n  - order: 300\n    comment: 'Prevent moving primary key constraints to the beginning of the table (cf. parent template).'\ntransform_relational_schema:\n  - order: 1000\n    comment: 'Prevent moving foreign key constraints to the end of the table (cf. parent template).'\n  - order: 1100\n    comment: 'Prevent grouping foreign key constraints (cf. parent template).'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sqlserver-b.yaml",
    "content": "parent: 'mssql-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/sqlserver.yaml",
    "content": "parent: 'mssql'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-b.yaml",
    "content": "parent: 'latex-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-bc.yaml",
    "content": "parent: 'latex-bc'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-bce.yaml",
    "content": "parent: 'latex-bce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-be.yaml",
    "content": "parent: 'latex-be'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-c.yaml",
    "content": "parent: 'latex-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-ce.yaml",
    "content": "parent: 'latex-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex-e.yaml",
    "content": "parent: 'latex-e'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/tex.yaml",
    "content": "parent: 'latex'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-b.yaml",
    "content": "parent: 'text-c'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-bc.yaml",
    "content": "parent: 'text-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-bce.yaml",
    "content": "parent: 'text-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-be.yaml",
    "content": "parent: 'text-bce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-c.yaml",
    "content": "parent: 'html-c'\nextension: 'txt'\nhighlight: 'text'\ntransform_attribute:\ntransform_relation_name:\ncolumn_separator: ', '\ncompose_relation: '- {this_relation_name} ({columns})'\ntransform_relation:\n  - order: 10000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\1'\n  - order: 10100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '_\\1_'\n  - order: 10200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>(.+?)</span>'\n    replace: '_\\1_'\n  - order: 10300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>(.+?)</span>'\n    replace: '\\1'\ncompose_relational_schema: '# Generated by Mocodo {version}\\n\\n{relations}'\ntransform_relational_schema:\n  - order: 10000\n    search: '(<sup>[^<]*)u0 ?([^<]*</sup>)'\n    replace: '\\1⁰\\2'\n  - order: 10100\n    search: '(<sup>[^<]*)u1 ?([^<]*</sup>)'\n    replace: '\\1¹\\2'\n  - order: 10200\n    search: '(<sup>[^<]*)u2 ?([^<]*</sup>)'\n    replace: '\\1²\\2'\n  - order: 10300\n    search: '(<sup>[^<]*)u3 ?([^<]*</sup>)'\n    replace: '\\1³\\2'\n  - order: 10400\n    search: '(<sup>[^<]*)u4 ?([^<]*</sup>)'\n    replace: '\\1⁴\\2'\n  - order: 10500\n    search: '(<sup>[^<]*)u5 ?([^<]*</sup>)'\n    replace: '\\1⁵\\2'\n  - order: 10600\n    search: '(<sup>[^<]*)u6 ?([^<]*</sup>)'\n    replace: '\\1⁶\\2'\n  - order: 10700\n    search: '(<sup>[^<]*)u7 ?([^<]*</sup>)'\n    replace: '\\1⁷\\2'\n  - order: 10800\n    search: '(<sup>[^<]*)u8 ?([^<]*</sup>)'\n    replace: '\\1⁸\\2'\n  - order: 10900\n    search: '(<sup>[^<]*)u9 ?([^<]*</sup>)'\n    replace: '\\1⁹\\2'\n  - order: 11000\n    search: ' <sup>|</sup>'\n    replace: ''\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-ce.yaml",
    "content": "parent: 'html-ce'\nextension: 'txt'\nhighlight: 'text'\ncolumn_separator: ', '\ncompose_relation: '- {this_relation_name} ({columns})'\ntransform_relation:\n  - order: 10000\n    comment: 'Compose normal attributes'\n    search: '<span class=''normal''>(.+?)</span>'\n    replace: '\\1'\n  - order: 10100\n    comment: 'Compose primary keys'\n    search: '<span class=''primary''>(.+?)</span>'\n    replace: '_\\1_'\n  - order: 10200\n    comment: 'Compose foreign primary keys'\n    search: '<span class=''foreign primary''>(.+?)</span>'\n    replace: '_\\1_'\n  - order: 10300\n    comment: 'Compose foreign attributes'\n    search: '<span class=''foreign''>(.+?)</span>'\n    replace: '\\1'\ncompose_relational_schema: '# Generated by Mocodo {version}\\n\\n{relations}{deleted_relations}'\ntransform_relational_schema:\n  - order: 1000\n    comment: 'Process italics'\n    search: '<i>(.+?)</i>'\n    replace: '«\\xa0\\1\\xa0»'\n  - order: 1100\n    comment: 'Process strong'\n    search: '</?strong>'\n    replace: ''\n  - order: 1200\n    comment: 'Format lists'\n    search: '    <li>(.+?)</li>'\n    replace: '  - \\1'\n  - order: 1300\n    search: '<hr>'\n    replace: '\\n--------------------------------------------------------------------------------'\n  - order: 1400\n    search: '<div>\\n  <span>(.+?)</span>\\n</div>'\n    replace: '\\1'\n  - order: 10000\n    search: '(<sup>[^<]*)u0 ?([^<]*</sup>)'\n    replace: '\\1⁰\\2'\n  - order: 10100\n    search: '(<sup>[^<]*)u1 ?([^<]*</sup>)'\n    replace: '\\1¹\\2'\n  - order: 10200\n    search: '(<sup>[^<]*)u2 ?([^<]*</sup>)'\n    replace: '\\1²\\2'\n  - order: 10300\n    search: '(<sup>[^<]*)u3 ?([^<]*</sup>)'\n    replace: '\\1³\\2'\n  - order: 10400\n    search: '(<sup>[^<]*)u4 ?([^<]*</sup>)'\n    replace: '\\1⁴\\2'\n  - order: 10500\n    search: '(<sup>[^<]*)u5 ?([^<]*</sup>)'\n    replace: '\\1⁵\\2'\n  - order: 10600\n    search: '(<sup>[^<]*)u6 ?([^<]*</sup>)'\n    replace: '\\1⁶\\2'\n  - order: 10700\n    search: '(<sup>[^<]*)u7 ?([^<]*</sup>)'\n    replace: '\\1⁷\\2'\n  - order: 10800\n    search: '(<sup>[^<]*)u8 ?([^<]*</sup>)'\n    replace: '\\1⁸\\2'\n  - order: 10900\n    search: '(<sup>[^<]*)u9 ?([^<]*</sup>)'\n    replace: '\\1⁹\\2'\n  - order: 11000\n    search: ' <sup>|</sup>'\n    replace: ''\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text-e.yaml",
    "content": "parent: 'text-ce'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/text.yaml",
    "content": "help_en: 'convert the conceptual model into a relational schema in text format'\nhelp_fr: 'convertit le modèle conceptuel en un schéma relationnel au format texte'\nhelp_zh: '将概念模型转换为文本格式的关系模式'\nparent: 'text-c'\nfr_examples:\n  - order: 1\n    example: 'text'\n    explanation: 'version de base'\n  - order: 2\n    example: 'text:c'\n    explanation: 'avec contraintes d''unicité et d''optionalité'\n  - order: 3\n    example: 'html:e'\n    explanation: 'avec explications'\n  - order: 5\n    example: 'html:ce'\n    explanation: 'avec contraintes et explications'\nadd_unicity_constraints:\nadd_optionality_constraints:\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-b.yaml",
    "content": "parent: 'text-b'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-bc.yaml",
    "content": "parent: 'text-bc'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-bce.yaml",
    "content": "parent: 'text-bce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-be.yaml",
    "content": "parent: 'text-be'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-c.yaml",
    "content": "parent: 'text-c'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-ce.yaml",
    "content": "parent: 'text-ce'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt-e.yaml",
    "content": "parent: 'text-e'\n"
  },
  {
    "path": "mocodo/resources/relation_templates/txt.yaml",
    "content": "parent: 'text'\n"
  },
  {
    "path": "mocodo/resources/rendering_services.json",
    "content": "{\n    \"d2\": {\n        \"preprocessing\": [\"urlsafe_encoding\"],\n        \"url\": \"https://kroki.io/d2/svg/{data}\"\n    },\n    \"gv\": {\n        \"preprocessing\": [\"minify_graphviz\", \"urlsafe_encoding\"],\n        \"url\": \"https://kroki.io/graphviz/svg/{data}\"\n    },\n    \"mmd\": {\n        \"preprocessing\": [\"urlsafe_encoding\"],\n        \"url\": \"https://kroki.io/mermaid/svg/{data}\"\n    },\n    \"puml\": {\n        \"preprocessing\": [\"urlsafe_encoding\"],\n        \"url\": \"https://kroki.io/plantuml/svg/{data}\"\n    },\n    \"url\": {\n        \"preprocessing\": [\"encode_prefix\"],\n        \"url\": \"https://api.qrserver.com/v1/create-qr-code/?format=svg&size=1000x1000&qzone=1&data={data}\"\n    }\n}"
  },
  {
    "path": "mocodo/resources/shapes/arial.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Arial\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 13\n  },\n  \"attribute_text_height_ratio\": 0.7,\n  \"box_stroke_depth\": 3,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Arial\",\n    \"size\": 12\n  },\n  \"card_margin\": 6,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1.2,\n  \"card_underline_skip_height\": -3,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2.5,\n  \"constraint_font\": {\n    \"family\": \"Arial\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1.5,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Arial\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 13\n  },\n  \"inner_stroke_depth\": 1.5,\n  \"label_font\": {\n    \"family\": \"Arial\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1.5,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 13\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 8,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 6,\n  \"round_rect_margin_width\": 9,\n  \"underline_depth\": 1.2,\n  \"underline_skip_height\": -2\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/copperplate.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Gill Sans\",\n    \"size\": 15\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Copperplate\",\n    \"size\": 18\n  },\n  \"attribute_text_height_ratio\": 0.65,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Futura\",\n    \"size\": 11\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -2,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Futura\",\n    \"size\": 11\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.1,\n  \"entity_attribute_font\": {\n    \"family\": \"Gill Sans\",\n    \"size\": 15\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Copperplate\",\n    \"size\": 18\n  },\n  \"inner_stroke_depth\": 1.5,\n  \"label_font\": {\n    \"family\": \"Futura\",\n    \"size\": 11\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 0,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Futura\",\n    \"size\": 16\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 6,\n  \"rect_margin_width\": 8,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": -3\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/georgia.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Georgia\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Georgia\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -2,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Georgia\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Georgia\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Georgia\",\n    \"size\": 15\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/mondrian.json",
    "content": "{\n  \"arrow_axis\": 12,\n  \"arrow_half_height\": 9,\n  \"arrow_width\": 18,\n  \"association_attribute_font\": {\n    \"family\": \"Skia\",\n    \"size\": 18,\n    \"weight\": \"bold\"\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Skia\",\n    \"size\": 20,\n    \"weight\": \"bold\"\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 5,\n  \"card_baseline\": 4,\n  \"card_font\": {\n    \"family\": \"Skia\",\n    \"size\": 18,\n    \"weight\": \"bold\"\n  },\n  \"card_margin\": 8,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1.2,\n  \"card_underline_skip_height\": -3,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 10,\n  \"constraint_dot_stroke_depth\": 7,\n  \"constraint_font\": {\n    \"family\": \"Skia\",\n    \"size\": 18,\n    \"weight\": \"bold\"\n  },\n  \"constraint_margin\": 8,\n  \"constraint_stroke_depth\": 5,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 2,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Skia\",\n    \"size\": 18,\n    \"weight\": \"bold\"\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Skia\",\n    \"size\": 20,\n    \"weight\": \"bold\"\n  },\n  \"inner_stroke_depth\": 5,\n  \"label_font\": {\n    \"family\": \"Skia\",\n    \"size\": 18,\n    \"weight\": \"bold\"\n  },\n  \"leg_stroke_depth\": 5,\n  \"line_skip_height\": 1,\n  \"margin\": 25,\n  \"note_baseline\": 32,\n  \"note_font\": {\n    \"family\": \"Skia\",\n    \"size\": 20,\n    \"weight\": \"bold\"\n  },\n  \"note_overlay_height\": 50,\n  \"rect_margin_height\": 10,\n  \"rect_margin_width\": 10,\n  \"round_corner_radius\": 2,\n  \"round_rect_margin_height\": 10,\n  \"round_rect_margin_width\": 10,\n  \"underline_depth\": 1.2,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/sans.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 12\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": 1,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 2.5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Liberation Sans\",\n    \"size\": 14\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/serif.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 12\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": 1,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 2.5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Liberation Serif\",\n    \"size\": 14\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/times.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Times New Roman\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Times New Roman\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -2,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.1,\n  \"entity_attribute_font\": {\n    \"family\": \"Times New Roman\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Times New Roman\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Times New Roman\",\n    \"size\": 16\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/trebuchet.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Trebuchet MS\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Trebuchet MS\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 1.5,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -2,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 5.0,\n  \"constraint_dot_stroke_depth\": 2,\n  \"constraint_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 0.9,\n  \"entity_attribute_font\": {\n    \"family\": \"Trebuchet MS\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Trebuchet MS\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12\n  },\n  \"leg_stroke_depth\": 1,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Trebuchet MS\",\n    \"size\": 14\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0.0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/verdana.json",
    "content": "{\n  \"arrow_axis\": 8,\n  \"arrow_half_height\": 6,\n  \"arrow_width\": 12,\n  \"association_attribute_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"attribute_text_height_ratio\": 0.85,\n  \"box_stroke_depth\": 2,\n  \"card_baseline\": 3,\n  \"card_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"card_margin\": 5,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -2,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 6,\n  \"constraint_dot_stroke_depth\": 3,\n  \"constraint_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"constraint_margin\": 5,\n  \"constraint_stroke_depth\": 1.5,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"inner_stroke_depth\": 1,\n  \"label_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 12,\n    \"weight\": \"bold\"\n  },\n  \"leg_stroke_depth\": 2,\n  \"line_skip_height\": 2,\n  \"margin\": 9,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Verdana\",\n    \"size\": 14\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 5,\n  \"rect_margin_width\": 5,\n  \"round_corner_radius\": 14,\n  \"round_rect_margin_height\": 5,\n  \"round_rect_margin_width\": 7,\n  \"underline_depth\": 1,\n  \"underline_skip_height\": 0\n}\n"
  },
  {
    "path": "mocodo/resources/shapes/xinnian.json",
    "content": "{\n  \"arrow_axis\": 12,\n  \"arrow_half_height\": 9,\n  \"arrow_width\": 18,\n  \"association_attribute_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 14\n  },\n  \"association_cartouche_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 14\n  },\n  \"attribute_text_height_ratio\": 0.5,\n  \"box_stroke_depth\": 5,\n  \"card_baseline\": 5,\n  \"card_font\": {\n    \"family\": \"Comic Sans MS\",\n    \"size\": 14\n  },\n  \"card_margin\": 10,\n  \"card_text_height_ratio\": 0.85,\n  \"card_underline_depth\": 1,\n  \"card_underline_skip_height\": -4.0,\n  \"cartouche_text_height_ratio\": 0.85,\n  \"constraint_dot_gap_width\": 8,\n  \"constraint_dot_stroke_depth\": 4,\n  \"constraint_font\": {\n    \"family\": \"Comic Sans MS\",\n    \"size\": 14\n  },\n  \"constraint_margin\": 5.0,\n  \"constraint_stroke_depth\": 2,\n  \"constraint_text_height_tweak\": 0.3,\n  \"dash_width\": 4,\n  \"df_text_height_ratio\": 1.0,\n  \"entity_attribute_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 14\n  },\n  \"entity_cartouche_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 14\n  },\n  \"inner_stroke_depth\": 0.5,\n  \"label_font\": {\n    \"family\": \"Comic Sans MS\",\n    \"size\": 14\n  },\n  \"leg_stroke_depth\": 2,\n  \"line_skip_height\": 2,\n  \"margin\": 20,\n  \"note_baseline\": 24,\n  \"note_font\": {\n    \"family\": \"Arial Black\",\n    \"size\": 16\n  },\n  \"note_overlay_height\": 40,\n  \"rect_margin_height\": 9,\n  \"rect_margin_width\": 14,\n  \"round_corner_radius\": 30,\n  \"round_rect_margin_height\": 10,\n  \"round_rect_margin_width\": 14,\n  \"underline_depth\": 2,\n  \"underline_skip_height\": -5.0\n}\n"
  },
  {
    "path": "mocodo/resources/transformations.json",
    "content": "{\n  \"arrange\": {\n    \"category\": \"rw\",\n    \"help\": \"réarrange la disposition, soit par Branch & Bound, soit avec un algorithme génétique\",\n    \"fr_examples\": {\n      \"arrange\": \"B&B sans contraintes\",\n      \"arrange:timeout=60\": \"B&B limité à une minute\",\n      \"arrange:wide\": \"B&B privilégiant la largeur\",\n      \"arrange:current\": \"B&B sur la grille courante\",\n      \"arrange:balanced=0\": \"B&B sur la plus petite grille équilibrée\",\n      \"arrange:balanced=1\": \"B&B sur la seconde plus petite grille équilibrée\",\n      \"arrange:algo=ga\": \"algorithme génétique\"\n    },\n    \"aliases\": []\n  },\n  \"ascii\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en ASCII\",\n    \"fr_examples\": {\n      \"ascii:roles,labels\": \"rôles, libellés des boîtes et des attributs en ASCII\"\n    },\n    \"aliases\": [],\n    \"op_tk\": true\n  },\n  \"ast\": {\n    \"category\": \"cv\",\n    \"help\": \"crée l'arbre de syntaxe abstraite du texte source (pour le débogage)\",\n    \"aliases\": []\n  },\n  \"camel\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en camelCase\",\n    \"aliases\": [\n      \"camelcase\",\n      \"camel_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"capitalize\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en capitalisant la première lettre de chaque mot\",\n    \"aliases\": [],\n    \"op_tk\": true\n  },\n  \"casefold\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en minuscules, mais plus agressivement que « lower »\",\n    \"aliases\": [\n      \"case_fold\"\n    ],\n    \"op_tk\": true\n  },\n  \"prompt\": {\n    \"category\": \"cv\",\n    \"help\": \"génère un prompt pour demander à une IA de compléter le MCD\",\n    \"fr_examples\": {\n      \"prompt:cards\": \"avec les explications des cardinalités\",\n      \"prompt:types\": \"avec les types des attributs\"\n    },\n    \"aliases\": [\n      \"chat\",\n      \"chatbot\",\n      \"ia\",\n      \"ai\"\n    ]\n  },\n  \"chen\": {\n    \"category\": \"cv\",\n    \"help\": \"convertit le modèle conceptuel dans la notation de Chen\",\n    \"fr_examples\": {\n      \"chen\": \"sans attributs\",\n      \"chen:attrs\": \"avec attributs\",\n      \"chen:attrs --defer\": \"calcule le rendu graphique via un service web\",\n      \"chen:layout=circo,mindist=2,scale=0.6\": \"ajoute des options arbitraires pour Graphviz\"\n    },\n    \"aliases\": []\n  },\n  \"create\": {\n    \"category\": \"rw\",\n    \"help\": \"essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants\",\n    \"fr_examples\": {\n      \"guess:types\": \"deviner les types manquants\",\n      \"create:types=\": \"remplacer les types manquants par `[]`\",\n      \"create:types=TODO\": \"remplacer les types manquants par `[TODO]`\",\n      \"make:entities\": \"réparer l'oubli d'entités référencées dans des associations\",\n      \"create:dfs\": \"mettre des DF partout où c'est possible\",\n      \"add:df_arrows\": \"ajouter des flèches aux DF 11\",\n      \"add:cifs\": \"ajouter les CIF correspondant aux agrégats\",\n      \"add:cifs=light\": \"même chose en visualisation allégée\",\n      \"add:roles\": \"mettre comme rôles le nom des associations partout où c'est utile\"\n    },\n    \"aliases\": [\n      \"add\",\n      \"insert\",\n      \"make\",\n      \"guess\",\n      \"infer\",\n      \"complete\",\n      \"new\"\n    ],\n    \"op_tk\": true\n  },\n  \"crow\": {\n    \"category\": \"cv\",\n    \"help\": \"convertit le modèle conceptuel dans la notation crow's foot\",\n    \"fr_examples\": {\n      \"crow\": \"format Graphviz\",\n      \"crow --defer\": \"calcule le rendu graphique via un service web\",\n      \"crow:mmd\": \"format Mermaid\",\n      \"crow:mermaid\": \"idem\"\n    },\n    \"aliases\": [\n      \"crowfoot\",\n      \"crowsfoot\"\n    ]\n  },\n  \"data_dict\": {\n    \"category\": \"cv\",\n    \"help\": \"extrait tous les attributs du MCD dans une table\",\n    \"aliases\": [\n      \"data_dictionary\"\n    ],\n    \"fr_examples\": {\n      \"data_dict\": \"tableau Markdown, trois colonnes\",\n      \"data_dict:label\": \"liste Markdown, une colonne\",\n      \"data_dict:label,type='Description'\": \"deux colonnes, un libellé personnalisé\",\n      \"data_dict:label='Attribut',type='Description'\": \"deux colonnes, deux libellés personnalisés\",\n      \"data_dict:**box**='Entité ou<br>association',label,`type`=`'Type de données'`\": \"mise en forme de certains libellés\",\n      \"data_dict:tsv\": \"tableau TSV, trois colonnes\",\n      \"data_dict:tsv,label\": \"liste des attributs séparés par des retours à la ligne\"\n    }\n  },\n  \"delete\": {\n    \"category\": \"rw\",\n    \"help\": \"supprime les éléments donnés quand c'est possible\",\n    \"fr_examples\": {\n      \"empty\": \"ne garde que la structure et le nom des boîtes\",\n      \"delete:types,notes,attrs,cards\": \"idem\",\n      \"delete:cards\": \"remplace les cardinalités par `XX`\",\n      \"delete:card_prefixes\": \"supprime les marqueurs d'entités faibles et d'agrégats\",\n      \"delete:dfs\": \"supprime les entités indépendantes dont tous les attributs sont identifiants (et les DF qui les relient)\"\n    },\n    \"aliases\": [\n      \"del\",\n      \"suppress\",\n      \"erase\",\n      \"remove\",\n      \"hide\",\n      \"empty\"\n    ],\n    \"op_tk\": true\n  },\n  \"drain\": {\n    \"category\": \"rw\",\n    \"help\": \"déplace tout attribut d'association (1,1) vers l'entité appropriée\",\n    \"aliases\": []\n  },\n  \"drown\": {\n    \"category\": \"rw\",\n    \"help\": \"remplace tous les noms d'éléments par un libellé générique numéroté\",\n    \"aliases\": [\n      \"drown_by_numbers\",\n      \"anonymize\",\n      \"anonymise\"\n    ]\n  },\n  \"echo\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit le texte source tel quel\",\n    \"aliases\": []\n  },\n  \"explode\": {\n    \"category\": \"rw\",\n    \"help\": \"décompose toute association n-aire (*,N) en n associations binaires\",\n    \"fr_examples\": {\n      \"explode arrange\": \"décomposer les non-DF ternaires et plus, puis réarranger\",\n      \"explode:arity=3 arrange\": \"idem\",\n      \"explode:weak arrange\": \"idem, avec création d'entités faibles\",\n      \"explode:arity=2.5 arrange\": \"étendre aux non-DF binaires porteuses d'attributs\",\n      \"explode:arity=2 arrange\": \"étendre à toutes les non-DF binaires\"\n    },\n    \"aliases\": []\n  },\n  \"fix\": {\n    \"category\": \"rw\",\n    \"help\": \"essaie de corriger les erreurs courantes dans les éléments donnés\",\n    \"fr_examples\": {\n      \"fix:cards\": \"normaliser les cardinalités en 01, 11, 0N et 1N\"\n    },\n    \"aliases\": [],\n    \"op_tk\": true\n  },\n  \"flip\": {\n    \"category\": \"rw\",\n    \"help\": \"applique au diagramme une symétrie verticale, horizontale ou diagonale\",\n    \"fr_examples\": {\n      \"flip:v\": \"symétrie verticale\",\n      \"flip:h\": \"symétrie horizontale\",\n      \"flip:d\": \"symétrie selon la seconde diagonale\",\n      \"flip:vhd\": \"symétrie selon la première diagonale\",\n      \"flip:dhv\": \"idem (ordre indifférent)\"\n    },\n    \"aliases\": [\n      \"mirror\",\n      \"reflect\"\n    ]\n  },\n  \"grow\": {\n    \"category\": \"rw\",\n    \"help\": \"ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations)\",\n    \"fr_examples\": {\n      \"grow arrange\": \"ajouter des éléments avec les paramètres par défaut, puis réarranger\",\n      \"grow:n=10\": \"nombre total d'associations à ajouter (défaut)\",\n      \"grow:arity_1=2\": \"nombre d'associations réflexives (défaut)\",\n      \"grow:arity_3=2\": \"nombre d'associations ternaires (défaut)\",\n      \"grow:arity_4=0\": \"nombre d'associations quaternaires (défaut)\",\n      \"grow:doubles=1\": \"nombre d'associations liant deux mêmes entités (défaut)\",\n      \"grow:composite_ids=1\": \"nombre d'identifiants composites (défaut)\",\n      \"grow:ent_attrs=4\": \"nombre maximal d'attributs par entité (défaut)\",\n      \"grow:assoc_attrs=2\": \"nombre maximal d'attributs par association (défaut)\",\n      \"grow:'*1-*N'=3\": \"nombre d'associations `*1-*N` (défaut)\",\n      \"grow:'01-11'=1\": \"nombre d'associations `01-11` (défaut)\",\n      \"grow:'_11-*N'=1\": \"une entité faible (zéro par défaut)\",\n      \"grow:'/1N-*N'=1\": \"un agrégat (zéro par défaut)\",\n      \"grow:from_scratch arrange\": \"à partir d'un MCD vide\",\n      \"grow:grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange\": \"créer un MCD d'entraînement à la conversion en relationnel\"\n    },\n    \"aliases\": []\n  },\n  \"lower\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en minuscules\",\n    \"fr_examples\": {\n      \"lower:attrs,roles\": \"attributs et rôles en minuscules\"\n    },\n    \"aliases\": [\n      \"lowercase\",\n      \"lower_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"pascal\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les élements donnés en PascalCase\",\n    \"aliases\": [\n      \"pascalcase\",\n      \"pascal_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"prefix\": {\n    \"category\": \"rw\",\n    \"help\": \"préfixe les éléments donnés avec la chaîne donnée\",\n    \"fr_examples\": {\n      \"prefix:roles='-'\": \"force les rôles à remplacer le nom des clés étrangères lors du passage au relationnel\"\n    },\n    \"aliases\": [\n      \"prepend\"\n    ],\n    \"op_tk\": true\n  },\n  \"randomize\": {\n    \"category\": \"rw\",\n    \"help\": \"garde la structure, mais randomise les éléments donnés quand c'est possible\",\n    \"fr_examples\": {\n      \"obfuscate\": \"libellés remplacés par du Lorem Ipsum\",\n      \"obfuscate:labels=lorem\": \"idem\",\n      \"obfuscate:labels=disparition\": \"idem, lexique du roman de Perec\",\n      \"obfuscate:labels=en4\": \"idem, mots anglais de 4 lettres (SFW)\",\n      \"obfuscate:attrs=fr,boxes=fr5\": \"idem, mots français de longueur quelconque pour les attributs, de 5 lettres pour les boîtes\",\n      \"randomize:types\": \"types randomisés avec les fréquences de `default_datatypes_fr.tsv`.\"\n    },\n    \"aliases\": [\n      \"rand\",\n      \"random\",\n      \"randomise\",\n      \"obfuscate\",\n      \"obscure\"\n    ],\n    \"op_tk\": true\n  },\n  \"relation\": {\n    \"category\": \"cv\",\n    \"help\": \"convertit le modèle conceptuel en schéma relationnel avec le gabarit donné\",\n    \"fr_examples\": {\n      \"relation:path/to/my_template.yaml\": \"chemin relatif, extension obligatoire\"\n    },\n    \"aliases\": [\n      \"template\",\n      \"relation_template\"\n    ]\n  },\n  \"replace\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné\",\n    \"fr_examples\": {\n      \"replace:boxes='DIRIGER/RÉPONDRE DE'\": \"renomme une boîte\",\n      \"replace:texts='personel/personnel'\": \"corrige une faute d'orthographe\",\n      \"replace:replace:texts='_/ '\": \"remplace les tirets bas par des espaces\",\n      \"replace:types='VARCHAR/VARCHAR2'\": \"modifie un nom de type\",\n      \"replace:cards=0N/1N\": \"remplace toutes les cardinalités 0N par 1N\",\n      \"replace:cards=1N//1N\": \"crée des agrégats un peu partout\",\n      \"replace:cards='0/X' replace:cards='11/X1' replace:cards='1N/XN'\": \"masque les cardinalités minimales\",\n      \"delete:card_prefixes replace:cards=11/_11\": \"ajoute des marqueurs d'entités faibles\"\n    },\n    \"aliases\": [\n      \"substitute\",\n      \"sub\",\n      \"repl\"\n    ],\n    \"op_tk\": true\n  },\n  \"slice\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en n'en gardant qu'une tranche donnée\",\n    \"fr_examples\": {\n      \"slice:boxes=5:10\": \"de l'indice 5 (inclus) à l'indice 10 (exclu)\",\n      \"slice:boxes=5:\": \"supprime les 5 premiers caractères\",\n      \"slice:boxes=:5\": \"ne garde que les 5 premiers caractères\",\n      \"slice:boxes=:-5\": \"supprime les 5 derniers caractères\",\n      \"slice:boxes=:\": \"équivalent de `echo`\",\n      \"slice:boxes=\": \"idem\",\n      \"slice:boxes\": \"idem\"\n    },\n    \"aliases\": [\n      \"cut\",\n      \"interval\"\n    ],\n    \"op_tk\": true\n  },\n  \"snake\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en snake_case\",\n    \"aliases\": [\n      \"snakecase\",\n      \"snake_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"split\": {\n    \"category\": \"rw\",\n    \"help\": \"décompose toute association n-aire (*,1) en n-1 associations binaires\",\n    \"fr_examples\": {\n      \"split arrange\": \"décomposer, puis réarranger\"\n    },\n    \"aliases\": []\n  },\n  \"suffix\": {\n    \"category\": \"rw\",\n    \"help\": \"suffixe les éléments donnés avec la chaîne donnée\",\n    \"fr_examples\": {\n      \"suffix:boxes=1\": \"Ajoute un suffixe numérique au nom des boîtes en vue de mettre un MCD et sa copie sur le même diagramme.\"\n    },\n    \"aliases\": [\n      \"append\"\n    ],\n    \"op_tk\": true\n  },\n  \"swapcase\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en inversant la casse de chaque lettre\",\n    \"aliases\": [\n      \"swap_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"title\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule\",\n    \"aliases\": [\n      \"titlecase\",\n      \"title_case\"\n    ],\n    \"op_tk\": true\n  },\n  \"truncate\": {\n    \"category\": \"rw\",\n    \"help\": \"tronque les éléments donnés à la longueur donnée (par défaut : 64)\",\n    \"fr_examples\": {\n      \"truncate:boxes=10\": \"tronque les noms des boîtes à 10 caractères\"\n    },\n    \"aliases\": [\n      \"trunc\",\n      \"shorten\"\n    ],\n    \"op_tk\": true\n  },\n  \"uml\": {\n    \"category\": \"cv\",\n    \"help\": \"convertit le modèle conceptuel en diagramme de classes UML\",\n    \"fr_examples\": {\n      \"uml\": \"format PlantUML\",\n      \"uml:plantuml\": \"idem\",\n      \"uml --defer\": \"calcule le rendu graphique via un service web\",\n      \"uml:plantuml=-\": \"supprime les styles par défaut\",\n      \"uml:plantuml='skinparam backgroundColor yellow\\nskinparam classAttributeFontName Arial\\n'\": \"ajoute des styles personnalisés\"\n    },\n    \"aliases\": [\n      \"uml\",\n      \"class_diagram\"\n    ]\n  },\n  \"share\": {\n    \"category\": \"cv\",\n    \"help\": \"encode le MCD dans une URL pour Mocodo online\",\n    \"fr_examples\": {\n      \"qr --defer\": \"génère un QR code via un service web\"\n    },\n    \"aliases\": [\n      \"url\",\n      \"link\",\n      \"qr\",\n      \"qr_code\"\n    ]\n  },\n  \"upper\": {\n    \"category\": \"rw\",\n    \"help\": \"réécrit les éléments donnés en majuscules\",\n    \"fr_examples\": {\n      \"upper:boxes\": \"noms des boîtes en majuscules\"\n    },\n    \"aliases\": [\n      \"uppercase\",\n      \"upper_case\"\n    ],\n    \"op_tk\": true\n  }\n}\n"
  },
  {
    "path": "mocodo/rewrite/__init__.py",
    "content": ""
  },
  {
    "path": "mocodo/rewrite/_arrange.py",
    "content": "import importlib\nfrom time import time\nfrom mocodo.mocodo_error import subarg_error\n\ndef run(source, subargs, **kargs):\n    algo = subargs.get(\"algo\", \"bb\")\n    try:\n        module = importlib.import_module(f\".rewrite.arrange_{algo}\", package=\"mocodo\")\n    except ModuleNotFoundError:\n        raise subarg_error(\"algo\", algo)\n    timeout = subargs.get(\"timeout\")\n    if timeout is None:\n        has_expired = lambda: False\n    else:\n        try:\n            timeout = time() + float(timeout)\n            has_expired = lambda: time() > timeout\n        except Exception:\n            raise subarg_error(\"timeout\", timeout)\n    return module.arrange(source, subargs, has_expired)\n"
  },
  {
    "path": "mocodo/rewrite/_drain.py",
    "content": "from collections import defaultdict\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..parse_mcd import Token, Visitor\nfrom ..tools.parser_tools import parse_source, reconstruct_source, first_child\n\n\nclass DrainerFirstPass(Visitor):\n    \"\"\"\n    In the first pass, the attributes to drain are suppressed from the tree and\n    stored in a dictionary.\n    \"\"\"\n    def __init__(self):\n        self.drained_attrs = defaultdict(list)\n\n    def assoc_clause(self, tree):\n\n        # Guard: ensure that exactly one cardinality is 11\n        cards = [node.children[0].value for node in tree.find_data(\"card\")]\n        if cards.count(\"11\") != 1:\n            return\n\n        # Guard: ensure that the association has at least one attributes\n        attrs = [*tree.find_data(\"typed_attr\")]\n        if len(attrs) == 0:\n            return\n\n        # Find out the name of the entity that is the target of the 11 leg\n        entity_name_refs = [node.children[0] for node in tree.find_data(\"entity_name_ref\")]\n        i = cards.index(\"11\")\n        entity_name_ref = entity_name_refs[i].children[0].value\n\n        # Store the attributes to drain\n        self.drained_attrs[entity_name_ref].extend(map(reconstruct_source, attrs))\n\n        # Remove the attributes from the association\n        drop = False\n        children = []\n        for child in tree.children:\n            if isinstance(child, Token):\n                if child.type == \"COLON\":\n                    drop = True\n                elif child.type == \"NL\":\n                    drop = False\n            if not drop:\n                children.append(child)\n        tree.children = children\n\n\nclass DrainerSecondPass(Visitor):\n    \"\"\"\n    In the second pass, the drained attributes are reinjected into the appropriate entities.\n    \"\"\"\n    def __init__(self, drained_attrs):\n        self.drained_attrs = drained_attrs\n\n    def entity_clause(self, tree):\n\n        # Guard: ensure that the entity must get drained attributes\n        entity_name_def = first_child(tree, \"entity_name_def\").children[0]\n        if not entity_name_def in self.drained_attrs:\n            return\n\n        # Add the drained attributes to the entity\n        attrs = self.drained_attrs[entity_name_def]\n        last_token = tree.children[-1]\n        last_token.value = f\", {', '.join(attrs)}{last_token.value}\"\n\n\ndef run(source, **kargs):\n    tree = parse_source(source)\n    visitor = DrainerFirstPass()\n    visitor.visit(tree)\n    visitor = DrainerSecondPass(visitor.drained_attrs)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/_drown.py",
    "content": "from ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source, reconstruct_source\n\n\nclass Numbering(Visitor):\n\n    def __init__(self, tree, params):\n\n        self.size = len(str(len(set(node.children[0].value for node in tree.find_data(\"box_name\")))))\n\n        def new_name(base_name, name, i):\n            if name == params[\"df\"]:\n                return name\n            return f\"{base_name} {i:0{self.size}d}_\"\n\n        def update_translations(token_name, base_name, n):\n            nodes = tree.find_data(token_name)\n            names = [node.children[0].children[0].value for node in nodes]\n            self.names.update({name: new_name(base_name, name, i) for (i, name) in enumerate(names, n)})\n            self.numbers.update({new_name(base_name, name, i): f\"{i:0{self.size}d}\"  for (i, name) in enumerate(names, n)})\n        \n        self.names = {}\n        self.numbers = {}\n        update_translations(\"entity_name_def\", _(\"ENTITY\"), 1)\n        update_translations(\"assoc_name_def\", _(\"ASSOC\"), len(self.names) + 1)\n\n        self.attr_base = _(\"attr\")\n        self.leg_note_base = _(\"role\")\n\n    def update_box_attrs(self, tree, token_name):\n        number = self.numbers[first_child(tree, token_name).children[0].value]\n        for (i, attr) in enumerate(tree.find_data(\"attr\"), 1):\n            if attr.children[0] == \"\":\n                continue # do nothing for a spacer attribute\n            attr.children[0].value = f\"{self.attr_base} {number} {i}\"\n    \n    def box_name(self, tree):\n        token = tree.children[0]\n        token.value = self.names[token.value]\n\n    def entity_clause(self, tree):\n        self.update_box_attrs(tree, \"entity_name_def\")\n    \n    def assoc_clause(self, tree):\n        self.update_box_attrs(tree, \"assoc_name_def\")\n        for (i, attr) in enumerate(tree.find_data(\"leg_note\"), 1):\n            attr.children[0].value = f\"{self.leg_note_base} {i}\"\n\n\ndef run(source, params, **kargs):\n    tree = parse_source(source)\n    visitor = Numbering(tree, params)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/_explode.py",
    "content": "__import__(\"sys\").path[0:0] = [\".\"]\n\nimport contextlib\nfrom ..parse_mcd import Token, Visitor\nfrom ..tools.parser_tools import parse_source, reconstruct_source, first_child\n\nclass Exploder(Visitor):\n\n    def __init__(self, subargs, params):\n        arity = 3\n        with contextlib.suppress(ValueError, KeyError):\n            arity = float(subargs[\"arity\"])\n        self.empty_only = (arity == 2.5)\n        self.threshold = int(arity)\n        self.allow_weak = \"weak\" in subargs\n        if self.allow_weak:\n            # Don't create an identifier for the new weak entity\n            self.explosion_template = \":\"\n            # Prefix the potential first attribute with an underscore\n            self.explosion_prefix = \" _\"\n            # Strenghten the new legs\n            self.explosion_card = \"_11\"\n        else:\n            # Create a strong identifier for the new entity\n            self.explosion_template = \": id. {}\"\n            # Separate the potential first attribute with a comma\n            self.explosion_prefix = \", \"\n            # Don't strengthen the new legs\n            self.explosion_card = \"11\"\n        self.df_label = params[\"df\"]\n\n    def line(self, tree):\n        # It is not possible to use a method `assoc_clause` since the amount of indentation needs\n        # to be known for the added clauses.\n\n        # Guard: store the indentation and abort if the clause is not an association.\n        indent = next(tree.find_data(\"indent\"), None)\n        indent = indent.children[0].value if indent else \"\"\n        tree = next(tree.find_data(\"assoc_clause\"), None)\n        if tree is None:\n            return\n\n        # Guard: ensure that there are enough legs and all their max cards are N.\n        cards = [node.children[0].value for node in tree.find_data(\"card\")]\n        if len(cards) < self.threshold or any(card[1] != \"N\" for card in cards):\n            return\n        \n        # Guard: on demand, avoid processing binary associations with no attributes.\n        if self.empty_only and not first_child(tree, \"typed_attr\"):\n            return\n\n        # Guard: don't explode a clustered association if weak is not allowed\n        card_prefixes = [node.children[0].value == \"/\" for node in tree.find_data(\"card_prefix\")]\n        if any(card_prefixes) and not self.allow_weak:\n            return\n        \n        # Guard: don't explode an association of several clusters\n        if sum(card_prefixes) > 1:\n            return\n        \n        # Back the legs up as a list of strings.\n        legs = list(map(reconstruct_source, tree.find_data(\"assoc_leg\")))\n\n        # Convert the original association into an entity.\n        assoc_name = first_child(tree, \"assoc_name_def\").children[0]\n        state = \"Waiting for first comma\"\n        children = []\n        for child in tree.children:\n            if isinstance(child, Token):\n                if child.type == \"COMMA\" and state == \"Waiting for first comma\":\n                    child.value = self.explosion_template.format(assoc_name.lower())\n                    children.append(child)\n                    state = \"Scanning legs\"\n                    continue\n                if child.type == \"COLON\": # There were at least one attribute\n                    state = \"Scanning attributes\"\n                    child.value = self.explosion_prefix\n                if child.type == \"NL\": # useful where there are no attributes\n                    state = \"EOL\"\n            if state != \"Scanning legs\":\n                children.append(child)\n        tree.children = children\n\n        # Construct the clauses of the new associations\n        clauses = []\n        prefix = first_child(tree, \"box_def_prefix\")\n        for leg in legs:\n            card = self.explosion_card\n            # TODO: check this logic\n            if leg.startswith(\"/\"): # when there is a cluster\n                leg = leg[1:] # suppress it\n                card = \"11\" # and switch to a non-strenghtening leg\n            clauses.append(f\"{indent}{prefix}{self.df_label}, {card} {assoc_name}, {leg}\")\n\n        # Suffix the resulting string to the last node (a \"NL\" token\")\n        tree.children[-1].value += \"\\n\".join(clauses) + \"\\n\"\n\n\ndef run(source, subargs=None, params=None, **kargs):\n    subargs = subargs or {}\n    params = params or {\"df\": \"DF\"}\n    tree = parse_source(source)\n    visitor = Exploder(subargs, params)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/_grow.py",
    "content": "import contextlib\nimport random\nimport re\n\nfrom ..tools.parser_tools import parse_source\nfrom ..mocodo_error import MocodoError\n\n\ndef random_booleans(n, p):\n    p = min(n, p)\n    result = [True] * p + [False] * (n - p)\n    random.shuffle(result)\n    return result\n\ndef calculate_cards(scheme, refs):\n    if len(refs) > len(set(refs)): # If the association is reflexive\n        # Process the cases of n-ary associations with n > 2\n        # (the other ones have already been filtered out by the caller)\n        scheme = scheme.replace(\"_\", \"\") # silently forbid weak associations\n        scheme = scheme.replace(\"/\", \"\") # silently forbid cluster associations\n    (head, tail) = scheme.split(\"-\")\n    cards = [head] + [tail] * (len(refs) - 1)\n    cards = [card.replace(\"*\", random.choice(\"01\")) for card in cards]\n    random.shuffle(cards)\n    return cards\n\ndef extract_weak_entities(cards, refs):\n    for (card, ref) in zip(cards, refs):\n        if \"_\" in card:\n            yield ref\n\ndef biased_choice(elements):\n    # Return a random element from a list, with a bias towards the last elements.\n    i = max(random.randrange(0, len(elements)) for _ in range(3))\n    return elements[i]\n\ndef biased_sample(elements, k):\n    # Return a random sample of k elements from a list, with a bias towards the last elements.\n    max_sample = [-1] # incorrect sample, but it will be replaced on the first iteration\n    for _ in range(3):\n        sample = random.sample(range(len(elements)), k)\n        if min(sample) > min(max_sample):\n            max_sample = sample\n    return [elements[i] for i in max_sample]\n\ndef run(source, subargs=None, params=None, **kargs):\n    match_card_scheme = re.compile(r\"^[/_]?[01*][1N]-[/_]?[01*][1N]$\").match\n    subargs = subargs or {}\n    default = {\n            \"n\": 10,\n            \"arity_1\": 2,\n            \"arity_3\": 2,\n            \"arity_4\": 0,\n            \"ent_attrs\": 4,\n            \"doubles\": 1,\n            \"composite_ids\": 1,\n            \"assoc_attrs\": 2,\n            \"*1-*N\": 3,\n            \"01-11\": 1,\n            \"from_scratch\": False,\n        }\n    # Complete the given subargs with default values\n    settings = {}\n    for (k, v) in default.items():\n        if k in subargs:\n            cast = type(v) # cast to the same type as the default value\n            with contextlib.suppress(TypeError):\n                settings[k] = cast(subargs[k])\n                continue\n            # If the cast fails, silently fall back to the default value\n        settings[k] = v\n    \n    # Complete the settings with the remaining card schemes\n    for (k, v) in subargs.items():\n        if match_card_scheme(k):\n            with contextlib.suppress(TypeError):\n                settings[k] = int(v)\n    \n    # Silently correct incompatible numbers\n    n = settings[\"n\"]\n    for (k, v) in list(settings.items()):\n        if k in (\"n\", \"assoc_attrs\"):\n            continue\n        elif k == \"ent_attrs\":\n            settings[k] = max(v, 1)\n        elif k in (\"doubles\", \"arity_1\", \"arity_3\", \"arity_4\"):\n            settings[k] = min(v, n - 1)\n\n    association_bases = [None, _(\"Reflexive\"), _(\"Binary\"), _(\"Ternary\"), _(\"Quaternary\")]\n    entity_base = _(\"Entity\")\n    weak_entity_base = _(\"Weak Entity\")\n    attr_base = _(\"attr\")\n    id_base = _(\"id\")\n\n    card_schemes = []\n    for (k, v) in settings.items():\n        if match_card_scheme(k):\n            card_schemes.extend([k] * v)\n    card_schemes.extend([\"*N-*N\"] * (n - len(card_schemes)))\n\n    # Try to find a combination of card schemes and arities that is compatible\n    arities = [1] * settings[\"arity_1\"] + [3] * settings[\"arity_3\"] + [4] * settings[\"arity_4\"] + [2] * n\n    arities = arities[:n]\n    max_tries = 100\n    while max_tries > 0:\n        random.shuffle(arities)\n        # Slightly push the non binary arities towards the end (one iteration of bubble sort).\n        # Reason: the non binary arities are tougher to place when there are not many entities yet\n        for i in range(len(arities) - 1):\n            if arities[i] != 2 and arities[i + 1] == 2:\n                (arities[i], arities[i + 1]) = (arities[i + 1], arities[i])\n        random.shuffle(card_schemes) # avoid being stuck with a card scheme incompatible with a small arity\n        max_tries -= 1\n        for (scheme, arity) in zip(card_schemes, arities):\n            if \"_\" in scheme and arity == 1:\n                break # A reflexive association cannot be weak\n            if \"/\" in scheme and arity < 3:\n                break # A cluster association is better with at least 3 entities\n            if \"11\" in scheme and (arity > 2 or \"/\" in scheme):\n                break # A DF is better with at most 2 entities or a cluster\n        else:\n            # All associations are compatible with their card schemes\n            break\n    else:\n        raise MocodoError(28, _(\"Cannot find a suitable combination of card schemes and arities.\"))  # fmt: skip\n\n    for key in (\"assoc_attrs\", \"composite_ids\"):\n        settings[key] = random_booleans(n, settings[key])\n    \n    ent_attr_names = []\n    for is_composite in settings[\"composite_ids\"]:\n        if is_composite:\n            ent_attr_names.append([f\"{id_base}\", f\"_{id_base}\"] + [f\"{attr_base}\"] * random.randint(0, settings[\"ent_attrs\"] - 2))\n        else:\n            ent_attr_names.append([f\"{id_base}\"] + [f\"{attr_base}\"] * random.randint(0, settings[\"ent_attrs\"] - 1))\n    \n    if \"from_scratch\" in subargs:\n        source = f\"ENTITY_NAME_PLACEHOLDER 1_: {id_base} 1 1, {attr_base} 1 2, {attr_base} 1 3\\n\"\n\n    tree = parse_source(source)\n    entities = [node.children[0].children[0].value for node in tree.find_data(\"entity_name_def\")]\n    associations = [node.children[0].children[0].value for node in tree.find_data(\"assoc_name_def\")]\n    counter = len(entities) + len(associations) + 1\n\n    clauses = [source]\n    ref_pool = []\n    weak_entities = set()\n    for i in range(settings[\"n\"] - settings[\"doubles\"]):\n\n        if arities[i] == 1:\n            # to keep the MCD connected, don't create a new entity if the association is reflexive\n            old_entity = biased_choice(entities)\n            refs = [old_entity, old_entity]\n        else:\n            # Normal case: create a new entity\n            new_entity = f\"ENTITY_NAME_PLACEHOLDER {counter}_\"\n            new_ent_attrs = [f\"{ent_attr_name} {counter} {j}\" for (j, ent_attr_name) in enumerate(ent_attr_names[i], 1)]\n            clauses.append(f\"{new_entity}: {', '.join(new_ent_attrs)}\")\n            try: # Prefer all distinct entities\n                old_refs = biased_sample(entities, arities[i] - 1)\n            except ValueError: # If there are not enough entities, allow reflexive associations\n                old_refs = [biased_choice(entities) for _ in range(arities[i] - 1)]\n            refs = [new_entity] + old_refs\n            entities.append(new_entity)\n            counter += 1\n        \n        new_association = f\"{association_bases[arities[i]]} {counter}_\"\n        ref_pool.append(refs)\n        cards = calculate_cards(card_schemes[i], refs)\n        clauses.append(\", \".join([new_association] + [f\"{card} {ref}\" for (card, ref) in zip(cards, refs)]))\n        weak_entities.update(extract_weak_entities(cards, refs))\n        new_assoc_attrs = [f\"{attr_base} {counter} {j}\" for j in range(1, settings[\"assoc_attrs\"][i] + 1)]\n        if new_assoc_attrs:\n            clauses[-1] += f\": {', '.join(new_assoc_attrs)}\"\n        associations.append(new_association)\n        counter += 1\n    for i in range(settings[\"n\"] - settings[\"doubles\"], settings[\"n\"]):\n        refs = biased_choice(ref_pool)\n        arity = len(set(refs))\n        new_association = f\"{association_bases[arity]} {counter}_\"\n        cards = calculate_cards(card_schemes[i], refs)\n        clauses.append(\", \".join([new_association] + [f\"{card} {ref}\" for (card, ref) in zip(cards, refs)]))\n        weak_entities.update(extract_weak_entities(cards, refs))\n        new_assoc_attrs = [f\"{attr_base} {counter} {j}\" for j in range(1, settings[\"assoc_attrs\"][i] + 1)]\n        if new_assoc_attrs:\n            clauses[-1] += f\": {', '.join(new_assoc_attrs)}\"\n        associations.append(new_association)\n        counter += 1\n    \n    text = \"\\n\".join(clauses)\n\n    j = len(\"ENTITY_NAME_PLACEHOLDER\")\n    for e in weak_entities:\n        text = re.sub(fr\"\\b{e}\\b\", lambda m: f\"{weak_entity_base}{m.group(0)[j:]}\", text)\n    text = text.replace(\"ENTITY_NAME_PLACEHOLDER\", entity_base)\n    \n    return text\n"
  },
  {
    "path": "mocodo/rewrite/_split.py",
    "content": "from collections import Counter\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..parse_mcd import Token, Visitor\nfrom ..tools.parser_tools import parse_source, reconstruct_source, first_child\n\nclass Splitter(Visitor):\n\n    def line(self, tree):\n        # It is not possible to use a method `assoc_clause` since the amount of indentation needs\n        # to be known for the added clauses.\n\n        # Guard: store the indentation and abort if the clause is not an association.\n        indent = next(tree.find_data(\"indent\"), None)\n        indent = indent.children[0].value if indent else \"\"\n        tree = next(tree.find_data(\"assoc_clause\"), None)\n        if tree is None:\n            return\n\n        # Guard: abort if the association has less than 3 legs.\n        legs = [node for node in tree.find_data(\"assoc_leg\")]\n        if len(legs) < 3:\n            return\n\n        # Reorder the legs with \"11\" cards first, then \"01\", then the other ones.\n        d = {\"11\": 0, \"01\": 1}\n        legs.sort(key=lambda leg: d.get(first_child(leg, \"card\").value, 2))\n\n        # Guard: ensure that the first max cardinality is 1.\n        if first_child(legs[0], \"card\")[1] != \"1\":\n            return\n        \n        # Guard: don't split a clustered association\n        card_prefixes = [first_child(leg, \"card_prefix\") == \"/\" for leg in legs]\n        if any(card_prefixes):\n            return\n        \n        # Accumulate the constituting elements (cf. grammar.lark) of the original legs.\n        new_items = []\n        for leg in legs:\n            acc = []\n            acc.append(first_child(leg, \"card_hidden\"))\n            acc.append(first_child(leg, \"card_prefix\"))\n            acc.append(first_child(leg, \"card\"))\n            acc.append(first_child(leg, \"leg_arrow\"))\n            acc.append(first_child(leg, \"leg_note\"))\n            acc[-1] = f\" [{acc[-1]}] \" if acc[-1] else \" \"\n            acc.append(first_child(leg, \"entity_name_ref\").children[0])\n            new_items.append(\"\".join(acc))\n        \n        # Concatenate any attributes of the association.\n        attrs = []\n        for child in tree.find_data(\"typed_attr\"):\n            acc = []\n            acc.append(first_child(child, \"attr\"))\n            datatype  = first_child(child, \"datatype\")\n            if datatype:\n                acc.append(f\" [{datatype}]\")\n            attrs.append(\"\".join(acc))\n        \n        # Construct the lines of the exploded association. The *1 leg is the first one.\n        result = []\n        box_def_prefix = first_child(tree, \"box_def_prefix\")\n        assoc_name_def = first_child(tree, \"assoc_name_def\").children[0]\n        for (i, new_item) in enumerate(new_items[1:]):\n            result.append(f\"{indent}{box_def_prefix}{assoc_name_def}{i}, {new_items[0]}, {new_item}\")\n\n        # Add the attributes to the first clause only. Duplicating them would be an error.\n        result[0] += f\": {', '.join(attrs)}\" if attrs else \"\"\n\n        # The first clause starts at the same position as the association name: unindent.\n        result[0] = result[0].lstrip()\n\n        # Add a blank line after the exploded association.\n        result.append(\"\")\n\n        # Replace the original tree by a pseudo-tree containing only the desired string.\n        token = first_child(tree, \"box_name\")\n        tree.children = [Token(\"MOCK\", \"\\n\".join(result), line=token.line, column=token.column)]\n\ndef run(source, **kargs):\n    tree = parse_source(source)\n    visitor = Splitter()\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/arrange_bb.py",
    "content": "import contextlib\nfrom functools import lru_cache\nfrom itertools import count, product\nfrom math import hypot\nfrom random import choice, random, shuffle\n\nfrom .cross import cross\nfrom ..mocodo_error import MocodoError\nfrom ..argument_parser import non_negative_integer, positive_integer\nfrom ..mcd import Mcd\n\ndef arrange(source, subargs, has_expired):\n\n    is_organic = False\n    if \"wide\" in subargs:\n        col_count = 8\n        with contextlib.suppress(Exception):\n            col_count = int(subargs[\"wide\"]) or 1\n        mcd = Mcd(source)\n        (q, r) = divmod(mcd.get_non_phantom_count(), col_count)\n        row_count = q + bool(r)\n        source = mcd.get_refitted_clauses(col_count, row_count)\n    elif \"balanced\" in subargs:\n        nth_fit = 0\n        with contextlib.suppress(Exception):\n            nth_fit = int(subargs[\"balanced\"])\n        mcd = Mcd(source)\n        source = mcd.get_refitted_clauses(nth_fit)\n    elif \"current\" in subargs:\n        pass\n    else:\n        is_organic = True\n    \n    mcd = Mcd(source)\n    layout_data = mcd.get_layout_data()\n    successors = layout_data[\"successors\"]\n    col_count = layout_data[\"col_count\"]\n    row_count = layout_data[\"row_count\"]\n    multiplicity = layout_data[\"multiplicity\"]\n\n    min_objective = non_negative_integer(subargs.get(\"min_objective\", 0))\n    max_objective = non_negative_integer(subargs.get(\"max_objective\", 15))\n    call_limit = positive_integer(subargs.get(\"call_limit\", 10000))\n    verbose = bool(subargs.get(\"verbose\") is not None) # -t arrange:verbose => {\"verbose\": \"\"} => True\n\n    has_expired = has_expired or (lambda: False)\n\n    @lru_cache\n    def bounded_neighborhood(x1, y1):\n        result = set()\n        for x2 in range(\n            max(0, x1 - radius),\n            min(col_count, x1 + radius + 1),\n        ):\n            for y2 in range(\n                max(0, y1 - radius + abs(x1 - x2)),\n                min(row_count, y1 + radius - abs(x1 - x2) + 1),\n            ):\n                if x1 != x2 or y1 != y2:\n                    result.add((x2, y2))\n        return result\n\n    @lru_cache\n    def organic_neighborhood(x1, y1):\n        result = set()\n        for x2 in range(x1 - radius, x1 + radius + 1):\n            for y2 in range(y1 - radius + abs(x1 - x2), y1 + radius - abs(x1 - x2) + 1):\n                if x1 != x2 or y1 != y2:\n                    result.add((x2, y2))\n        return result\n\n    @lru_cache\n    def bounded_hull(coords):\n        result = set()\n        for (x, y) in coords:\n            if x - 1 >= 0:\n                result.add((x - 1, y))\n            if x + 1 < col_count:\n                result.add((x + 1, y))\n            if y - 1 >= 0:\n                result.add((x, y - 1))\n            if y + 1 < row_count:\n                result.add((x, y + 1))\n        return result.difference(coords)\n\n    @lru_cache\n    def organic_hull(coords):\n        result = set()\n        for (x, y) in coords:\n            result.add((x - 1, y))\n            result.add((x + 1, y))\n            result.add((x, y - 1))\n            result.add((x, y + 1))\n        return result.difference(coords)\n\n    def recurs(box_coords, next_boxes, placed_segments, cumulated_distances):\n        if cumulated_distances > objective:\n            # print(\"cut\")\n            return None\n        if len(next_boxes) == 0:\n            return {\n                \"coords\": box_coords,\n                \"crossings\": 0,\n                \"distances\": cumulated_distances,\n            }\n        outside_hull_count = len(next_boxes) - len(hull(frozenset(box_coords.values())))\n        if outside_hull_count * outside_hull_minimal_distance + cumulated_distances > objective:\n            # print(\"Lower bound cut\")\n            return None\n        if has_expired():\n            raise MocodoError(10, _('Layout calculation time exceeded.'))  # fmt: skip\n        if next(iteration) > call_limit:\n            # print(\"call limit exceeded\")\n            return None\n        box_to_place = next_boxes[0]\n        placed_successors = {\n            box_coords[box]: box for box in successors[box_to_place] if box in box_coords\n        }\n        if placed_successors:\n            placed_successor_coords = iter(placed_successors)\n            (x1, y1) = next(placed_successor_coords)\n            possible_coords = neighborhood(x1, y1).copy()\n            # print(placed_successors[0], possible_coords)\n            for (x1, y1) in placed_successor_coords:\n                possible_coords.intersection_update(neighborhood(x1, y1))\n                if not possible_coords:\n                    # print(\"neighborhood intersection is empty\")\n                    return None\n        else:\n            # print(\"the box to place has no successors: all empty coords are possible\")\n            possible_coords = set(product(range(col_count), range(row_count)))\n        possible_coords.difference_update(box_coords.values())\n        if not possible_coords:\n            # print(\"neighborhood intersection is not free\")\n            return None\n        non_crossing_possible_coords = []\n        for (x1, y1) in possible_coords:\n            for ((x2, y2), (x3, y3, x4, y4)) in product(placed_successors, placed_segments):\n                if cross(x1, y1, x2, y2, x3, y3, x4, y4):\n                    break\n            else:\n                non_crossing_possible_coords.append((x1, y1))\n        if not non_crossing_possible_coords:\n            # print(\"all possible coords result in a crossing with existing segment\")\n            return None\n        weighted_possible_coords = []\n        for (x1, y1) in non_crossing_possible_coords:\n            cumulated_distance = 0\n            for ((x2, y2), placed_box) in placed_successors.items():\n                cumulated_distance += (\n                    distances[abs(x1 - x2)][abs(y1 - y2)] * multiplicity[(box_to_place, placed_box)]\n                )\n            weighted_possible_coords.append((cumulated_distance, random(), x1, y1))\n        weighted_possible_coords.sort()\n        for (cumulated_distance, __, x1, y1) in weighted_possible_coords:  # For the double underscore, see __main__.py\n            box_coords[box_to_place] = (x1, y1)\n            new_segments = [(x1, y1, x2, y2) for (x2, y2) in placed_successors]\n            new_next_boxes = list(\n                successors[box_to_place].difference(box_coords).difference(next_boxes)\n            )\n            if len(next_boxes) == 1 and len(new_next_boxes) == 0 and len(box_coords) != box_count:\n                # print(\"the placed boxes have no more non placed successors\")\n                new_next_boxes = list(set(range(box_count)).difference(box_coords))\n                if new_next_boxes:\n                    new_next_boxes = [choice(new_next_boxes)]\n            shuffle(new_next_boxes)\n            result = recurs(\n                box_coords,\n                next_boxes[1:] + new_next_boxes,\n                placed_segments + new_segments,\n                cumulated_distances + cumulated_distance,\n            )\n            if result:\n                return result\n            del box_coords[box_to_place]\n\n    box_count = col_count * row_count\n    neighborhood = organic_neighborhood if is_organic else bounded_neighborhood\n    hull = organic_hull if is_organic else bounded_hull\n    radius = 3\n    distances = [[hypot(i, j) - 1 for j in range(radius + 1)] for i in range(radius + 1)]\n    outside_hull_minimal_distance = distances[1][2]\n    if all(not successor for successor in successors):\n        # print(\"no link: return a random layout\")\n        layout = list(range(box_count))\n        shuffle(layout)\n        result = {\n            \"layout\": layout,\n            \"crossings\": 0,\n            \"distances\": 0,\n        }\n        mcd.set_layout(**result)\n        return mcd.get_clauses()\n    for objective in range(min_objective, max_objective + 1):\n        if verbose:\n            print(\"Objective %s.\" % objective)\n        boxes = list(range(box_count))\n        shuffle(boxes)\n        for first_box in boxes:\n            iteration = count()\n            if successors[first_box]:\n                if verbose:\n                    print(\"  Starting from box %s.\" % first_box)\n                result = recurs({first_box: (0, 0)}, list(successors[first_box]), [], 0)\n                if result:\n                    coords = result[\"coords\"]\n                    if is_organic:\n                        min_x = min(x for (x, y) in coords.values())\n                        max_x = max(x for (x, y) in coords.values())\n                        min_y = min(y for (x, y) in coords.values())\n                        max_y = max(y for (x, y) in coords.values())\n                        for (box_index, (x, y)) in coords.items():\n                            coords[box_index] = (x - min_x, y - min_y)\n                        result[\"row_count\"] = row_count = max_y - min_y + 1\n                        result[\"col_count\"] = col_count = max_x - min_x + 1\n                    result[\"layout\"] = [None] * row_count * col_count\n                    for (box_index, (x, y)) in coords.items():\n                        result[\"layout\"][x + y * col_count] = box_index\n                    mcd.set_layout(**result)\n                    if mcd.row_count > mcd.col_count:\n                        # If the layout is taller than wide, transpose it.\n                        return mcd.get_diagonally_flipped_clauses()\n                    else:\n                        return mcd.get_clauses()\n                if is_organic:\n                    break\n        objective += 1\n    if is_organic:\n        raise MocodoError(41, _('Failed to calculate a non-constrained planar layout.'))  # fmt: skip\n    else:\n        raise MocodoError(9, _('Failed to calculate a planar layout satisfying the given constraint.'))  # fmt: skip\n\n\nif __name__ == \"__main__\":\n    # python -m mocodo.rewrite._arrange_bb\n\n    from time import time\n    import random\n    from ..argument_parser import parsed_arguments\n    from ..mcd import Mcd\n\n    clauses = \"\"\"\n        SUSPENDISSE: diam\n        SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n        CONSECTETUER: elit, sed\n        MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n        DF, 11 LOREM, 1N SUSPENDISSE\n        LOREM: ipsum, dolor, sit\n        TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n        DIGNISSIM: ligula, massa, varius\n\n        DF, 11 RISUS, 0N RISUS\n        AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n        RISUS: ultricies, _cras, elementum\n        SEMPER, 0N RISUS, 1N DIGNISSIM\n    \"\"\"\n    params = parsed_arguments()\n    mcd = Mcd(clauses.replace(\"  \", \"\"), **params)\n    starting_time = time()\n    random.seed(42)\n    rearrangement = arrange(mcd, {\"is_organic\": True}, lambda: False)\n    if rearrangement:\n        print()\n        mcd.set_layout(**rearrangement)\n        print(mcd.get_clauses())\n        print()\n        print(\"Cumulated distances:\", rearrangement[\"distances\"])\n        print(\"Duration:\", time() - starting_time)\n        print()\n"
  },
  {
    "path": "mocodo/rewrite/arrange_ga.py",
    "content": "from collections import namedtuple\nfrom random import choice, random, randrange, sample\n\nfrom .fitness import fitness\nfrom ..argument_parser import rate, positive_integer\nfrom ..mcd import Mcd\n\ndef arrange(source, subargs, has_expired):\n    \n    mcd = Mcd(source)\n    layout_data = mcd.get_layout_data()\n    links = layout_data[\"links\"]\n    successors = layout_data[\"successors\"]\n    col_count = layout_data[\"col_count\"]\n    row_count = layout_data[\"row_count\"]\n    multiplicity = layout_data[\"multiplicity\"]\n\n    verbose = subargs.get(\"verbose\", False)\n    population_size = positive_integer(subargs.get(\"population_size\", 1000)) # number of individuals to evolve\n    max_generations = positive_integer(subargs.get(\"max_generations\", 300))\n    plateau = positive_integer(subargs.get(\"plateau\", 30)) # maximal number of consecutive generations without improvement\n    crossover_rate = rate(subargs.get(\"crossover_rate\", 0.9))\n    mutation_rate = rate(subargs.get(\"mutation_rate\", 0.06))\n    sample_size = positive_integer(subargs.get(\"sample_size\", 7))\n    verbose = bool(subargs.get(\"verbose\") is not None) # -r arrange:verbose => {\"verbose\": \"\"} => True\n\n    def make_individual():\n        \"\"\" Construct a chromosome. Select a random node for the first gene. The next ones are chosen\n            sequentially. When a gene has another gene to the west, the corresponding node is preferably\n            selected among the successors of the latter. NB: Applying the same technic for the north and\n            nortwest directions produces better individual, but worse final results. \"\"\"\n        pool = list(range(box_count))\n        chromosome = [pool.pop(randrange(box_count))]\n        (x, y) = (0, 0)\n        for i in range(1, box_count):\n            x += 1\n            if x == col_count:\n                x = 0\n                y += 1\n                candidates = set()\n            else:\n                candidates = successors[chromosome[i-1]].intersection(pool)\n            chromosome.append(pool.pop(pool.index(choice(tuple(candidates))) if candidates else randrange(len(pool))))\n        return Individual(evaluate(chromosome), chromosome)\n\n    def crossover(chromosome_1, chromosome_2):\n        \"\"\" Produce two children for a given pair of individuals. A random rectangular zone is first selected.\n            The corresponding genes in the first individual are copied in the first child. The remaining places\n            are filled with the genes of the second individual taken one by one. Symmetrical operations for the\n            second child. \"\"\"\n        (x1, y1) = (randrange(col_count), randrange(row_count))\n        (x2, y2) = (randrange(x1+1, col_count+1), randrange(y1+1, row_count+1))\n        def mate(chromosome_1, chromosome_2):\n            used = set(chromosome_1[x+y*col_count] for x in range(x1, x2) for y in range(y1, y2))\n            not_used = (allele for allele in chromosome_2 if allele not in used)\n            return [chromosome_1[x+y*col_count] if x1 <= x < x2 and y1 <= y < y2 else next(not_used) for y in range(row_count) for x in range(col_count)]\n        return (mate(chromosome_1, chromosome_2), mate(chromosome_2, chromosome_1))\n\n    def next_population():\n        \"\"\" Evolve the population. The best individual is kept. The others are selected by tournament.\n            Some selected pairs produce two children. Each selected individual may mutate at certain\n            places. Mutation of a gene simply consists in swapping it with another one. \"\"\"\n        result = [best]\n        while len(result) < population_size:\n            chromosomes = crossover(tournament(), tournament()) if random() < crossover_rate else [tournament()]\n            for chromosome in chromosomes:\n                for i in range(box_count):\n                    if random() < mutation_rate:\n                        j = randrange(box_count)\n                        (chromosome[i], chromosome[j]) = (chromosome[j], chromosome[i])\n                result.append(Individual(evaluate(chromosome), chromosome))\n        return result[:population_size]\n\n    def tournament():\n        \"\"\" Return a COPY of the best chromosome selected among a random sample. \"\"\"\n        return min(sample(population, sample_size)).chromosome[:]\n    \n    evaluate = fitness(links, multiplicity, col_count, row_count)\n    Individual = namedtuple(\"Individual\", [\"score\", \"chromosome\"])\n    box_count = col_count * row_count\n    patience = plateau\n    previous_best_score = None\n    population = sorted([make_individual() for _ in range(population_size)])\n    best = population[0]\n    for generation in range(max_generations):\n        if best.score == previous_best_score:\n            patience -= 1\n        else:\n            if verbose:\n                print(\"% 3d: %s\" % (generation, best.score))\n            previous_best_score = best.score\n            patience = plateau\n        if best.score == (0, 0) or patience == 0 or has_expired():\n            # Even if the best individual is not perfect, we stop here\n            # without raising an exception.\n            break\n        population = sorted(next_population())\n        best = population[0]\n        generation += 1\n    result = {\n        \"distances\": best.score[1],\n        \"crossings\": best.score[0],\n        \"layout\": best.chromosome\n    }\n    mcd.set_layout(**result)\n    return mcd.get_clauses()\n    \nif __name__ == \"__main__\":\n    # python -m mocodo.rewrite._arrange_ga\n\n    from time import time\n    import random\n    from ..argument_parser import parsed_arguments\n    from ..mcd import Mcd\n\n    clauses = \"\"\"\n        SUSPENDISSE: diam\n        SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n        CONSECTETUER: elit, sed\n        MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n        DF, 11 LOREM, 1N SUSPENDISSE\n        LOREM: ipsum, dolor, sit\n        TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n        DIGNISSIM: ligula, massa, varius\n\n        DF, 11 RISUS, 0N RISUS\n        AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n        RISUS: ultricies, _cras, elementum\n        SEMPER, 0N RISUS, 1N DIGNISSIM\n    \"\"\"\n    params = parsed_arguments()\n    mcd = Mcd(clauses.replace(\"  \", \"\"), **params)\n    starting_time = time()\n    random.seed(42)\n    rearrangement = arrange(mcd, {}, lambda: False)\n    if rearrangement:\n        print()\n        mcd.set_layout(**rearrangement)\n        print(mcd.get_clauses())\n        print()\n        print(\"Cumulated distances:\", rearrangement[\"distances\"])\n        print(\"Duration:\", time() - starting_time)\n        print()\n"
  },
  {
    "path": "mocodo/rewrite/arrows.py",
    "content": "from ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source, reconstruct_source\n\nclass ArrowsHere(Visitor):\n\n    def assoc_leg(self, tree):\n        card = first_child(tree, \"card\")\n        if card != \"11\":\n            return\n        if first_child(tree, \"leg_arrow\") != \"\":\n            return\n        card.value += \"<\"\n    \nclass ArrowsAcross(Visitor):\n\n    def assoc_clause(self, tree):\n        legs = [node for node in tree.find_data(\"assoc_leg\")]\n        cards = [first_child(leg, \"card\") for leg in legs]\n        for (i, card) in enumerate(cards):\n            if card == \"11\":\n                for (j, other_leg) in enumerate(legs):\n                    if i != j and first_child(other_leg, \"leg_arrow\") == \"\":\n                        other_card = first_child(other_leg, \"card\")\n                        other_card.value += \">\"\n\n\ndef create_df_arrows(source, where):\n    visitor = ArrowsHere() if where == \"here\" else ArrowsAcross()\n    tree = parse_source(source)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/cards.py",
    "content": "from ..parse_mcd import Visitor\nfrom ..tools.parser_tools import parse_source, reconstruct_source, first_child\nfrom ..tools.various import invert_dict\n\n\ndef fix_card(\n    card,\n    fixes=invert_dict(\n        {\n            \"01\": [\"O1\", \"o1\", \"10\", \"1O\", \"1o\", \"Ol\", \"ol\", \"l0\", \"lO\", \"lo\"],\n            \"0N\": [\"ON\", \"oN\", \"NO\", \"No\", \"N0\"],\n            \"0n\": [\"On\", \"on\", \"no\", \"nO\", \"n0\"],\n            \"1N\": [\"N1\", \"Nl\"],\n            \"1n\": [\"n1\", \"nl\"],\n        }\n    ),\n):\n    return fixes.get(card, card)\n\nclass DfInference(Visitor):\n\n    def __init__(self, df_label):\n        self.df_label = df_label\n\n    def assoc_clause(self, tree):\n        assoc_name = first_child(tree, \"assoc_name_def\").children[0]\n        if assoc_name == self.df_label:\n            return\n        cards = []\n        legs = list(tree.find_data(\"assoc_leg\"))\n        for leg in legs:\n            card_prefix = first_child(leg, \"card_prefix\")\n            if card_prefix == \"/\":\n                return\n            card = first_child(leg, \"card\")\n            cards.append(card)\n        if \"11\" in cards:\n            assoc_name.value = self.df_label\n\ndef infer_dfs(source, df_label):\n    tree = parse_source(source)\n    visitor = DfInference(df_label)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n\nclass RoleInference(Visitor):\n\n    def assoc_clause(self, tree):\n        assoc_name = first_child(tree, \"assoc_name_def\").children[0]\n        legs = list(tree.find_data(\"assoc_leg\"))\n        cards = [first_child(leg, \"card\") for leg in legs]\n        roles = [first_child(leg, \"leg_note\") for leg in legs]\n        if \"01\" in cards or \"11\" in cards:\n            for (card, role) in zip(cards, roles):\n                if role:\n                    continue\n                if card[1] != \"1\": # *1 vs *N\n                    card.value += f\" [{assoc_name}]\"\n                elif card == \"01\" and \"11\" in cards: # 01 vs 11\n                    card.value += f\" [{assoc_name}]\"\n                elif card == \"11\" and cards.count(\"11\") > 1: # 11 vs 11\n                    card.value += f\" [{assoc_name}]\"\n\ndef infer_roles(source):\n    tree = parse_source(source)\n    visitor = RoleInference()\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/rewrite/constraints.py",
    "content": "import re\nfrom ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source\nfrom ..tools.string_tools import surrounds\nfrom ..tools.various import first_missing_positive\n    \nclass CreateCifs(Visitor):\n\n    def __init__(self):\n        self.candidates = set()\n        self.existing = set()\n        self.invisible_numbers = []\n\n    def entity_clause(self, tree):\n        ent_name = str(first_child(tree, \"box_name\"))\n        m = re.match(r\"(?i)invisible(\\d+)$\", ent_name)\n        if m:\n            self.invisible_numbers.append(int(m.group(1)))\n\n    def assoc_clause(self, tree):\n        legs = [node for node in tree.find_data(\"assoc_leg\")]\n        assoc_name = str(first_child(tree, \"assoc_name_def\").children[0])\n        target_names = []\n        entity_names = set()\n        for leg in legs:\n            entity_name = first_child(leg, \"entity_name_ref\").children[0].value\n            entity_names.add(entity_name)\n            if first_child(leg, \"card_prefix\") == \"/\":\n                target_names.append(entity_name)\n        for target_name in target_names:\n            self.candidates.add((assoc_name, target_name, *sorted(entity_names - {target_name})))\n    \n    def constraint_clause(self, tree):\n        if first_child(tree, \"constraint_name\").upper() != \"CIF\":\n            return\n        assoc_name = None\n        target_name = None\n        source_names = []\n        for node in tree.find_data(\"constraint_target\"):\n            leg = first_child(node, \"constraint_leg\")\n            box_name = first_child(node, \"box_name_ref\").children[0].value\n            if surrounds(leg, \"..\"):\n                if assoc_name is not None:\n                    return\n                assoc_name = box_name\n            elif surrounds(leg, \"->\"):\n                if target_name is not None:\n                    return\n                target_name = box_name\n            elif leg == \"\" or surrounds(leg, \"--\"):\n                source_names.append(box_name)\n            else:\n                return\n        self.existing.add((assoc_name, target_name, *sorted(source_names)))\n    \n    def get_new_cifs(self, hidden_links_from_sources=False):\n        self.new_cifs = self.candidates - self.existing\n        if not self.new_cifs:\n            return \"\"\n        sep = \", \" if hidden_links_from_sources else \", --\"\n        new_invisible_clauses = [\"\\n\"]\n        new_cif_clauses = [\"\"]\n        for (assoc_name, *entity_names) in sorted(self.new_cifs):\n            n = first_missing_positive(self.invisible_numbers)\n            self.invisible_numbers.append(n)\n            new_invisible_clauses.append(f\"-INVISIBLE_{n}, XX {entity_names[0]}, XX {entity_names[0]}\")\n            new_cif_clauses.append(f\"(CIF) ..{assoc_name}, ->{sep.join(entity_names)}: INVISIBLE_{n}, INVISIBLE_{n}\")\n        if new_cif_clauses == [\"\"]:\n            return \"\"\n        return \"\\n\".join(new_invisible_clauses + new_cif_clauses)\n\n\ndef create_cifs(source, subsubarg):\n    visitor = CreateCifs()\n    tree = parse_source(source)\n    visitor.visit(tree)\n    return source + visitor.get_new_cifs(subsubarg == \"light\")\n"
  },
  {
    "path": "mocodo/rewrite/cross.py",
    "content": "from functools import lru_cache\n\ncrossed_strings = frozenset([\"-++-\", \"-++0\", \"-+0-\", \"-0+-\", \"0++-\", \"+--+\", \"0--+\", \"+0-+\", \"+-0+\", \"+--0\"])\n\n@lru_cache\ndef cross(x1, y1, x2, y2, x3, y3, x4, y4):\n    \"\"\" Tests whether the segments ((x1,y1), (x2,y2)) and ((x3,y3), (x4,y4)) intersect.\n        Two segments sharing exactly one extremity are NOT considered as intersecting. \"\"\"\n    a = (x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)\n    b = (x4-x3)*(y2-y3) - (y4-y3)*(x2-x3)\n    c = (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1)\n    d = (x2-x1)*(y4-y1) - (y2-y1)*(x4-x1)\n    if a or b or c or d:\n        return \"\".join(\"+\" if x>0 else (\"-\" if x<0 else \"0\") for x in (a, b, c, d)) in crossed_strings\n    else: # the segments are collinear\n        if x1 == x2:  # both segments are vertical\n            if y1 < y2:\n                if y3 < y4:\n                    return y2 > y3 and y1 < y4\n                else:\n                    return y2 > y4 and y1 < y3\n            else:\n                if y3 < y4:\n                    return y1 > y3 and y2 < y4\n                else:\n                    return y1 > y4 and y2 < y3\n        else:\n            if x1 < x2:\n                if x3 < x4:\n                    return x2 > x3 and x1 < x4\n                else:\n                    return x2 > x4 and x1 < x3\n            else:\n                if x3 < x4:\n                    return x1 > x3 and x2 < x4\n                else:\n                    return x1 > x4 and x2 < x3\n"
  },
  {
    "path": "mocodo/rewrite/damerau_levenshtein.py",
    "content": "# http://mwh.geek.nz/2009/04/26/python-damerau-levenshtein-distance/\n\n\ndef distance(seq1, seq2):\n    \"\"\"Calculate the Damerau-Levenshtein distance between sequences.\n\n    This distance is the number of additions, deletions, substitutions,\n    and transpositions needed to transform the first sequence into the\n    second. Although generally used with strings, any sequences of\n    comparable objects will work.\n\n    Transpositions are exchanges of *consecutive* characters; all other\n    operations are self-explanatory.\n\n    This implementation is O(N*M) time and O(M) space, for N and M the\n    lengths of the two sequences.\n\n    >>> damerau_levenshtein('ba', 'abc')\n    2\n    >>> damerau_levenshtein('fee', 'deed')\n    2\n    It works with arbitrary sequences too:\n    >>> damerau_levenshtein('abcd', ['b', 'a', 'c', 'd', 'e'])\n    2\n    \"\"\"\n    # codesnippet:D0DE4716-B6E6-4161-9219-2903BF8F547F\n    # Conceptually, this is based on a len(seq1) + 1 * len(seq2) + 1 matrix.\n    # However, only the current and two previous rows are needed at once,\n    # so we only store those.\n    one_ago = None\n    this_row = list(range(1, len(seq2) + 1)) + [0]\n    for x in range(len(seq1)):\n        # Python lists wrap around for negative indices, so put the\n        # leftmost column at the *end* of the list. This matches with\n        # the zero-indexed strings and saves extra calculation.\n        two_ago, one_ago, this_row = one_ago, this_row, [0] * len(seq2) + [x + 1]\n        for y in range(len(seq2)):\n            del_cost = one_ago[y] + 1\n            add_cost = this_row[y - 1] + 1\n            sub_cost = one_ago[y - 1] + (seq1[x] != seq2[y])\n            this_row[y] = min(del_cost, add_cost, sub_cost)\n            # This block deals with transpositions\n            if (x > 0 and y > 0 and seq1[x] == seq2[y - 1]\n                and seq1[x-1] == seq2[y] and seq1[x] != seq2[y]):\n                this_row[y] = min(this_row[y], two_ago[y - 2] + 1)\n    return this_row[len(seq2) - 1]\n"
  },
  {
    "path": "mocodo/rewrite/fitness.py",
    "content": "from math import hypot\n\nfrom .cross import cross\n\n\ndef fitness(links, multiplicity, col_count, row_count, max_distance = 4):\n    \"\"\" Return (by closure) a function evaluating the aesthetic quality of a given layout. \"\"\"\n    \n    def evaluate(layout):\n        for (position, index) in enumerate(layout):\n            coordinates[index] = divmod(position, col_count)\n        segments = [(coordinates[p1], coordinates[p2], multiplicity[p1, p2]) for (p1, p2) in links]\n        total_distances = 0\n        short_segments = []\n        for  ((y1, x1), (y2, x2), m) in segments:\n            distance = distances[abs(x1-x2)][abs(y1-y2)] * m\n            if distance <= max_distance:\n                short_segments.append((x1, y1, x2, y2))\n            total_distances += distance\n        crossing_count = (link_count - len(short_segments)) * link_count\n        for (i, (x1, y1, x2, y2)) in enumerate(short_segments):\n             for (x3, y3, x4, y4) in short_segments[i+1:]:\n                 crossing_count += cross(x1, y1, x2, y2, x3, y3, x4, y4)\n        return (crossing_count, total_distances)\n    \n    distances = [[hypot(i, j) - 1 for j in range(row_count)] for i in range(col_count)]\n    coordinates = [(0, 0)] * (row_count * col_count)\n    link_count = len(links)\n    return evaluate\n"
  },
  {
    "path": "mocodo/rewrite/guess_entities.py",
    "content": "from ..tools.string_tools import rstrip_digit_or_underline\nfrom ..tools.parser_tools import parse_source\n\ndef run(source, id_prefix):\n    if id_prefix is None:\n        id_prefix = \"id. \"\n    tree = parse_source(source)\n    entity_name_refs =set(node.children[0].children[0].value for node in tree.find_data(\"entity_name_ref\"))\n    entity_name_defs = set(node.children[0].children[0].value for node in tree.find_data(\"entity_name_def\"))\n    new_entity_names = entity_name_refs - entity_name_defs\n    new_entity_clauses = [source]\n    for ent in new_entity_names:\n        lower_ent = rstrip_digit_or_underline(ent.lower())\n        if lower_ent in (\"date\", \"calendrier\", \"calendar\"):\n            clause = f\"{ent}: date\"\n        elif lower_ent == \"période\":\n            clause = f\"{ent}: début, _fin\"\n        elif lower_ent == \"period\":\n            clause = f\"{ent}: start, _end\"\n        else:\n            clause = f\"{ent}: {id_prefix}{lower_ent}, \"\n        new_entity_clauses.append(clause)\n    return \"\\n\".join(new_entity_clauses)\n"
  },
  {
    "path": "mocodo/rewrite/obfuscate.py",
    "content": "import random\nimport re\nfrom pathlib import Path\n\nfrom .damerau_levenshtein import distance\nfrom ..mocodo_error import MocodoError\n\nMIN_DISTANCE = 3  # Minimal Damereau-Levenshtein distance between two words.\n\ndef random_words_generator(\n    lorem_text,\n    find_all_words=re.compile(r\"(?u)[^\\W\\d_]{3,}\").findall,\n):\n    # use dict.fromkeys instead of set for preserving order\n    words = list(dict.fromkeys(word.lower() for word in find_all_words(lorem_text)))\n    random.shuffle(words)\n    previous_words = set()\n    for word in words:\n        for previous_word in previous_words:\n            if distance(word, previous_word) < MIN_DISTANCE:\n                # Keeping this word would be too confusing, let's try the next one.\n                break\n        else:\n            yield word\n            previous_words.add(word)\n\n\ndef obfuscator_factory(pool, params):\n\n    pool = pool or \"\"\n\n    # Initialize the random word generator\n    try:\n        lorem_path = Path(pool)\n        lorem_text = lorem_path.read_text(encoding=\"utf8\")\n    except IOError:\n        lorem_dir = Path(params[\"script_directory\"], \"resources\", \"lorem\")\n        lorem_path = lorem_dir / f\"{lorem_path.stem}.txt\"\n        try:\n            lorem_text = lorem_path.read_text(encoding=\"utf8\")\n        except IOError:\n            lorem_path = lorem_dir / \"lorem.txt\"\n            lorem_text = lorem_path.read_text(encoding=\"utf8\")\n    random_word = random_words_generator(lorem_text)\n\n    # Define and return the inner obfuscator function\n    cache = {}\n    def obfuscate(name):\n        suffix = \"\"\n        if name not in cache or name == params[\"df\"]:\n            try:\n                new_name = next(random_word)\n            except StopIteration:\n                raise MocodoError(12, _('Obfuscation failed. Not enough substitution words in \"{filename}\".').format(filename=lorem_path)) from None # fmt: skip\n            if name.isupper():\n                new_name = new_name.upper()\n            elif name.islower():\n                new_name = new_name.lower()\n            elif name.partition(\" \")[0].istitle():\n                new_name = new_name.title()\n            cache[name] = new_name\n        return cache[name] + suffix\n    return obfuscate\n"
  },
  {
    "path": "mocodo/rewrite/op_tk.py",
    "content": "import contextlib\nfrom pathlib import Path\nimport random\nimport re\n\n__import__(\"sys\").path[0:0] = [\".\"]\n\nfrom ..parse_mcd import Transformer\nfrom ..tools.parser_tools import transform_source\nfrom ..tools.string_tools import ascii, camel, snake, pascal, TRUNCATE_DEFAULT_SIZE\nfrom ..mocodo_error import MocodoError\nfrom .cards import fix_card, infer_dfs, infer_roles\nfrom .types import read_default_datatypes, create_type_placeholders, guess_types\nfrom .obfuscate import obfuscator_factory\nfrom .arrows import create_df_arrows\nfrom .constraints import create_cifs\n\nELEMENT_TO_TOKENS = {\n    \"arrows\": [\"leg_arrow\"],\n    \"attrs\": [\"attr\"],\n    \"boxes\": [\"box_name\"],\n    \"card_prefixes\": [\"card_prefix\"],\n    \"cards\": [\"card\"],\n    \"roles\": [\"leg_note\"],\n    \"leg_notes\": [\"leg_note\"],\n    \"constraint_notes\": [\"constraint_note\"],\n    \"labels\": [\"box_name\", \"attr\"],\n    \"texts\": [\"box_name\", \"attr\", \"leg_note\", \"constraint_note\"],\n    \"notes\": [\"leg_note\", \"constraint_note\"],\n    \"types\": [\"datatype\"],\n}\n\nGENERAL_OPERATIONS = { # operations that can be applied to any token\n    \"ascii\": ascii,\n    \"camel\": camel,\n    \"capitalize\": str.capitalize,\n    \"casefold\": str.casefold,\n    \"echo\": lambda x: x,\n    \"lower\": str.lower,\n    \"pascal\": pascal,\n    \"snake\": snake,\n    \"swapcase\": str.swapcase,\n    \"title\": str.title,\n    \"upper\": str.upper,\n}\n\n\nclass Mapper(Transformer):\n\n    def __init__(self, op_name, pre_token, subsubarg, params):\n        tokens = ELEMENT_TO_TOKENS[pre_token]\n        op = GENERAL_OPERATIONS.get(op_name)\n        if op is None: # op_tk operations with limited applicability and/or using a subsubarg\n            if op_name == \"randomize\" and pre_token == \"types\":\n                resource_dir = Path(params[\"script_directory\"], \"resources\")\n                pool = list(dict(read_default_datatypes(resource_dir)).values())\n                op = lambda _: random.choice(pool)\n            elif op_name == \"delete\" and pre_token in (\"attrs\", \"notes\", \"roles\", \"constraint_notes\", \"arrows\", \"types\", \"card_prefixes\"):\n                op = lambda _: \"\"\n            elif op_name == \"delete\" and pre_token == \"cards\":\n                op = lambda _: \"XX\"\n            elif op_name == \"fix\" and pre_token == \"cards\":\n                op = fix_card\n            elif op_name == \"randomize\" and pre_token in (\"labels\", \"texts\", \"boxes\", \"attrs\", \"notes\", \"roles\", \"constraint_notes\"):\n                op = obfuscator_factory(subsubarg, params)\n            elif op_name == \"truncate\":\n                truncate_size = TRUNCATE_DEFAULT_SIZE\n                if subsubarg and subsubarg.isdigit():\n                    truncate_size = int(subsubarg) or truncate_size\n                op = lambda x: x[:truncate_size]\n            elif op_name == \"slice\":\n                slice_start = slice_stop = None\n                if subsubarg:\n                    with contextlib.suppress(ValueError):\n                        slice_start = int(subsubarg.partition(\":\")[0])\n                    with contextlib.suppress(ValueError):\n                        slice_stop = int(subsubarg.partition(\":\")[2])\n                op = lambda x: x[slice_start:slice_stop]\n            elif op_name == \"replace\":\n                (substring, __, repl) = subsubarg.partition(\"/\")\n                op = lambda x: x.replace(substring, repl)\n            elif op_name == \"suffix\":\n                op = lambda x: f\"{x}{subsubarg}\"\n            elif op_name == \"prefix\":\n                op = lambda x: f\"{subsubarg}{x}\"\n            else:\n                raise MocodoError(24, _('Operation \"{op_name}\" cannot be applied to \"{pre_token}\".').format(op_name=op_name, pre_token=pre_token))\n        update_first_child = lambda tree: tree[0].update(value=op(tree[0].value))\n        for token in tokens:\n            setattr(self, token, update_first_child)\n\n\ndef run(source, op_name, subargs, params, **kargs):\n    if op_name == \"randomize\" and not subargs:\n        subargs = {\"labels\": \"\"} # used for obfuscation\n    elif op_name == \"delete\" and not subargs:\n        subargs = dict.fromkeys(\"types notes attrs cards\".split(), \"\")\n    for (pre_token, subsubarg) in subargs.items():\n        # filter special non-op_tk operations\n        if op_name == \"create\" and pre_token == \"types\":\n            source = create_type_placeholders(source, subsubarg) if subsubarg is not None else guess_types(source, params)\n        elif op_name == \"create\" and pre_token == \"df_arrows\":\n            source = create_df_arrows(source, subsubarg)\n        elif op_name == \"create\" and re.match(\"(?i)dfs?$\", pre_token):\n            source = infer_dfs(source, params[\"df\"])\n        elif op_name == \"create\" and pre_token == \"roles\":\n            source = infer_roles(source)\n        elif op_name == \"create\" and re.match(\"(?i)cifs?$\", pre_token):\n            source = create_cifs(source, subsubarg)\n        else: # apply a normal op_tk operation\n            source = transform_source(source, Mapper(op_name, pre_token, subsubarg, params))\n        if op_name == \"delete\":\n            # After a delete operation, remove any [] that may have been left behind\n            # (it's too tedious to remove them from the AST, and it's not worth it).\n            source = re.sub(r\" *\\[\\]\", \" \", source)\n    return source\n"
  },
  {
    "path": "mocodo/rewrite/types.py",
    "content": "from pathlib import Path\nimport re\n\nfrom ..parse_mcd import Visitor\nfrom ..tools.parser_tools import first_child, parse_source, reconstruct_source\nfrom ..tools.string_tools import ascii, snake, strip_surrounds\n\nclass CreateTypePlaceholder(Visitor):\n\n    def __init__(self, subsubarg):\n        self.default = strip_surrounds(subsubarg, \"[]\")\n\n    def typed_attr(self, tree):\n        if len(tree.children) == 1:\n            tree.children[0].children[0].value += f\" [{self.default}]\"\n\ndef create_type_placeholders(source, subsubarg):\n    visitor = CreateTypePlaceholder(subsubarg)\n    tree = parse_source(source)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n\ndef read_default_datatypes(resource_dir, language=\"en\"):\n    path = Path(resource_dir, f\"default_datatypes_{language}.tsv\")\n    if not path.exists():\n        return\n    for line in path.read_text(encoding=\"utf8\").splitlines():\n        fields = line.split(\"\\t\")\n        if len(fields) < 2:\n            continue\n        yield tuple(fields[:2])\n\nclass GuessType(Visitor):\n\n    def __init__(self,params):\n        resource_dir = Path(params[\"script_directory\"], \"resources\")\n        self.field_types = dict(read_default_datatypes(resource_dir)) # English always used as fallback\n        language = params.get(\"language\", \"en\")\n        if language != \"en\":\n            self.field_types.update(read_default_datatypes(resource_dir, language))\n        # Convert the dict to a list of tuples, and sort them by decreasing length\n        # so that the longest match is found first.\n        self.field_types = sorted(self.field_types.items(), key=lambda x: -len(x[0]))\n        # Precompile the regexes\n        self.field_types = [(re.compile(k).search, v) for (k, v) in self.field_types]\n\n    def typed_attr(self, tree):\n        n = len(tree.children)\n        # Possible lengths of the children list:\n        # 0: empty attribute\n        # 1: attribute without datatype\n        # 3: attribute with empty datatype\n        # 4: attribute with non-empty datatype\n        if n not in (1, 3):\n            return\n        attr = first_child(tree, \"attr\")\n        needle = snake(ascii(attr)).replace(\"_\", \" \").lower()\n        for (found, datatype) in self.field_types:\n            if found(needle):\n                break\n        else:\n            datatype = \"\"\n        if n == 1: # concatenate to the attribute label the datatype between brackets\n            tree.children[0].children[0].value += f\" [{datatype}]\"\n        else: # insert the datatype between brackets\n            tree.children[1].value += datatype\n\n\ndef guess_types(source, params):\n    visitor = GuessType(params)\n    tree = parse_source(source)\n    visitor.visit(tree)\n    return reconstruct_source(tree)\n"
  },
  {
    "path": "mocodo/tools/__init__.py",
    "content": ""
  },
  {
    "path": "mocodo/tools/graphviz_tools.py",
    "content": "import re\n\ndef create_name_to_index():\n    \"\"\"\n    Return a function that maps names to unique numbers.\n    Used to generate short \"names\" for Graphviz nodes.\n    \"\"\"\n    cache = {}\n    def name_to_index(name):\n        if name not in cache:\n            cache[name] = len(cache) + 1\n        return cache[name]\n    return name_to_index\n\n\ndef minify_graphviz(text):\n    # Suppress comments\n    text = re.sub(r\"(?m)^ *//.*$\", \"\", text)\n    # Suppress empty lines\n    text = re.sub(r\"(?m)^\\s*\\n\", \"\", text)\n    # Suppress leading spaces\n    text = re.sub(r\"(?m)^\\s+\", \"\", text)\n    # Suppress newline before delimiters\n    text = re.sub(r\"\\n([]<>])\", r\"\\1\", text)\n    # Factorize edges\n    while True:\n        (text, n) = re.subn(r\"(?m)(\\d+) (-[->]) ([^[\\n]+)\\n\\1 -- \", r\"\\1 \\2 \\3,\", text)\n        if n == 0:\n            break\n    # Suppress spaces around arrows\n    text = re.sub(r\"(?m)(\\d+) (-[->]) \", r\"\\1\\2\", text)\n    # Suppress spaces before opening brackets\n    text = re.sub(r\"(?m)^(edge|node) *\\[\", r\"\\1[\", text)\n    # Suppress newlines after opening brackets\n    text = re.sub(r\"\\[\\n\", r\"[\", text)\n    # Supress spaces after \\d+ -> \\d+\n    text = re.sub(r\"(?m)^([\\d>-]+) +\", r\"\\1\", text)\n    return text\n\n\nNODE_OPTIONS_TEMPLATE = \"\"\"\n      shape=none\n      fontcolor=\"{cell_font_color}\"\n      fontsize={cell_font_size}\n      fontname=\"Helvetica\"\n\"\"\" # This constant is public\n\nTABLE_TEMPLATE = \"\"\"<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"{cell_bg_color}\"\n        color=\"{stroke_color}\"\n        cellpadding=\"4\"\n    >\n        TABLE_CONTENT_PLACEHOLDER\n    </table>\n\"\"\"\n\nHEADER_TEMPLATE = \"\"\"<tr>\n            <td bgcolor=\"{header_bg_color}\" colspan=\"COL_COUNT_PLACEHOLDER\">\n                <font\n                    color=\"{header_font_color}\"\n                    point-size=\"{header_font_size}\"\n                >HEADER_TEXT_PLACEHOLDER</font>\n            </td>\n        </tr>\n\"\"\"\n\nSPECIAL_FONT_TEMPLATE = \"\"\"<font face=\"Courier\">TEXT_PLACEHOLDER</font>\"\"\"\n\nROW_TEMPLATE = \"\"\"        <tr>{cells}</tr>\"\"\"\n\n\ndef row_format_to_td_templates(\n    row_format, # a LaTeX-like table format string (e.g. \"|l|c|r|\")\n    ALIGN={\n        \"l\": ' align=\"left\"',\n        \"c\": \"\",\n        \"r\": ' align=\"right\"',\n    },\n):\n    \"\"\"\n    Return a list of td element templates from a LaTeX-table-like format string.\n    NB: an uppercase letter means \"use the special font\".\n    \"\"\"\n    acc = []\n    row_format = f\" {row_format} \"\n    for (i, symbol) in enumerate(row_format[1:-1], 1):\n        text = \"TEXT_PLACEHOLDER\"\n        if symbol.isupper():\n            text = SPECIAL_FONT_TEMPLATE\n            symbol = symbol.lower()\n        if symbol in ALIGN:\n            align = ALIGN[symbol]\n            sides = ' sides=\"TB'\n            if row_format[i - 1] == \"|\":\n                sides += \"L\"\n            if row_format[i + 1] == \"|\":\n                sides += \"R\"\n            sides += '\"'\n            if sides == ' sides=\"TBLR\"':\n                sides = \"\"\n            acc.append(f\"<td{align}{sides}>{text}</td>\")\n    return acc\n\ndef table_as_label(header_text, rows, row_format, style):\n    \"\"\"Return a table has an HTML-like Graphviz label.\"\"\"\n    header = HEADER_TEMPLATE.format(**style)\n    header = header.replace(\"HEADER_TEXT_PLACEHOLDER\", header_text)\n    td_templates = row_format_to_td_templates(row_format)\n    header = header.replace(\"COL_COUNT_PLACEHOLDER\", str(len(td_templates)))\n    trs = []\n    for row in rows:\n        cells = []\n        for (text, td_template) in zip(row, td_templates):\n            cells.append(td_template.replace(\"TEXT_PLACEHOLDER\", text))\n        trs.append(ROW_TEMPLATE.format(cells=\"\".join(cells)))\n    trs = \"\\n\".join(trs)\n    table = TABLE_TEMPLATE.format(**style)\n    table = table.replace(\"TABLE_CONTENT_PLACEHOLDER\", header + trs)\n    return table\n\nif __name__ == \"__main__\":\n    header_text = \"CLIENT\"\n    rows = [\n        [\"PK\", \"id. client\", \"varchar(8)\"],\n        [\"\", \"nom\", \"varchar(30)\"],\n        [\"\", \"prénom\", \"varchar(30)\"],\n        [\"\", \"âge\", \"int\"],\n    ]\n    row_format = \"|cl|L|\"\n    style = {\n        \"cell_bg_color\": \"#c0d4ff\",\n        \"stroke_color\": \"#578dff\",\n        \"header_bg_color\": \"#97b8ff\",\n        \"header_font_color\": \"#131114\",\n        \"header_font_size\": 14,\n        \"cell_font_color\": \"#3e3c42\",\n        \"cell_font_size\": 12,\n    }\n    node_options = NODE_OPTIONS_TEMPLATE.format(**style)\n    table = table_as_label(header_text, rows, row_format, style)\n    print(\"digraph {\")\n    print(f\"node [{node_options}]\")\n    print(f'1 [label=<{table}>]')\n    print(\"}\")\n"
  },
  {
    "path": "mocodo/tools/load_mini_yaml.py",
    "content": "from ast import literal_eval\nimport re\n\ndef parse_value(v):\n    v = v.strip()\n    if v.startswith(\"'\"):\n        if v != \"''\":\n            v = v.replace(\"''\", \"\\\\'\")\n        v = literal_eval(f\"r{v}\")\n        v = v.replace(\"\\\\'\", \"'\")\n        v = re.sub(r\"(?<!\\\\)\\\\n\", \"\\n\", v) # replace \\n into newline, except if preceded by \\\n        v = v.replace(r\"\\\\n\", r\"\\n\") # replace stuff like \\\\newcommand into \\newcommand\n        v = re.sub(r\"(?<!\\\\)\\\\t\", \"\\t\", v) # idem for \\t\n        v = v.replace(r\"\\\\t\", r\"\\t\") # idem for \\t\n        v = v.replace(\"\\\\xa0\", '\\xa0') # replace \\xa0 into non-breaking space\n        return v\n    elif v.lower() == \"true\":\n        return True\n    elif v.lower() == \"false\":\n        return False\n    elif v.lower() == \"null\":\n        return None\n    elif v:\n        return literal_eval(v)\n    else:\n        return []\n\ndef run(path):\n    text = path.read_text(encoding=\"utf8\")\n    data = {}\n    lines = text.splitlines()\n    i = 0\n    while i < len(lines):\n        line = lines[i]\n        i += 1\n        (k1, v1) = re.match(r\"(\\S+?) *: *(.*?) *$\", line).groups()\n        data[k1] = parse_value(v1)\n        if data[k1] == []: # list of dicts\n            while i < len(lines):\n                line = lines[i]\n                (prefix, k2, v2) = re.match(r\"([- ]*)(\\w+?) *: *(.*?) *$\", line).groups()\n                if prefix == \"  - \": # new dict\n                    data[k1].append({k2: parse_value(v2)})\n                    i += 1\n                elif prefix == \"    \": # continuation of previous dict\n                    data[k1][-1][k2] = parse_value(v2)\n                    i += 1\n                else:\n                    break\n    return data\n"
  },
  {
    "path": "mocodo/tools/parser_tools.py",
    "content": "__import__(\"sys\").path[0:0] =  [\".\"]\n\nfrom ..mocodo_error import MocodoError\nfrom ..parse_mcd import Token, Visitor, Transformer, Lark_StandAlone, Discard\n\ndef parse_source(source):\n    parser = Lark_StandAlone()\n    try:\n        return parser.parse(f\"{source}\\n\")\n    except Exception as error:\n        pin = _(\"Parsing error:\\n{e}\\n\").format(e=error.get_context(source))\n        expected = set(error.expected)\n        t = error.token.type\n        v = repr(error.token.value)\n        if error.token.value == \"\\n\":\n            t = \"BREAK\"\n        try:\n            previous = error.token_history[0].type\n        except:\n            previous = None\n        if expected == {'PERCENT', 'CONSTRAINT_LPAREN', 'BREAK', 'INDENT', 'PHANTOMS', 'BOX_NAME', 'SLASH', 'PLUS', 'MINUS', 'NL'}:\n            raise MocodoError(501, _('{pin}\"{v}\" is not a valid line beginning.').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'PHANTOMS', 'PERCENT', 'CONSTRAINT_LPAREN', 'PLUS', 'MINUS', 'NL', 'SLASH', 'BOX_NAME'}:\n            raise MocodoError(501, _('{pin}\"{v}\" is not a valid line beginning.').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'INHERITANCE_ARROW', 'COLON', 'NL', 'MORETHAN', 'SP', 'COMMA'}:\n            raise MocodoError(502, _('{pin}Malformed box name.').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'COLON', 'COMMA'}:\n            raise MocodoError(503, _('{pin}A valid box name starting a line must be followed by a colon or a comma.').format(pin=pin)) # fmt: skip\n        if t == \"COMMA\" and expected == {'SP', 'BOX_NAME'}:\n            raise MocodoError(505, _('{pin}Illegal comma after inheritance.').format(pin=pin)) # fmt: skip\n        if t == \"NUMBER\" and expected == {'BOX_NAME', 'CARD', 'LBRACKET', 'LEG_ARROW', 'MINUS', 'SLASH', 'SP', 'ID_MARK'}:\n            raise MocodoError(506, _('{pin}Malformed cardinalities.').format(pin=pin)) # fmt: skip\n        if expected == {'CARD'}:\n            raise MocodoError(506, _('{pin}Malformed cardinalities.').format(pin=pin)) # fmt: skip\n        if expected == {'SLASH', 'CARD', 'ID_MARK'}:\n            raise MocodoError(506, _('{pin}Malformed cardinalities.').format(pin=pin)) # fmt: skip\n        if expected == {'INHERITANCE_NAME', 'BACKSLASH'} or expected == {'BACKSLASH'}:\n            raise MocodoError(507, _('{pin}An inheritance name must be \"\", \"X\", \"T\" or \"XT\".').format(pin=pin)) # fmt: skip\n        if t == \"COMMA\" and expected == {'NL'}:\n            raise MocodoError(508, _('{pin}Only two coords are allowed.').format(pin=pin)) # fmt: skip\n        if t == \"BREAK\" and expected == {'BOX_NAME', 'CARD', 'LBRACKET', 'LEG_ARROW', 'MINUS', 'SLASH', 'SP', 'ID_MARK'}:\n            raise MocodoError(509, _('{pin}An association leg cannot be empty.').format(pin=pin)) # fmt: skip\n        if expected == {'BOX_NAME', 'NUMBER'}:\n            raise MocodoError(510, _('{pin}Expected a number or a box name.').format(pin=pin)) # fmt: skip\n        if expected == {'BOX_NAME'}:\n            raise MocodoError(511, _('{pin}Only a box name is possible here.').format(pin=pin)) # fmt: skip\n        if expected == {'RBRACKET'}:\n            raise MocodoError(512, _('{pin}Unclosed square bracket.').format(pin=pin)) # fmt: skip\n        if expected == {'CONSTRAINT_RPAREN'}:\n            raise MocodoError(514, _('{pin}A constraint name cannot contain more than three characters.').format(pin=pin)) # fmt: skip\n        if expected == {'SP', 'BOX_NAME', 'CONSTRAINT_LEG'}:\n            raise MocodoError(515, _('{pin}Expected a box name or a constraint leg.').format(pin=pin)) # fmt: skip\n        if expected == {'LBRACKET', 'SP', 'BOX_NAME', 'NL', 'COLON', 'CONSTRAINT_LEG'}:\n            raise MocodoError(516, _('{pin}Illegal character after a constraint name.').format(pin=pin)) # fmt: skip\n        if expected == {'INHERITANCE_ARROW', 'SP'} or expected == {'INHERITANCE_ARROW'}:\n            raise MocodoError(517, _('{pin}A parent name must be followed by an inheritance arrow among \"<=\", \"<-\", \"->\", \"=>\".').format(pin=pin)) # fmt: skip\n        if t == \"INHERITANCE_ARROW\" and expected == {'MORETHAN'}:\n            raise MocodoError(518, _('{pin}Please change the old foreign key syntax (\"->\") by the new one (\">\").').format(pin=pin)) # fmt: skip\n        if t == \"SP\" and expected == {'COMMA', 'COLON', 'NL'}:\n            raise MocodoError(519, _('{pin}The constraint targets must be comma-separated.').format(pin=pin)) # fmt: skip\n        if expected == {'HASHTAG', 'NL', 'ID_GROUPS', 'ID_MARK', 'ATTR', 'COMMA'}:\n            raise MocodoError(500, _('{pin}An attribute label cannot start with \"{v[1]!r}\".').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'ID_MARK', 'NL', 'ATTR', 'COMMA'}:\n            raise MocodoError(500, _('{pin}An attribute label cannot start with \"{v[1]!r}\".').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'LBRACKET', 'NL', 'COMMA'}:\n            raise MocodoError(521, _('{pin}An attribute label cannot contain \"{v}\".').format(pin=pin, v=v)) # fmt: skip\n        if t in (\"COMMA\", \"NL\", \"BREAK\") and expected == {'MORETHAN'}:\n            raise MocodoError(522, _('{pin}An attribute starting with \"#\" must contain two \">\".').format(pin=pin)) # fmt: skip\n        if t in (\"COMMA\", \"NL\", \"BREAK\") and expected == {'ATTR'}:\n            raise MocodoError(523, _('{pin}Expected an entity name.').format(pin=pin)) # fmt: skip\n        if expected == {'COLON', 'COMMA', 'NL'}:\n            raise MocodoError(524, _('{pin}A box name cannot contain \"{v}\".').format(pin=pin, v=v)) # fmt: skip\n        if expected == {\"COMMA\"}:\n            raise MocodoError(525, _('{pin}Expected a comma.').format(pin=pin, v=v)) # fmt: skip)\n        if t == \"BOX_NAME\" and expected == {'COMMA', 'NL'}:\n            raise MocodoError(526, _('{pin}Malformed number.').format(pin=pin, v=v)) # fmt: skip\n        if previous in (\"NUMBER\", \"BOX_NAME\") and expected == {'COMMA', 'NL'}:\n            raise MocodoError(527, _('{pin}More than two coordinates.').format(pin=pin, v=v)) # fmt: skip\n        if expected == {'LBRACKET', 'NL', 'COMMA', 'MORETHAN'}:\n            raise MocodoError(528, _('{pin}An attribute label cannot have more than one optionality marker.').format(pin=pin, v=v))\n        raise MocodoError(504, _('{pin}Token \"{t}\" encountered. Expected tokens: {expected}.').format(pin=pin, expected=expected, t=t))\n        \n    \nclass Reconstructor(Visitor):\n\n    def __init__(self):\n        self.result = []\n    \n    def __default__(self, tree):\n        for child in tree.children:\n            if isinstance(child, Token):\n                self.result.append((child.line, child.column, child.value))\n\ndef reconstruct_source(tree):\n    visitor = Reconstructor()\n    try:\n        visitor.visit(tree)\n    except Exception as visitor_error:\n        raise visitor_error.__context__ if visitor_error.__context__ else visitor_error\n    return \"\".join(s for (_, _, s) in sorted(visitor.result))\n\ndef transform_source(source, transformer):\n    tree = parse_source(source)\n    try:\n        new_tree = transformer.transform(tree)\n    except Exception as transformer_error:\n        raise transformer_error.__context__ if transformer_error.__context__ else transformer_error\n    return reconstruct_source(new_tree)\n\nclass ClauseExtractor(Transformer):\n\n    discard = lambda self, tree: Discard\n    COLON = discard\n    COMMA = discard\n    NL = discard\n    SP = discard\n    LBRACKET = discard\n    RBRACKET = discard\n    LPAREN = discard\n    RPAREN = discard\n    CONSTRAINT_LPAREN = discard\n    CONSTRAINT_RPAREN = discard\n    HASHTAG = discard\n    MORETHAN = discard\n    PERCENT = discard\n    BACKSLASH = discard\n\n    def _item(self, key, tree):\n        return (key, tree[0].value)\n    \n    card = lambda self, tree: self._item(\"card\", tree)\n    entity_name_ref = lambda self, tree: self._item(\"entity\", tree)\n    box_name_ref = lambda self, tree: self._item(\"name\", tree)\n    leg_note = lambda self, tree: self._item(\"leg_note\", tree)\n    constraint_note = lambda self, tree: self._item(\"constraint_note\", tree)\n    constraint_leg = lambda self, tree: self._item(\"constraint_leg\", tree)\n    constraint_name = lambda self, tree: self._item(\"name\", tree)\n    card_prefix = lambda self, tree: self._item(\"card_prefix\", tree)\n    card_hidden = lambda self, tree: self._item(\"card_hidden\", tree)\n    leg_arrow = lambda self, tree: self._item(\"leg_arrow\", tree)\n    inheritance_arrow = lambda self, tree: self._item(\"inheritance_arrow\", tree)\n    entity_name_def = lambda self, tree: self._item(\"name\", tree)\n    inheritance_name = lambda self, tree: self._item(\"name\", tree)\n    assoc_name_def = lambda self, tree: self._item(\"name\", tree)\n    attr = lambda self, tree: self._item(\"attribute_label\", tree)\n    box_def_prefix = lambda self, tree: self._item(\"box_def_prefix\", tree)\n    id_mark = lambda self, tree: self._item(\"id_mark\", tree)\n\n    def start(self, tree):\n        return tree\n\n    def line(self, tree):\n        d = {}\n        for t in tree:\n            d.update(t)\n        return d\n    \n    def break_(self, tree):\n        return {\"type\": \"break\"}\n\n    def phantoms(self, tree):\n        return {\"type\": \"phantoms\", \"count\": tree[0].value.count(\":\")}\n    \n    def comment(self, tree):\n        return {\"type\": \"comment\", \"text\": f\"%{tree[0].value.rstrip()}\"}\n    \n    def entity_clause(self, tree):\n        return tree + [(\"type\", \"entity\")]\n\n    def assoc_clause(self, tree):\n        return tree + [(\"type\", \"association\")]\n    \n    def constraint_clause(self, tree):\n        return tree + [(\"type\", \"constraint\")]\n    \n    def inheritance_clause(self, tree):\n        # Tweak the tree to make it look like an association\n        d = dict(item for item in tree if isinstance(item, tuple))\n        d[\"name\"] = d.get(\"name\", \"\")\n        d[\"type\"] = \"inheritance\"\n        d[\"legs\"] = [{\"entity\": d[\"entity\"], \"rank\": -1}] + d[\"legs\"]\n        del d[\"entity\"]\n        return list(d.items())\n\n    def typed_attr(self, tree):\n        return (\"attr\", dict(tree))\n    \n    def assoc_leg(self, tree):\n        return (\"leg\", dict(tree))\n    \n    def inheritance_parent(self, tree):\n        return (\"entity\", tree[0][1])\n    \n    def inheritance_child(self, tree):\n        return (\"leg\", dict(tree))\n    \n    def foreign_reference(self, tree):\n        return (\"foreign_reference\", dict(tree))\n\n    def box_name(self, tree):\n        return tree[0]\n    \n    def seq(self, tree):\n        items = []\n        for (rank, (_, d)) in enumerate(tree):\n            d[\"rank\"] = rank\n            items.append(d)\n        return (f\"{tree[0][0]}s\", items)\n\n    def assoc_attr(self, tree):\n        if tree[0] == \"_\":\n            tree[-1][1][\"id_mark\"] = \"_\"\n        return (\"attr\", tree[-1][1])\n\n    def assoc_leg(self, tree):\n        return (\"leg\", dict(tree))\n    \n    def constraint_target(self, tree):\n        return (\"constraint_target\", dict(tree))\n    \n    def foreign_reference(self, tree):\n        return (\"foreign_reference\", dict(tree))\n\n    def entity_or_table_attr(self, tree):\n        d = dict(tree)\n        if \"foreign_reference\" in d:\n            d.update(d.pop(\"foreign_reference\"))\n        if \"attr\" in d:\n            d.update(d.pop(\"attr\"))\n        return (\"attr\", d)\n    \n    def this_table_attr(self, tree):\n        return (\"attribute_label\", tree[0][1])\n    \n    def that_table(self, tree):\n        return (\"that_table\", tree[0][1])\n    \n    def that_table_attr(self, tree):\n        return (\"that_table_attribute_label\", tree[0][1])\n    \n    def constraint_coords(self, tree):\n        return (\"constraint_coords\", [self._constraint_coord(x) for x in tree])\n    \n    def _constraint_coord(self, x):\n        try:\n            x = float(x)\n            return int(x) if x == int(x) else x\n        except (TypeError, ValueError):\n            return x[1]\n\n    def indent(self, tree):\n        return {\"type\": \"break\", \"indent\": tree[0].value} # Add a default type for dangling indents\n    \n    def datatype(self, tree):\n        return (\"datatype\", tree[0].value if tree else \"\")\n    \n    def id_groups(self, tree):\n        return (\"id_groups\", \"\".join(sorted(set(tree[0].value))))\n    \ndef extract_clauses(source):\n    tree = parse_source(source)\n    extractor = ClauseExtractor()\n    result = extractor.transform(tree)\n    for line in result:\n        if \"type\" not in line:\n            line[\"type\"] = \"break\"\n    # Uniformize indentations. First, find the set of all distinct indentations.\n    # Include the empty string if absent. Then, sort them by length. Finally,\n    # replace each indentation by a number of spaces proportional to its index\n    # in the sorted list.\n    indents = set(line.get(\"indent\", \"\") for line in result)\n    indents.add(\"\")\n    indents = sorted(indents, key=len)\n    indents = {indent: \"  \" * i for (i, indent) in enumerate(indents)}\n    for (line, raw_line) in zip(result, source.splitlines()):\n        line[\"indent\"] = indents[line.get(\"indent\", \"\")]\n        line[\"source\"] = line[\"indent\"] + raw_line.lstrip()\n    return result\n\n\ndef first_child(tree, name, i=0):\n    result = next(tree.find_data(name), None)\n    if result is None:\n        return \"\"\n    return result.children[i]\n\ndef is_identifier(i, id_groups, id_mark):\n    # Entity (foo, bar)\n    if i == 0:\n        if \"0\" not in id_groups:\n            return True # foo / 1_foo\n    elif \"0\" in id_groups:\n        return True # 0_bar / 01_bar\n    elif id_mark == \"_\" and id_groups == \"\":\n        return True # _bar\n    return False # 0_foo / 01_foo / _foo / bar / 1_bar\n\nif __name__ == \"__main__\":\n    # python -m mocodo.tools.parser_tools\n    source = \"EMPLOYER, 01 PARTICIPANT, 0N ENTREPRISE:\\nCLIENT: num client, nom\"\n    tree = parse_source(source)\n    print(tree.pretty())\n    print(reconstruct_source(tree))\n    print(extract_clauses(source))\n"
  },
  {
    "path": "mocodo/tools/pluralize_fr.py",
    "content": "irregular_plurals = {\n 'aieul': 'aieux',\n 'aval': 'avals',\n 'bail': 'baux',\n 'bal': 'bals',\n 'betail': 'bestiaux',\n 'bijou': 'bijoux',\n 'bleu': 'bleus',\n 'caillou': 'cailloux',\n 'cal': 'cals',\n 'carnaval': 'carnavals',\n 'chacal': 'chacals',\n 'choral': 'chorals',\n 'chou': 'choux',\n 'ciel': 'cieux',\n 'corail': 'coraux',\n 'credit-bail': 'credits-baux',\n 'email': 'emaux',\n 'emeu': 'emeus',\n 'emmenthal': 'emmenthals',\n 'enfeu': 'enfeus',\n 'etal': 'etals',\n 'fatal': 'fatals',\n 'festival': 'festivals',\n 'gemmail': 'gemmaux',\n 'genou': 'genoux',\n 'gentilhomme': 'gentilshommes',\n 'glacial': 'glacials',\n 'hibou': 'hiboux',\n 'joujou': 'joujoux',\n 'landau': 'landaus',\n 'madame': 'mesdames',\n 'mademoiselle': 'mesdemoiselles',\n 'mistral': 'mistrals',\n 'monsieur': 'messieurs',\n 'natal': 'natals',\n 'naval': 'navals',\n 'oeil': 'yeux',\n 'oeil-de-boeuf': 'oeils-de-boeuf',\n 'oeil-de-chat': 'oeils-de-chat',\n 'pal': 'pals',\n 'pascal': 'pascals',\n 'perinatal': 'perinatals',\n 'pneu': 'pneus',\n 'postnatal': 'postnatals',\n 'pou': 'poux',\n 'prenatal': 'prenatals',\n 'recital': 'recitals',\n 'regal': 'regals',\n 'sarrau': 'sarraus',\n 'soupirail': 'soupiraux',\n 'travail': 'travaux',\n 'unau': 'unaus',\n 'vantail': 'vantaux',\n 'veto': 'veto',\n 'vitrail': 'vitraux'\n}\n\ndef pluralize(word):\n    word = word.lower()\n    if word in irregular_plurals:\n        return irregular_plurals[word]\n    if word.endswith((\"eau\", \"oeu\")):\n        return word + \"x\"\n    if word.endswith((\"s\", \"x\", \"z\")):\n        return word\n    if word.endswith(\"al\"):\n        return word[:-2] + \"aux\"\n    if word.endswith((\"au\", \"eu\")):\n        return word + \"x\"\n    return word + \"s\"\n"
  },
  {
    "path": "mocodo/tools/string_tools.py",
    "content": "import textwrap\nimport re\nfrom unicodedata import combining, normalize\nimport base64\nimport zlib\n\nTRUNCATE_DEFAULT_SIZE = 64\n\ndef wrap_label(s, wrapping_ratio=2):\n    \"\"\"\n    Break a given short string into a list of lines, trying to keep the\n    width/height ratio just above wrapping_ratio.\n    \"\"\"\n    min_width = max(map(len, re.split(r\"[-\\s]+\", s)))\n    for width in range(min_width, len(s)):\n        lines = textwrap.wrap(s, width=width)\n        if max(map(len, lines)) / len(lines) > wrapping_ratio:\n            return lines\n    return [s]\n\ndef rstrip_digit_or_underline(s):\n    \"\"\"\n    Get rid of single digit suffix, if any. Works on empty strings too.\n    Used for entity and association raw names.\n    \"\"\"\n    return s[:-1] if s[-1:].isdigit() or s[-1:] == \"_\" else s\n\ndef surrounds(s, ends):\n    \"\"\"\n    Check if s is surrounded by the first and last characters of ends.\n    Works on empty strings too.\n    \"\"\"\n    return s[:1] == ends[:1] and s[-1:] == ends[-1:]\n\ndef strip_surrounds(s, ends):\n    \"\"\"\n    Remove the first and last characters of s if they match the first and last\n    characters of ends. Works on empty strings too.\n    \"\"\"\n    return s[1:-1] if surrounds(s, ends) else s\n\ndef is_a_description(note):\n    if not note:\n        return False\n    if note.startswith((\"+\", \"-\")):\n        return False\n    return \" \" in note\n\n# ASCII\n\nLATIN = \"ä  æ  ǽ  đ ð ƒ ħ ı ł ø ǿ ö  œ  ß  ŧ ü  Ä  Æ  Ǽ  Đ Ð Ƒ Ħ I Ł Ø Ǿ Ö  Œ  ẞ  Ŧ Ü \"\nASCII = \"ae ae ae d d f h i l o o oe oe ss t ue AE AE AE D D F H I L O O OE OE SS T UE\"\n\n\ndef ascii(s, outliers=str.maketrans(dict(zip(LATIN.split(), ASCII.split())))):\n    return \"\".join(c for c in normalize(\"NFD\", s.translate(outliers)) if not combining(c))\n\ndef raw_to_bid(box_raw_name):\n    return re.sub(r\"\\W\", \"_\", ascii(box_raw_name).upper())\n\ndef aggressive_split(\n    input_string,\n    find_all_words = re.compile(r\"(?u)[^\\W_]+\").findall\n):\n    # Split the string, and further split the words\n    result = []\n    for word in find_all_words(input_string):\n        previous_is_digit = word[0].isdigit()\n        previous_is_lower = word[0].islower()\n        i = 0\n        for (j, c) in enumerate(word[1:], 1):\n            current_is_lower = c.islower()\n            current_is_digit = c.isdigit()\n            if (\n                previous_is_digit and not current_is_digit\n                or\n                not previous_is_digit and current_is_digit\n                or\n                previous_is_lower and not current_is_lower\n            ):\n                result.append(word[i:j])\n                i = j\n            previous_is_lower = current_is_lower\n            previous_is_digit = current_is_digit\n        result.append(word[i:])\n    return result\n\n# A decorator which calls\n\ndef spare_protected_suffix(\n    function,\n    is_protected_suffix = re.compile(r\"[_0-9]\").match,\n):\n    def wrapper(input_string):\n        suffix = input_string[-1:]\n        if is_protected_suffix(suffix):\n            input_string = input_string[:-1]\n        else:\n            suffix = \"\"\n        result = function(input_string)\n        return result + suffix\n    return wrapper\n\n@spare_protected_suffix\ndef camel(input_string):\n    result = \"\".join([word.capitalize() for word in aggressive_split(input_string)])\n    return result[:1].lower() + result[1:]\n\n@spare_protected_suffix\ndef pascal(input_string):\n    return \"\".join([word.capitalize() for word in aggressive_split(input_string)])\n\n@spare_protected_suffix\ndef snake(input_string):\n    return \"_\".join([word for word in aggressive_split(input_string)])\n\ndef urlsafe_encoding(text):\n    return base64.urlsafe_b64encode(zlib.compress(text.encode('utf-8'), 9)).decode('ascii')\n\n# Markdown\n\ndef markdown_table(rows, formats=None):\n    \"\"\"\n    Return a Markdown table from a list of rows, each row being a tuple.\n    The first row is the header. For maximum readability, in text mode, each column\n    is filled with spaces so that the longest cell fits in the column.\n    'formats' is a sequence of formatting symbols \"l\", \"c\", \"r\".\n    \"\"\"\n    rows = [list(map(str, row)) for row in rows]\n    widths = [max(map(len, column)) for column in zip(*rows)]\n    result = [\"| \" + \" | \".join(f\"{c:<{w}}\" for (w, c) in zip(widths, row)) + \" |\" for row in rows]\n    formats = formats or \"l\" * len(rows[0])\n    formats = [(\"-\" if x == \"r\" else \":\") + \"-\" * w + (\"-\" if x == \"l\" else \":\") for (w, x) in zip(widths, formats)]\n    result[1:1] = [\"|\" + \"|\".join(formats) + \"|\"]\n    return \"\\n\".join(result)\n"
  },
  {
    "path": "mocodo/tools/various.py",
    "content": "def invert_dict(d):\n    return {v: k for (k, vs) in d.items() for v in vs}\n\ndef first_missing_positive(l):\n    return min(set(range(1, len(l) + 2)).difference(l))\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"mocodo\"\nversion = \"4.3.3\" # previously dynamically set by poetry-version-plugin\ndescription = \"Modélisation Conceptuelle de Données. Nickel. Ni souris.\"\nauthors = [{ name = \"Aristide Grange\" }]\nrequires-python = \">=3.6.1,<4\"\nreadme = \"README.md\"\nlicense = \"MIT\"\nkeywords = [\n    \"education\",\n    \"relational\",\n    \"database\",\n    \"drawing\",\n    \"ERD\",\n    \"SVG\",\n    \"Merise\",\n]\nclassifiers = [\n    \"Development Status :: 5 - Production/Stable\",\n    \"Environment :: Console\",\n    \"Framework :: IPython\",\n    \"Intended Audience :: Education\",\n    \"Intended Audience :: Information Technology\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Natural Language :: English\",\n    \"Operating System :: OS Independent\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3.6\",\n    \"Topic :: Database\",\n    \"Topic :: Education\",\n]\ndependencies = [\"requests>=2.22.0,<3\"]\n\n[project.urls]\nHomepage = \"https://www.mocodo.net/\"\nRepository = \"https://github.com/laowantong/mocodo/\"\nissues = \"https://github.com/laowantong/mocodo/issues\"\n\n[project.scripts]\nmocodo = \"mocodo.__main__:main\"\n\n[project.optional-dependencies]\nsvg = [\n    \"cairosvg>=2.7.1\",\n]\nclipboard = [\n    \"pyperclip>=1.9.0\",\n]\n\n[dependency-groups]\ndev = [\n    \"pytest>=7.0.1\",\n]\n\n[tool.poetry-version-plugin]\nsource = \"init\" # read version from __init__.py\n\n[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n"
  },
  {
    "path": "setup.py",
    "content": "\"\"\"A setuptools based setup module.\nSee:\nhttps://packaging.python.org/en/latest/distributing.html\nhttps://github.com/pypa/sampleproject\n\"\"\"\n\n# Always prefer setuptools over distutils\nfrom setuptools import setup\n# To use a consistent encoding\nfrom codecs import open\nfrom . import __version__\n\nlong_description = \"\"\"\nMocodo is an open-source tool for designing and teaching relational databases. It takes as an input a textual description of both entities and associations of an entity-relationship diagram (ERD). It outputs a vectorial drawing in SVG and a relational schema in various formats (SQL, LaTeX, Markdown, etc.).\n\nInstallation\n------------\n\nThe recommended way to install Mocodo is to use pip:\n\n::\n\n    pip install mocodo\n\nIf this fails, ensure first you have a working Python 3 installation.\n\nUsage\n-------\n\nGenerate the conceptual diagram of a default ERD:\n\n::\n\n    mocodo\n\nShow the argument list:\n\n::\n\n    mocodo --help\n\nMore\n------\n\n`Mocodo online\n<http://mocodo.net/>`_\n\n`Documentation\n<https://laowantong.github.io/mocodo/doc/fr_refman.html>`_\n\n`Source code on GitHub\n<https://github.com/laowantong/mocodo/>`_\"\"\"\n\nwith open(\"README.rst\", \"w\", \"utf8\") as f:\n    f.write(long_description)\n\nsetup(\n    name='mocodo',\n\n    # Versions should comply with PEP440.  For a discussion on single-sourcing\n    # the version across setup.py and the project code, see\n    # https://packaging.python.org/en/latest/single_source_version.html\n    version=version,\n\n    description='Modélisation Conceptuelle de Données. Nickel. Ni souris.',\n    long_description=long_description,\n\n    # The project's main homepage.\n    url='https://github.com/laowantong/mocodo',\n\n    # Author details\n    author='Aristide Grange',\n    author_email='mocodo@wingi.net',\n\n    # Choose your license\n    license='MIT',\n\n    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers\n    classifiers=[\n        # How mature is this project? Common values are\n        #   3 - Alpha\n        #   4 - Beta\n        #   5 - Production/Stable\n        'Development Status :: 5 - Production/Stable',\n\n        # Indicate who your project is intended for\n        'Intended Audience :: Education',\n        'Intended Audience :: Information Technology',\n        'Topic :: Database',\n\n        # Pick your license as you wish (should match \"license\" above)\n        'License :: OSI Approved :: MIT License',\n\n        # Specify the Python versions you support here. In particular, ensure\n        # that you indicate whether you support Python 2, Python 3 or both.\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.6',\n    ],\n\n    # What does your project relate to?\n    keywords='relational database drawing ERD SVG',\n\n    # You can just specify the packages manually here if your project is\n    # simple. Or you can use find_packages().\n    packages=[\"mocodo\"],\n    # List run-time dependencies here.  These will be installed by pip when\n    # your project is installed. For an analysis of \"install_requires\" vs pip's\n    # requirements files see:\n    # https://packaging.python.org/en/latest/requirements.html\n    # install_requires=['peppercorn'],\n\n    # List additional groups of dependencies here (e.g. development\n    # dependencies). You can install these using the following syntax,\n    # for example:\n    # $ pip install -e .[dev,test]\n    # extras_require={\n    #     'dev': ['check-manifest'],\n    #     'test': ['coverage'],\n    # },\n\n    # If there are data files included in your packages that need to be\n    # installed, specify them here.  If using Python 2.6 or less, then these\n    # have to be included in MANIFEST.in as well.\n    package_data={\n        'mocodo': [\n            'resources/colors/*.json',\n            'resources/lorem/*.txt',\n            'resources/relation_templates/*.json',\n            'resources/i18n/*.mo',\n            'resources/shapes/*.json',\n            'resources/pristine_sandbox.mcd',\n            'resources/font_metrics.json'\n        ],\n    },\n\n    # Although 'package_data' is the preferred approach, in some case you may\n    # need to place data files outside of your packages. See:\n    # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa\n    # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'\n    # data_files=[('my_data', ['data/data_file'])],\n\n    # To provide executable scripts, use entry points in preference to the\n    # \"scripts\" keyword. Entry points provide cross-platform support and allow\n    # pip to create the appropriate form of executable for the target platform.\n    entry_points={\n        'console_scripts': ['mocodo=mocodo.__main__:main'],\n    },\n    \n    # Not all packages, however, are capable of running in compressed form,\n    # because they may expect to be able to access either source code or data files\n    # as normal operating system files. \n    zip_safe=False,\n)\n"
  },
  {
    "path": "test/__init__.py",
    "content": "\n"
  },
  {
    "path": "test/launch_tests.sh",
    "content": "python -m unittest\n"
  },
  {
    "path": "test/test_api.py",
    "content": "import unittest\nimport gettext\nimport re\nfrom pathlib import Path\n\ngettext.NullTranslations().install()\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo import __version__\nfrom mocodo.api import mocodo\n\nclass TestMocodoApi(unittest.TestCase):\n\n    def test_unrecognized_arguments(self):\n        result = mocodo(\"foo bar\")\n        self.assertEqual(result, None)\n    \n    def test_no_arguments(self):\n        paths = list(map(Path, [\n            \"pristine_sandbox.svg\",\n            \"pristine_sandbox_static.svg\",\n            \"pristine_sandbox_geo.json\"\n        ]))\n        for path in paths:\n            path.unlink(missing_ok=True)\n        result = mocodo()\n        self.assertEqual(mocodo(\"\"), result)\n        for path in paths:\n            self.assertTrue(path.is_file())\n        for path in paths:\n            path.unlink()\n    \n    def test_help(self):\n        result = mocodo(\"--help\")\n        self.assertEqual(result, None)\n    \n    def test_version(self):\n        result = mocodo(\"--version\")\n        self.assertEqual(result, __version__)\n    \n    def test_language(self):\n        result = mocodo(\"--language=en\")\n        self.assertRegex(result, re.compile(r\"Output file.+generated\"))\n        result = mocodo(\"--language=fr\")\n        self.assertRegex(result, re.compile(r\"Fichier de sortie.+succès\"))\n    \n    def test_input_and_output_dir(self):\n        path_json = Path(\"test/ccp_geo.json\")\n        path_svg = Path(\"test/ccp.svg\")\n        path_json.unlink(missing_ok=True)\n        path_svg.unlink(missing_ok=True)\n        mocodo(\"-i doc/mocodo_notebook/ccp.mcd --output_dir test\")\n        self.assertTrue(path_json.is_file())\n        self.assertTrue(path_svg.is_file())\n        path_json.unlink()\n        path_svg.unlink()\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_argument_parser.py",
    "content": "import unittest\nimport argparse\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.argument_parser import extract_subargs\n\n\nclass TestSubArguments(unittest.TestCase):\n    def test_extract_subargs(self):\n        parser = argparse.ArgumentParser()\n        parser.add_argument(\n            \"--actual\",\n            metavar=\"STR\",\n            nargs=\"*\",\n            type=extract_subargs,\n        )\n        args = parser.parse_args(\n            [  # NB: names not necessarily the same as in the current version\n                \"--actual\",\n                \"arrange:algo=bb,grid=organic\",\n                \"randomize:cards=_/,types=mysql,labels=four_letter_words\",\n                \"map:ascii=labels,n=3,x=3.14,delete='',guess=types,create=types\",\n                \"drain\",\n                \"flip:vertical,horizontal,diagonal\",\n                \"\"\"data_dict:type,box=\"\",label=\"libellé de l'attribut\",tsv\"\"\",\n            ]\n        )\n        expected = [\n            (\n                \"arrange\",\n                {\"algo\": \"bb\", \"grid\": \"organic\"},\n            ),\n            (\n                \"randomize\",\n                {\"cards\": \"_/\", \"types\": \"mysql\", \"labels\": \"four_letter_words\"},\n            ),\n            (\n                \"map\",\n                {\"ascii\": \"labels\", \"n\": \"3\", \"x\": \"3.14\", \"delete\": \"\", \"guess\": \"types\", \"create\": \"types\"},\n            ),\n            (\"drain\", {}),\n            (\n                \"flip\",\n                {\"vertical\": None, \"horizontal\": None, \"diagonal\": None},\n            ),\n            (\n                \"data_dict\",\n                {\"type\": None, \"box\": \"\", \"label\": \"libellé de l'attribut\", \"tsv\": None}\n            ),\n        ]\n        self.assertEqual(args.actual, expected)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_arrange_bb.py",
    "content": "import unittest\nfrom random import seed\nimport gettext\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite._arrange import run as arrange\nfrom mocodo.mocodo_error import MocodoError\n\ngettext.NullTranslations().install()\n\nclass ArrangeBB(unittest.TestCase):\n\n    def test_constraints(self):\n        source = \"\"\"\n            SUSPENDISSE: diam\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            CONSECTETUER: elit, sed\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            DIGNISSIM: ligula, massa, varius\n\n            DF, 11 RISUS, 0N RISUS\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            RISUS: ultricies, _cras, elementum\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n        \"\"\".replace(\"   \", \"\").strip()\n\n        # balanced = 0\n        subargs = {\"algo\": \"bb\", \"balanced\": \"\"}\n        seed(42)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            SUSPENDISSE: diam\n            DF, 11 LOREM, 1N SUSPENDISSE\n\n            RISUS: ultricies, _cras, elementum\n            DIGNISSIM: ligula, massa, varius\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            LOREM: ipsum, dolor, sit\n\n            DF, 11 RISUS, 0N RISUS\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            CONSECTETUER: elit, sed\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n        # balanced = 1\n\n        subargs = {\"algo\": \"bb\", \"balanced\": \"1\"}\n        seed(42)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 RISUS, 0N RISUS\n            :\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            LOREM: ipsum, dolor, sit\n            DF, 11 LOREM, 1N SUSPENDISSE\n\n            RISUS: ultricies, _cras, elementum\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            CONSECTETUER: elit, sed\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            SUSPENDISSE: diam\n\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            DIGNISSIM: ligula, massa, varius\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            :\n            :\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n        # organic\n\n        subargs = {\"algo\": \"bb\"}\n        seed(2)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 LOREM, 1N SUSPENDISSE\n            SUSPENDISSE: diam\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            :\n\n            LOREM: ipsum, dolor, sit\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            DIGNISSIM: ligula, massa, varius\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            CONSECTETUER: elit, sed\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            RISUS: ultricies, _cras, elementum\n\n            :\n            :\n            :\n            DF, 11 RISUS, 0N RISUS\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n        # wide = 8 (default)\n\n        subargs = {\"algo\": \"bb\", \"wide\": None} # the mere presence of the key is enough\n        seed(2)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 RISUS, 0N RISUS\n            RISUS: ultricies, _cras, elementum\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            :\n            CONSECTETUER: elit, sed\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            SUSPENDISSE: diam\n\n            :\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            DIGNISSIM: ligula, massa, varius\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            LOREM: ipsum, dolor, sit\n            DF, 11 LOREM, 1N SUSPENDISSE\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n        # wide = 3\n\n        subargs = {\"algo\": \"bb\", \"wide\": \"3\"} # the mere presence of the key is enough\n        seed(2)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 LOREM, 1N SUSPENDISSE\n            SUSPENDISSE: diam\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n\n            LOREM: ipsum, dolor, sit\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            DIGNISSIM: ligula, massa, varius\n            RISUS: ultricies, _cras, elementum\n\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            CONSECTETUER: elit, sed\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            DF, 11 RISUS, 0N RISUS\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n        # timeout too low\n\n        subargs = {\"algo\": \"bb\", \"timeout\": 0.000001}\n        seed(2)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.10\", arrange, source, subargs)\n\n    def test_non_connected_graph(self):\n        source = \"\"\"\n            SUSPENDISSE: diam\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            CONSECTETUER: elit, sed\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n            DIGNISSIM: ligula, massa, varius\n\n            DF, 11 RISUS, 0N RISUS\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            RISUS: ultricies, _cras, elementum\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n        \"\"\".replace(\"   \", \"\").strip()\n        subargs = {\"algo\": \"bb\", \"balanced\": \"\"}\n        seed(42)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 RISUS, 0N RISUS\n            SUSPENDISSE: diam\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            CONSECTETUER: elit, sed\n\n            RISUS: ultricies, _cras, elementum\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            DIGNISSIM: ligula, massa, varius\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            :\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n    def test_no_link(self):\n        source = \"\"\"\n            SUSPENDISSE: diam\n            CONSECTETUER: elit, sed\n\n            LOREM: ipsum, dolor, sit\n            DIGNISSIM: ligula, massa, varius\n\n            RISUS: ultricies, _cras, elementum\n        \"\"\".replace(\"   \", \"\").strip()\n        subargs = {\"algo\": \"bb\", \"balanced\": \"0\"}\n        seed(42)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            :\n            DIGNISSIM: ligula, massa, varius\n            :\n            CONSECTETUER: elit, sed\n            :\n            LOREM: ipsum, dolor, sit\n            :\n\n            :\n            RISUS: ultricies, _cras, elementum\n            :\n            SUSPENDISSE: diam\n            :\n            :\n            :\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n    def test_inheritance(self):\n        source = \"\"\"\n            SUSPENDISSE: diam\n            /XT\\\\ SUSPENDISSE -> CONSECTETUER, LOREM\n            CONSECTETUER: elit, sed\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            DIGNISSIM: ligula, massa, varius\n\n            DF, 11 RISUS, 0N RISUS\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            RISUS: ultricies, _cras, elementum\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n        \"\"\".replace(\"   \", \"\").strip()\n        subargs = {\"algo\": \"bb\"}\n        seed(4)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 LOREM, 1N SUSPENDISSE\n            SUSPENDISSE: diam\n            :\n            :\n            :\n\n            LOREM: ipsum, dolor, sit\n            /XT\\\\ SUSPENDISSE -> CONSECTETUER, LOREM\n            :\n            :\n            :\n\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            CONSECTETUER: elit, sed\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            RISUS: ultricies, _cras, elementum\n            DF, 11 RISUS, 0N RISUS\n\n            :\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            DIGNISSIM: ligula, massa, varius\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            :\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n        \n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_arrange_ga.py",
    "content": "import unittest\nfrom random import seed\nimport gettext\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite._arrange import run as arrange\n\ngettext.NullTranslations().install()\n\nclass ArrangeGA(unittest.TestCase):\n\n    def test_arrange(self):\n        source = \"\"\"\n            SUSPENDISSE: diam\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            CONSECTETUER: elit, sed\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n            DIGNISSIM: ligula, massa, varius\n\n            DF, 11 RISUS, 0N RISUS\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n            RISUS: ultricies, _cras, elementum\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n        \"\"\".replace(\"   \", \"\").strip()\n        subargs = {\"algo\": \"ga\", \"max_generations\": 50, \"population_size\": 100}\n        seed(1)\n        actual = arrange(source, subargs)\n        expected = \"\"\"\n            DF, 11 RISUS, 0N RISUS\n            SUSPENDISSE: diam\n            DF, 11 LOREM, 1N SUSPENDISSE\n            LOREM: ipsum, dolor, sit\n\n            RISUS: ultricies, _cras, elementum\n            SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus\n            CONSECTETUER: elit, sed\n            AMET, 11> LOREM, 01 CONSECTETUER: adipiscing\n\n            SEMPER, 0N RISUS, 1N DIGNISSIM\n            MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM\n            DIGNISSIM: ligula, massa, varius\n            TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec\n        \"\"\".replace(\"   \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_association.py",
    "content": "import gettext\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.association import *\nfrom mocodo.tools.parser_tools import extract_clauses\n\n\ngettext.NullTranslations().install()\n\ndef association_wrapper(s, **kargs):\n    Association.reset_df_counter()\n    return Association(extract_clauses(s)[0], **kargs)\n\nclass ParseTest(unittest.TestCase):\n    \n    def test_reflexive(self):\n        a = association_wrapper(\"ÊTRE AMI, 0N BANDIT, 0N BANDIT\")\n        self.assertEqual(a.bid, \"ETRE_AMI\")\n        self.assertEqual(a.name_view, \"ÊTRE AMI\")\n        self.assertEqual(a.attributes, [])\n        for (i, leg) in enumerate(a.legs):\n            self.assertEqual(leg.card_view, \"0,N\")\n            self.assertEqual(leg.entity_bid, \"BANDIT\")\n            self.assertEqual(leg.arrow, \"\")\n            self.assertEqual(leg.note, None)\n\n    def test_double(self):\n        l = [\n            association_wrapper(\"EMPLOYER, 01 PARTICIPANT, 0N ENTREPRISE\"),\n            association_wrapper(\"EMPLOYER, 01 PARTICIPANT, 0N ENTREPRISE:\"),\n        ]\n        for a in l:\n            self.assertEqual(a.bid, \"EMPLOYER\")\n            self.assertEqual(a.name_view, \"EMPLOYER\")\n            self.assertEqual(a.legs[0].card_view, \"0,1\")\n            self.assertEqual(a.legs[0].entity_bid, \"PARTICIPANT\")\n            self.assertEqual(a.legs[0].arrow, \"\")\n            self.assertEqual(a.legs[0].note, None)\n            self.assertEqual(a.legs[1].card_view, \"0,N\")\n            self.assertEqual(a.legs[1].entity_bid, \"ENTREPRISE\")\n            self.assertEqual(a.legs[1].arrow, \"\")\n            self.assertEqual(a.legs[1].note, None)\n        self.assertEqual(l[0].attributes, [])\n        self.assertEqual(l[1].attributes[0].kind, \"phantom\")\n\n    def test_triple(self):\n        a = association_wrapper(\"SUIVRE, 0N DATE, 11 ÉTUDIANT, 0N ENSEIGNANT\")\n        self.assertEqual(a.bid, \"SUIVRE\")\n        self.assertEqual(a.name_view, \"SUIVRE\")\n        self.assertEqual(a.attributes, [])\n        self.assertEqual(a.legs[0].card_view, \"0,N\")\n        self.assertEqual(a.legs[0].entity_bid, \"DATE\")\n        self.assertEqual(a.legs[0].arrow, \"\")\n        self.assertEqual(a.legs[0].note, None)\n        self.assertEqual(a.legs[1].card_view, \"1,1\")\n        self.assertEqual(a.legs[1].entity_bid, \"ETUDIANT\")\n        self.assertEqual(a.legs[1].arrow, \"\")\n        self.assertEqual(a.legs[1].note, None)\n        self.assertEqual(a.legs[2].card_view, \"0,N\")\n        self.assertEqual(a.legs[2].entity_bid, \"ENSEIGNANT\")\n        self.assertEqual(a.legs[2].arrow, \"\")\n        self.assertEqual(a.legs[2].note, None)\n\n    def test_arrow(self):\n        a = association_wrapper(\"EMPLOYER, 01> PARTICIPANT, 0N< ENTREPRISE\")\n        self.assertEqual(a.legs[0].arrow, \">\")\n        self.assertEqual(a.legs[1].arrow, \"<\")\n        self.assertEqual(a.legs[0].card_view, \"0,1\")\n        self.assertEqual(a.legs[1].card_view, \"0,N\")\n\n    def test_note(self):\n        a = association_wrapper(\"ENGENDRER, 0N [Parent] PERSONNE, 1N [Enfant] PERSONNE\")\n        self.assertEqual(a.legs[0].note, \"Parent\")\n        self.assertEqual(a.legs[1].note, \"Enfant\")\n        self.assertEqual(a.legs[0].card_view, \"0,N\")\n        self.assertEqual(a.legs[1].card_view, \"1,N\")\n\n    def test_note_in_agregation(self):\n        a = association_wrapper(\"ENGENDRER, 0N [Père] PERSONNE, 0N [Mère] PERSONNE, /1N [Enfant] PERSONNE\")\n        self.assertEqual(a.legs[0].note, \"Père\")\n        self.assertEqual(a.legs[1].note, \"Mère\")\n        self.assertEqual(a.legs[2].note, \"Enfant\")\n        self.assertEqual(a.legs[0].card_view, \"0,N\")\n        self.assertEqual(a.legs[1].card_view, \"0,N\")\n        self.assertEqual(a.legs[2].card_view, \"1,N\")\n\n    def test_attributes(self):\n        l = [\n            association_wrapper(\"SOUTENIR, 01 ÉTUDIANT, 0N DATE: note stage, heure soutenance\"),\n            association_wrapper(\"SOUTENIR, 01 ÉTUDIANT, 0N DATE:  note stage , heure soutenance \"),\n            association_wrapper(\"SOUTENIR, 01 ÉTUDIANT, 0N DATE:  note stage,heure soutenance \"),\n        ]\n        for a in l:\n            self.assertEqual([att.label for att in a.attributes], [\"note stage\", \"heure soutenance\"])\n            self.assertEqual([att.__class__ for att in a.attributes], [SimpleAssociationAttribute, SimpleAssociationAttribute])\n\n    def test_identifiers(self):\n        a = association_wrapper(\"Réserver, 1N Client, 0N Chambre: _Date, Durée\")\n        self.assertEqual([att.label for att in a.attributes], [\"Date\", \"Durée\"])\n        self.assertEqual([att.__class__ for att in a.attributes], [StrongAttribute, SimpleAssociationAttribute])\n\n    def test_other_card(self):\n        a = association_wrapper(\"SOUTENIR, XX ÉTUDIANT, XX DATE: note stage\")\n        self.assertTrue(not a.legs[0].card_view.strip())\n        self.assertTrue(not a.legs[1].card_view.strip())\n        a = association_wrapper(\"SOUTENIR, AB ÉTUDIANT, CD DATE: note stage\")\n        self.assertEqual(a.legs[0].card_view, \"A,B\")\n        self.assertEqual(a.legs[1].card_view, \"C,D\")\n        a = association_wrapper(\"SOUTENIR, XY ÉTUDIANT, XY DATE: note stage\")\n        self.assertEqual(a.legs[0].card_view, \"Y\")\n        self.assertEqual(a.legs[1].card_view, \"Y\")\n\n    def test_numbered_association_wrapper(self):\n        a = association_wrapper(\"SOUTENIR1, 01 ÉTUDIANT, 0N DATE: note stage\")\n        self.assertEqual(a.bid, \"SOUTENIR1\")\n        self.assertEqual(a.name_view, \"SOUTENIR\")\n        a = association_wrapper(\"SOUTENIR123, 01 ÉTUDIANT, 0N DATE: note stage\")\n        self.assertEqual(a.bid, \"SOUTENIR123\")\n        self.assertEqual(a.name_view, \"SOUTENIR12\")\n\n    def test_df(self):\n        a = association_wrapper(\"DF, 0N CLIENT, 11 COMMANDE\")\n        self.assertEqual(a.bid, \"DF0\")\n        self.assertEqual(a.name_view, \"DF\")\n        a = association_wrapper(\"CIF, 0N CLIENT, 11 COMMANDE\", df_label=\"CIF\")\n        self.assertEqual(a.bid, \"CIF\")\n        self.assertEqual(a.name_view, \"CIF\")\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.37\", association_wrapper, \"DF, 0N CLIENT, 0N COMMANDE\")\n\n    def test_cluster_of_one_entity(self):\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.51\", association_wrapper, \"SUIVRE, 0N DATE, /1N ÉTUDIANT\")\n\n    def test_cluster_of_two_entities(self):\n        a = association_wrapper(\"SUIVRE, 0N DATE, /1N ÉTUDIANT, 0N ENSEIGNANT\")\n        self.assertEqual(a.legs[0].entity_bid, \"DATE\")\n        self.assertEqual(a.legs[0].kind, \"cluster_leg\")\n        self.assertEqual(a.legs[1].entity_bid, \"ETUDIANT\")\n        self.assertEqual(a.legs[1].kind, \"cluster_peg\")\n        self.assertEqual(a.legs[2].entity_bid, \"ENSEIGNANT\")\n        self.assertEqual(a.legs[2].kind, \"cluster_leg\")\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_convert_chen.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.common import Common\nfrom mocodo.convert._chen import *\n\nparams = {\"df\": \"DF\"}\ncommon = Common(params)\n\nclass TestChen(unittest.TestCase):\n\n    def test111N(self):\n        source = \"\"\"\n            Employé: employé\n            Travailler, 11 Département, 1N Employé\n            Département: département\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Département] ==N== <Travailler>\n            [Employé] ==1== <Travailler>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test011N(self):\n        source = \"\"\"\n            Mer: mer\n            Recevoir, 01 Rivière, 1N Mer\n            Rivière: rivière\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Mer] ==1== <Recevoir>\n            [Rivière] --N-- <Recevoir>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test0N1N(self):\n        source = \"\"\"\n            PROJET: projet\n            REQUÉRIR, 1N PROJET, 0N PIÈCE\n            PIÈCE: pièce\n            COMPOSER, 0N PIÈCE, 0N PIÈCE\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [PIÈCE] --M-- <COMPOSER>\n            [PIÈCE] --M-- <REQUÉRIR>\n            [PIÈCE] --N-- <COMPOSER>\n            [PROJET] ==N== <REQUÉRIR>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_110N(self):\n        source = \"\"\"\n            Œuvre: œuvre\n            DF, 0N Œuvre, _11 Exemplaire\n            Exemplaire: exemplaire\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [[Exemplaire]] ==N== <<DF>>\n            [Œuvre] --1-- <<DF>>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_gerund(self):\n        source = \"\"\"\n            Produit: produit\n            DF, _11 Ligne de commande, 0N Produit\n            Ligne de commande: _quantité\n            DF, _11 Ligne de commande, 1N Commande\n            Commande: commande\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [<Ligne de commande>] ==N== <<DF>>\n            [<Ligne de commande>] ==N== <<DF>>\n            [Commande] ==1== <<DF>>\n            [Produit] --1-- <<DF>>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_NNN(self):\n        source = \"\"\"\n            Employé: employé\n            Appliquer, 0N Employé, 1N Projet, 1N Compétence\n            Projet: projet\n            Compétence: compétence\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Compétence] ==N== <Appliquer>\n            [Employé] --N-- <Appliquer>\n            [Projet] ==N== <Appliquer>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_1NN(self):\n        source = \"\"\"\n            Ingénieur: ingénieur\n            Gérer, /1N Responsable, 1N Ingénieur, 1N Projet\n            Projet: projet\n            Responsable: responsable\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Ingénieur] ==N== <Gérer>\n            [Projet] ==N== <Gérer>\n            [Responsable] ==1== <Gérer>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_11N(self):\n        source = \"\"\"\n            Projet: projet\n            Affecter, /1N Site, /1N Projet, 0N Employé\n            Site: site\n            Employé: employé\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Employé] --N-- <Affecter>\n            [Projet] ==1== <Affecter>\n            [Site] ==1== <Affecter>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_111(self):\n        source = \"\"\"\n            Technicien: technicien\n            Utiliser, /1N Technicien, /1N Carnet, /1N Projet\n            Projet: projet\n            Carnet: carnet\n        \"\"\"\n        actual = run(source, common=common, testing=True)\n        expected = \"\"\"\n            [Carnet] ==1== <Utiliser>\n            [Projet] ==1== <Utiliser>\n            [Technicien] ==1== <Utiliser>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_attrs(self):\n        source = \"\"\"\n            COMMANDE: Num. commande, Date, Montant\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n        \"\"\"\n        actual = run(source, common=common, subargs={\"attrs\": 1}, testing=True)\n        expected = \"\"\"\n            <INCLURE> -- (Quantité)\n            [COMMANDE] -- (Date)\n            [COMMANDE] -- (Montant)\n            [COMMANDE] -- (_Num. commande_)\n            [COMMANDE] ==N== <INCLURE>\n            [PRODUIT] -- (Libellé)\n            [PRODUIT] -- (Prix unitaire)\n            [PRODUIT] -- (_Réf. produit_)\n            [PRODUIT] --M-- <INCLURE>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_id_weakness(self):\n        source = \"\"\"\n            Œuvre: œuvre\n            DF, 0N Œuvre, _11 Exemplaire\n            Exemplaire: exemplaire\n        \"\"\"\n        actual = run(source, common=common, subargs={\"attrs\": 1}, testing=True)\n        expected = \"\"\"\n            [[Exemplaire]] -- (.exemplaire.)\n            [[Exemplaire]] ==N== <<DF>>\n            [Œuvre] -- (_œuvre_)\n            [Œuvre] --1-- <<DF>>\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_cross.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.rewrite.cross import cross\n\n\nclass CrossTests(unittest.TestCase):\n\n    def test_non_parallel_normal_intersection(self):\n        self.assertTrue(cross(4,4, 7,4, 4,3, 6,5))\n        self.assertTrue(cross(2,1, 4,3, 1,2, 5,1))\n        self.assertTrue(cross(1,4, 7,4, 4,1, 4,7))\n        self.assertTrue(cross(0,0, 0,5,-1,2, 1,2))\n        self.assertTrue(cross(0,0, 0,5, 1,0,-1,4))\n\n    def test_non_parallel_intersection_is_one_extremity(self):\n        self.assertTrue(cross(2,0, 3,1, 3,0, 3,3))\n        self.assertTrue(cross(5,0, 0,5, 3,2, 5,4))\n        self.assertTrue(cross(0,0, 0,5, 7,5, -7,-5))\n        self.assertTrue(cross(3,0, 3,3, 2,0, 3,1))\n        self.assertTrue(cross(2,0, 3,1, 3,0, 3,3))\n        self.assertTrue(cross(3,3, 3,0, 3,1, 2,0))\n        self.assertTrue(cross(3,1, 2,0, 3,3, 3,0))\n        self.assertTrue(cross(3,0, 3,3, 3,2, 2,3))\n\n    def test_non_parallel_intersection_is_two_extremities(self):\n        \"\"\" This is not considered as a valid intersection. \"\"\"\n        self.assertTrue(not cross(0,0, 0,5, 0,0, 5,0))\n        self.assertTrue(not cross(0,0, 0,1, 0,1, 1,1))\n\n    def test_non_parallel_no_intersection(self):\n        self.assertTrue(not cross(2,2, 8,2, 3,3, 9,6))\n        self.assertTrue(not cross(1,2, 5,6, 3,2, 8,5))\n        self.assertTrue(not cross(0,0, 0,5, 1,2, 4,2))\n        self.assertTrue(not cross(0,0, 0,5, 1,0, 4,6))\n        self.assertTrue(not cross(0,0, 1,0, 3,0, 3,3))\n        self.assertTrue(not cross(0,0, 1,0, 0,1, 0,2))\n\n    def test_parallel_no_intersection(self):\n        self.assertTrue(not cross(1,2, 5,6, 3,2, 5,4))\n        self.assertTrue(not cross(3,3, 5,3, 4,4, 6,4))\n        self.assertTrue(not cross(3,3, 4,3, 5,4, 6,4))\n        self.assertTrue(not cross(0,0, 5,0, 1,1, 5,1))\n\n    def test_colinear_intersection_is_two_extremities(self):\n        \"\"\" This is not considered as a valid intersection. \"\"\"\n        self.assertTrue(not cross(0,0, 1,2, 1,2, 2,4))\n\n    def test_colinear_no_intersection(self):\n        self.assertTrue(not cross(3,3, 4,3, 5,3, 6,3))\n\n    def test_colinear_intersection_is_partial_segment(self):\n        self.assertTrue(cross(0,0, 4,2, 2,1, 6,3))\n\n    def test_colinear_intersection_is_partial_segment_horizontal(self):\n        self.assertTrue(cross(3,3, 5,3, 4,3, 6,3))\n\n    def test_colinear_intersection_is_partial_segment_vertical(self):\n        self.assertTrue(cross(3,3, 3,5, 3,4, 3,6))\n\n    def test_colinear_intersection_is_complete_segment_horizontal(self):\n        self.assertTrue(cross(0,2, 2,2,-2,2, 4,2))\n        self.assertTrue(cross(0,2, 2,2, 0,2, 4,2))\n        self.assertTrue(cross(0,2, 2,2,-2,2, 2,2))\n        self.assertTrue(cross(0,2, 2,2, 1,2, 2,2))\n        self.assertTrue(cross(2,2, 0,2, 1,2, 2,2))\n        self.assertTrue(cross(0,2, 2,2, 2,2, 1,2))\n        self.assertTrue(cross(2,2, 0,2, 2,2, 1,2))\n        self.assertTrue(cross(1,2, 2,2, 0,2, 2,2))\n        self.assertTrue(cross(1,2, 2,2, 2,2, 0,2))\n        self.assertTrue(cross(2,2, 1,2, 0,2, 2,2))\n        self.assertTrue(cross(2,2, 1,2, 2,2, 0,2))\n\n    def test_colinear_intersection_is_complete_segment_vertical(self):\n        self.assertTrue(cross(2,0, 2,2, 2,-2, 2,4))\n        self.assertTrue(cross(2,0, 2,2, 2, 0, 2,4))\n        self.assertTrue(cross(2,0, 2,2, 2,-2, 2,2))\n\n    def test_colinear_intersection_is_complete_segment(self):\n        self.assertTrue(cross(0,0, 6,3, 2,1, 4,2))\n        self.assertTrue(cross(0,0, 6,3, 2,1, 6,3))\n        self.assertTrue(cross(0,0, 6,3, 0,0, 4,2))\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_data/small_pool.txt",
    "content": "Foo\nBar\nBiz\nBuz\n"
  },
  {
    "path": "test/test_data/templates/bad_array_element.yaml",
    "content": "foo:\n  - order: 100\n    bar: null\n  - order: 200\n    bizz: null\n  - buzz\n"
  },
  {
    "path": "test/test_data/templates/bad_circular_1.yaml",
    "content": "parent: 'bad_circular_2'"
  },
  {
    "path": "test/test_data/templates/bad_circular_2.yaml",
    "content": "parent: 'bad_circular_1'"
  },
  {
    "path": "test/test_data/templates/bad_no_order.yaml",
    "content": "foo:\n  - order: 100\n    bar: null\n  - bizz: null\n"
  },
  {
    "path": "test/test_data/templates/bad_non_increasing_order.yaml",
    "content": "foo:\n  - order: 100\n    bar: null\n  - order: 50\n    bizz: null\n"
  },
  {
    "path": "test/test_data/templates/bad_non_numeric_order.yaml",
    "content": "foo:\n  - order: 100\n    bar: null\n  - order: 'bad'\n    bizz: null\n"
  },
  {
    "path": "test/test_data/templates/bad_not_an_object.yaml",
    "content": "- 42"
  },
  {
    "path": "test/test_data/templates/bad_object_value.yaml",
    "content": "foo:\n  'bar': null\n"
  },
  {
    "path": "test/test_data/templates/child.yaml",
    "content": "parent: 'root'\nbuzz: 'updated value'\nbaz:\n  - order: 5\n    foo: 'insert_before'\n  - order: 10\n    qux: 'updated value'\n    quux: 'new_item'\n  - order: 15\n    foo: 'insert_between'\n  - order: 20\n  - order: 35\n    foo: 'insert_after'\nforce_empty_list:\n"
  },
  {
    "path": "test/test_data/templates/expected_child.yaml",
    "content": "foo: 'bar'\nbuzz: 'updated value'\nbaz:\n  - order: 5\n    foo: 'insert_before'\n  - order: 10\n    qux: 'updated value'\n    unchanged: 'unchanged'\n    quux: 'new_item'\n  - order: 15\n    foo: 'insert_between'\n  - order: 30\n    qux: 'quux'\n  - order: 35\n    foo: 'insert_after'\nempty:\nforce_empty_list:\nunchanged: 'unchanged'\n"
  },
  {
    "path": "test/test_data/templates/expected_grandchild.yaml",
    "content": "foo: 'bar'\nbuzz: 'reupdated_value'\nbaz:\n  - order: 1\n    name: 'foo'\n  - order: 10\n    qux: 'updated value'\n    unchanged: 'unchanged'\n    quux: 'new_item'\n  - order: 15\n    foo: 'insert_between'\n  - order: 20\n    name: 'bar'\n  - order: 30\n    qux: 'quux'\nempty:\nforce_empty_list:\nunchanged: 'unchanged'\nbiz:\n  - order: 1\n    foo: 'bar'\n    baz: 'qux'\n  - order: 2\n    foo: 'bar'\n    baz: 'qux'\n"
  },
  {
    "path": "test/test_data/templates/grandchild.yaml",
    "content": "parent: 'test/test_data/templates/child.yaml'\nbuzz: 'reupdated_value'\nbiz:\n  - order: 1\n    foo: 'bar'\n    baz: 'qux'\n  - order: 2\n    foo: 'bar'\n    baz: 'qux'\nbaz:\n  - order: 1\n    name: 'foo'\n  - order: 5\n  - order: 20\n    name: 'bar'\n  - order: 35\n"
  },
  {
    "path": "test/test_data/templates/root.yaml",
    "content": "foo: 'bar'\nbuzz: 42\nbaz:\n  - order: 10\n    qux: 'quux'\n    unchanged: 'unchanged'\n  - order: 20\n    biz: 'buz'\n  - order: 30\n    qux: 'quux'\nempty:\nunchanged: 'unchanged'\nforce_empty_list:\n  - order: 10\n    qux: 'quux'\n"
  },
  {
    "path": "test/test_data_dict.py",
    "content": "import re\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.common import Common\nfrom mocodo.convert import _data_dict as data_dict\n\nclass TestDataDict(unittest.TestCase):\n\n    def test_data_dict(self):\n        source = \"\"\"\n            CLIENT: Réf. client [varchar(8)], Nom, Adresse [varchar(40)]\n            DF, 0N CLIENT, 11 COMMANDE\n            COMMANDE: Num commande [tinyint(4)], Date [date], Montant [decimal(5,2) DEFAULT '0.00']\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]\n            PRODUIT: Réf. produit [varchar(8)], Libellé [varchar(20)], Prix unitaire [decimal(5,2)]\n        \"\"\"\n        params = {\"language\": \"fr\"}\n        common = Common(params)\n\n        # Markdown table with two columns\n\n        subargs ={\n            \"label\": \"Libellé des attributs\",\n            \"type\": \"Type de données\",\n            \"md\": True,\n        }\n        actual = data_dict.run(source, common=common, subargs=subargs)[\"text\"]\n        expected = \"\"\"\n            | Libellé des attributs | Type de données             |\n            |:----------------------|:----------------------------|\n            | Adresse               | varchar(40)                 |\n            | Date                  | date                        |\n            | Libellé               | varchar(20)                 |\n            | Montant               | decimal(5,2) DEFAULT '0.00' |\n            | Nom                   |                             |\n            | Num commande          | tinyint(4)                  |\n            | Prix unitaire         | decimal(5,2)                |\n            | Quantité              | tinyint(4)                  |\n            | Réf. client           | varchar(8)                  |\n            | Réf. produit          | varchar(8)                  |\n        \"\"\"\n        self.assertEqual(actual.strip(), re.sub(\"(?m)^ +\", \"\", expected).strip())\n\n        # Markdown table with 3 columns in another order and a Markdown emphasis\n\n        subargs ={\n            \"**box**\": \"Entité ou association\",\n            \"type\": \"Type\",\n            \"label\": \"\", # omitted translation => default to a language-dependent one\n            \"md\": True,\n        }\n        actual = data_dict.run(source, common=common, subargs=subargs)[\"text\"]\n        expected = \"\"\"\n            | **Entité ou association** | Type                        | Libellé de l'attribut |\n            |:--------------------------|:----------------------------|:----------------------|\n            | **CLIENT**                |                             | Nom                   |\n            | **\"**                     | varchar(40)                 | Adresse               |\n            | **\"**                     | varchar(8)                  | Réf. client           |\n            | **COMMANDE**              | date                        | Date                  |\n            | **\"**                     | decimal(5,2) DEFAULT '0.00' | Montant               |\n            | **\"**                     | tinyint(4)                  | Num commande          |\n            | **INCLURE**               | tinyint(4)                  | Quantité              |\n            | **PRODUIT**               | decimal(5,2)                | Prix unitaire         |\n            | **\"**                     | varchar(20)                 | Libellé               |\n            | **\"**                     | varchar(8)                  | Réf. produit          |\n        \"\"\"\n        self.assertEqual(actual.strip(), re.sub(\"(?m)^ +\", \"\", expected).strip())\n\n        # With just one column, the table is converted to a list and the header is omitted\n\n        subargs = {\"md\": True, \"label\": \"\"}\n        actual = data_dict.run(source, common=common, subargs=subargs)[\"text\"]\n        expected = \"\"\"\n            - Adresse\n            - Date\n            - Libellé\n            - Montant\n            - Nom\n            - Num commande\n            - Prix unitaire\n            - Quantité\n            - Réf. client\n            - Réf. produit\n        \"\"\"\n        self.assertEqual(actual.strip(), re.sub(\"(?m)^ +\", \"\", expected).strip())\n\n        # By default: md,box,label,type\n\n        subargs = {\"tsv\": True}\n        actual = data_dict.run(source, common=common, subargs=subargs)[\"text\"]\n        expected = \"\"\"\n            Entité ou association\\tLibellé de l'attribut\\tType\n            CLIENT\\tAdresse\\tvarchar(40)\n            CLIENT\\tNom\\t\n            CLIENT\\tRéf. client\\tvarchar(8)\n            COMMANDE\\tDate\\tdate\n            COMMANDE\\tMontant\\tdecimal(5,2) DEFAULT '0.00'\n            COMMANDE\\tNum commande\\ttinyint(4)\n            INCLURE\\tQuantité\\ttinyint(4)\n            PRODUIT\\tLibellé\\tvarchar(20)\n            PRODUIT\\tPrix unitaire\\tdecimal(5,2)\n            PRODUIT\\tRéf. produit\\tvarchar(8)\n        \"\"\"\n        self.assertEqual(actual.strip(), re.sub(\"(?m)^ +\", \"\", expected).strip())\n\n    def test_data_dict_with_invisible_boxes(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            -Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n            -Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n            -Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n\n            DF, 0N CLIENT, 11 COMMANDE\n            COMMANDE: Num. commande, Date, Montant\n            -Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n\n            -Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n            -Binary 15_, 0N Entity 14_, 01 Entity 11_\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n            -Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\n\n            -Binary 16_, 0N Entity 14_, 1N Entity 11_\n            -Entity 11_: id 11 1, attr 11 2\n            -Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n            -Entity 9_: id 9 1, attr 9 2, attr 9 3\n        \"\"\"\n        params = {\"language\": \"fr\"}\n        common = Common(params)\n        actual = data_dict.run(source, common=common, subargs={})[\"text\"]\n        expected = \"\"\"\n            | Entité ou association | Libellé de l'attribut | Type |\n            |:----------------------|:----------------------|:-----|\n            | CLIENT                | Adresse               |      |\n            | \"                     | Nom                   |      |\n            | \"                     | Prénom                |      |\n            | \"                     | Réf. client           |      |\n            | COMMANDE              | Date                  |      |\n            | \"                     | Montant               |      |\n            | \"                     | Num. commande         |      |\n            | INCLURE               | Quantité              |      |\n            | PRODUIT               | Libellé               |      |\n            | \"                     | Prix unitaire         |      |\n            | \"                     | Réf. produit          |      |\n        \"\"\"\n        self.assertEqual(actual.strip(), re.sub(\"(?m)^ +\", \"\", expected).strip())\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_entity.py",
    "content": "import unittest\nfrom collections import defaultdict\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.entity import *\nfrom mocodo.tools.parser_tools import extract_clauses\n\ndef entity_wrapper(s, legs_to_strengthen=None, is_child=False):\n    if legs_to_strengthen is None:\n        legs_to_strengthen = []\n    e = Entity(extract_clauses(s)[0])\n    e.add_attributes(legs_to_strengthen, is_child, fk_format=None)\n    return e\n\nclass EntityTest(unittest.TestCase):\n\n    def test_default(self):\n        entities = [\n            entity_wrapper(\"PARTICIPANT: numero, nom, adresse\"),\n            entity_wrapper(\"PARTICIPANT:numero,nom,adresse\"),\n            entity_wrapper(\" PARTICIPANT: numero, nom, adresse \"),\n            entity_wrapper(\"PARTICIPANT :numero ,nom ,adresse\"),\n        ]\n        for e in entities:\n            self.assertEqual(e.bid, \"PARTICIPANT\")\n            self.assertEqual(e.name_view, \"PARTICIPANT\")\n            self.assertEqual([a.label for a in e.attributes], [\"numero\", \"nom\", \"adresse\"])\n            self.assertEqual([a.kind for a in e.attributes], [\"strong\", \"simple\", \"simple\"])\n\n    def test_datatypes(self):\n        e = entity_wrapper(\"PARTICIPANT: numero [type1], nom [type2] , adresse[type3]\")\n        self.assertEqual([a.label for a in e.attributes], [\"numero\", \"nom\", \"adresse\"])\n        self.assertEqual([a.datatype for a in e.attributes], [\"type1\", \"type2\", \"type3\"])\n        e = entity_wrapper(\"PARTICIPANT: numero [type a,b,c], nom [type2], adresse [type3]\")\n        self.assertEqual([a.datatype for a in e.attributes], [\"type a,b,c\", \"type2\", \"type3\"])\n        e = entity_wrapper(\"PARTICIPANT: numero [], nom, adresse [type3]\")\n        self.assertEqual([a.datatype for a in e.attributes], [\"\", \"\", \"type3\"])\n\n    def test_numbered_entity(self):\n        e = entity_wrapper(\"PARTICIPANT5: numero, nom, adresse\")\n        self.assertEqual(e.bid, \"PARTICIPANT5\")\n        self.assertEqual(e.name_view, \"PARTICIPANT\")\n        e = entity_wrapper(\"PARTICIPANT123: numero, nom, adresse\")\n        self.assertEqual(e.bid, \"PARTICIPANT123\")\n        self.assertEqual(e.name_view, \"PARTICIPANT12\")\n\n    def test_blank(self):\n        e = entity_wrapper(\"MOT-CLEF: mot-clé, ,\")\n        self.assertEqual([a.label for a in e.attributes], [\"mot-clé\", \"\", \"\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"strong\", \"phantom\", \"phantom\"])\n\n    def test_all_blank(self):\n        e = entity_wrapper(\"BLANK: , ,\")\n        self.assertEqual([a.label for a in e.attributes], [\"\", \"\", \"\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"phantom\", \"phantom\", \"phantom\"])\n\n    def test_no_identifier_at_first_position(self):\n        e = entity_wrapper(\"POSITION: _abscisse, ordonnee\")\n        self.assertEqual([a.label for a in e.attributes], [\"abscisse\", \"ordonnee\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"simple\", \"simple\"])\n\n    def test_no_identifier_for_children(self):\n        e = entity_wrapper(\"POSITION: abscisse, _ordonnee\", [], is_child=True)\n        self.assertEqual([a.label for a in e.attributes], [\"abscisse\", \"ordonnee\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"simple\", \"simple\"])\n\n    def test_multiple_strong_identifier(self):\n        e = entity_wrapper(\"POSITION: abscisse, _ordonnee\")\n        self.assertEqual([a.label for a in e.attributes], [\"abscisse\", \"ordonnee\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"strong\", \"strong\"])\n\n    def test_weak_identifier(self):\n        e = entity_wrapper(\"LIVRE: Num. exemplaire, Etat du livre, Date d'achat\", [\"placeholder\"])\n        self.assertEqual([a.label for a in e.attributes], [\"Num. exemplaire\", \"Etat du livre\", \"Date d'achat\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"weak\", \"simple\", \"simple\"])\n\n    def test_weak_composite_identifier(self):\n        e = entity_wrapper(\"POSITION: abscisse, _ordonnee, foobar\", [\"placeholder\"])\n        self.assertEqual([a.label for a in e.attributes], [\"abscisse\", \"ordonnee\", \"foobar\"])\n        self.assertEqual([a.kind for a in e.attributes], [\"weak\", \"weak\", \"simple\"])\n\n\nclass CandidateIdentifiersTest(unittest.TestCase):\n\n    def check(self, expected_candidates, expected_id_texts, legs_to_strengthen=None):\n        for source in self.sources:\n            entity = entity_wrapper(source, legs_to_strengthen)\n            self.assertEqual(entity.candidates, expected_candidates)\n            actual_id_texts = [a.id_text for a in entity.attributes]\n            self.assertEqual(actual_id_texts, expected_id_texts)\n\n    # Strong entities without alternate identifiers\n\n    def test_simple_id(self):\n        self.sources = [\n            \"FOOBAR: foo, bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}},\n            [\"ID\", \"\", \"\", \"\"]\n        )\n    \n    def test_no_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, bar, biz, qux\",\n            \"FOOBAR: 0_foo, bar, biz, qux\",            \n        ]\n        self.check(\n            {},\n            [\"\", \"\", \"\", \"\"]\n        )\n\n    def test_composite_id(self):\n        self.sources = [\n            \"FOOBAR: foo, _bar, biz, qux\",\n            \"FOOBAR: foo, 0_bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\", \"bar\"}},\n            [\"ID\", \"ID\", \"\", \"\"]\n        )\n    \n    def test_pushed_simple_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, _bar, biz, qux\",\n            \"FOOBAR: _foo, 0_bar, biz, qux\",\n            \"FOOBAR: 0_foo, _bar, biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\"}},\n            [\"\", \"ID\", \"\", \"\"]\n        )\n\n    def test_pushed_composite_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, _bar, _biz, qux\",\n            \"FOOBAR: _foo, _bar, 0_biz, qux\",\n            \"FOOBAR: _foo, 0_bar, _biz, qux\",\n            \"FOOBAR: _foo, 0_bar, 0_biz, qux\",\n            \"FOOBAR: 0_foo, _bar, _biz, qux\",\n            \"FOOBAR: 0_foo, _bar, 0_biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, _biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, 0_biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\", \"biz\"}},\n            [\"\", \"ID\", \"ID\", \"\"]\n        )\n\n    # Weak entities without alternate identifiers\n\n    def test_simple_weak_id(self):\n        self.sources = [\n            \"FOOBAR: foo, bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}},\n            [\"id\", \"\", \"\", \"\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n    \n    def test_no_weak_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, bar, biz, qux\",\n            \"FOOBAR: 0_foo, bar, biz, qux\",            \n        ]\n        self.check(\n            {},\n            [\"\", \"\", \"\", \"\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n\n    def test_composite_weak_id(self):\n        self.sources = [\n            \"FOOBAR: foo, _bar, biz, qux\",\n            \"FOOBAR: foo, 0_bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\", \"bar\"}},\n            [\"id\", \"id\", \"\", \"\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n    \n    def test_pushed_simple_weak_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, _bar, biz, qux\",\n            \"FOOBAR: _foo, 0_bar, biz, qux\",\n            \"FOOBAR: 0_foo, _bar, biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\"}},\n            [\"\", \"id\", \"\", \"\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n\n    def test_pushed_composite_weak_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, _bar, _biz, qux\",\n            \"FOOBAR: _foo, _bar, 0_biz, qux\",\n            \"FOOBAR: _foo, 0_bar, _biz, qux\",\n            \"FOOBAR: _foo, 0_bar, 0_biz, qux\",\n            \"FOOBAR: 0_foo, _bar, _biz, qux\",\n            \"FOOBAR: 0_foo, _bar, 0_biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, _biz, qux\",\n            \"FOOBAR: 0_foo, 0_bar, 0_biz, qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\", \"biz\"}},\n            [\"\", \"id\", \"id\", \"\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n\n    # Strong entities with alternate identifiers\n\n    def test_alt_ids_and_simple_id(self):\n        self.sources = [\n            \"FOOBAR: foo, 1_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}, \"1\": {\"bar\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"ID\", \"1\", \"1 2\", \"2\"]\n        )\n        self.sources = [\n            \"FOOBAR: 1_foo, bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}, \"1\": {\"foo\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"1 ID\", \"\", \"1 2\", \"2\"]\n        )\n    \n    def test_alt_ids_and_no_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, 1_bar, 12_biz, 2_qux\",\n            \"FOOBAR: 0_foo, 1_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"1\": {\"bar\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"\", \"1\", \"1 2\", \"2\"]\n        )\n\n    def test_alt_ids_and_composite_id(self):\n        # NB: the \"0\" prefix is mandatory since \"bar\" belongs to an alt id.\n        # Otherwise, cf. test_alt_ids_and_simple_id().\n        self.sources = [\n            \"FOOBAR: foo, 01_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\", \"bar\"}, \"1\": {\"bar\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"ID\", \"1 ID\", \"1 2\", \"2\"]\n        )\n        # When \"bar\" is not part of an alt id, the \"0\" prefix is optional.\n        self.sources = [\n            \"FOOBAR: foo, _bar, 12_biz, 2_qux\",\n            \"FOOBAR: foo, 0_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\", \"bar\"}, \"1\": {\"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"ID\", \"ID\", \"1 2\", \"2\"]\n        )\n        # When \"bar\" is not part of an alt id, the \"0\" prefix is optional.\n        self.sources = [\n            \"FOOBAR: 1_foo, 0_bar, 12_biz, 2_qux\",\n            \"FOOBAR: 1_foo, _bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\", \"bar\"}, \"1\": {\"foo\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"1 ID\", \"ID\", \"1 2\", \"2\"]\n        )\n    \n    def test_alt_ids_and_pushed_simple_id(self):\n        # NB: the \"0\" prefix on \"bar\" is mandatory since \"bar\" belongs to an alt id.\n        # Otherwise, cf. test_alt_ids_and_no_id().\n        self.sources = [\n            \"FOOBAR: _foo, 01_bar, 12_biz, 2_qux\",\n            \"FOOBAR: 0_foo, 01_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\"}, \"1\": {\"bar\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"\", \"1 ID\", \"1 2\", \"2\"]\n        )\n        # When \"bar\" is not part of an alt id, the \"0\" prefix is optional.\n        self.sources = [\n            \"FOOBAR: _foo, _bar, 12_biz, 2_qux\",\n            \"FOOBAR: 0_foo, _bar, 12_biz, 2_qux\",\n            \"FOOBAR: _foo, 0_bar, 12_biz, 2_qux\",\n            \"FOOBAR: 0_foo, 0_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\"}, \"1\": {\"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"\", \"ID\", \"1 2\", \"2\"]\n        )\n        # NB: the \"0\" prefix on \"foo\" is mandatory since \"foo\" belongs to an alt id.\n        # Otherwise, cf. test_alt_ids_and_composite_id().\n        self.sources = [\n            \"FOOBAR: 01_foo, 0_bar, 12_biz, 2_qux\",\n            \"FOOBAR: 01_foo, _bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\"}, \"1\": {\"foo\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"1\", \"ID\", \"1 2\", \"2\"]\n        )\n\n    def test_alt_ids_and_pushed_composite_id(self):\n        self.sources = [\n            \"FOOBAR: _foo, 01_bar, 02_biz, 12_qux\",\n            \"FOOBAR: 0_foo, 01_bar, 02_biz, 12_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\", \"biz\"}, \"1\": {\"bar\", \"qux\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"\", \"1 ID\", \"2 ID\", \"1 2\"]\n        )\n        self.sources = [\n            \"FOOBAR: _foo, _bar, 02_biz, 12_qux\",\n            \"FOOBAR: 0_foo, _bar, 02_biz, 12_qux\",\n            \"FOOBAR: _foo, 0_bar, 02_biz, 12_qux\",\n            \"FOOBAR: 0_foo, 0_bar, 02_biz, 12_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\", \"biz\"}, \"1\": {\"qux\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"\", \"ID\", \"2 ID\", \"1 2\"]\n        )\n        self.sources = [\n            \"FOOBAR: 02_foo, _bar, _biz, 12_qux\",\n            \"FOOBAR: 02_foo, _bar, 0_biz, 12_qux\",\n            \"FOOBAR: 02_foo, 0_bar, _biz, 12_qux\",\n            \"FOOBAR: 02_foo, 0_bar, 0_biz, 12_qux\",\n        ]\n        self.check(\n            {\"0\": {\"bar\", \"biz\"}, \"1\": {\"qux\"}, \"2\": {\"foo\", \"qux\"}},\n            [\"2\", \"ID\", \"ID\", \"1 2\"]\n        )\n\n    # Weak entities with alternate identifiers\n    # Just one test, since the logic is the same as for strong entities.\n\n    def test_alt_ids_and_simple_id(self):\n        self.sources = [\n            \"FOOBAR: foo, 1_bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}, \"1\": {\"bar\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"id\", \"1\", \"1 2\", \"2\"],\n            legs_to_strengthen =[\"placeholder\"]\n        )\n        self.sources = [\n            \"FOOBAR: 1_foo, bar, 12_biz, 2_qux\",\n        ]\n        self.check(\n            {\"0\": {\"foo\"}, \"1\": {\"foo\", \"biz\"}, \"2\": {\"biz\", \"qux\"}},\n            [\"1 id\", \"\", \"1 2\", \"2\"],\n            legs_to_strengthen = [\"placeholder\"]\n        )\n    \n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_fitness.py",
    "content": "import unittest\nfrom math import hypot\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.argument_parser import parsed_arguments\nfrom mocodo.rewrite.fitness import *\nfrom mocodo.mcd import Mcd\n\n\nclass ArrangeBB(unittest.TestCase):\n    \n    def test_optimal_layout(self):\n        source = \"\"\"\n            SCELERISQUE LOREM: blandit, elit, ligula\n            EROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue\n\n            NIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM\n            PELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(total_distances, 0.0)\n\n    def test_optimal_layout_with_reflexive_association(self):\n        source = \"\"\"\n            Assistas, 01 Hci poilu, 0N Hci poilu\n            Hci poilu: graffiti, champignon, troussa, graffiti\n            Rayonnait, 0N Hci poilu, 0N Lappa: monobloc\n\n            Brisa: souffrait\n            Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar\n            Lappa: graffiti, champignon\n            Puni, 11 Lappa, 0N Lappa\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(total_distances, 0.0)\n\n    def test_diagonal_reflexive_association(self):\n        source = \"\"\"\n            Norm : Draw, Unit, Folk, Peer, Tour, Hall\n            :\n\n            :\n            Baby, 1N Norm, 0N> Norm\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(round(total_distances, 4), 0.8284)\n\n    def test_2_0_link(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            PASSER, 0N CLIENT, 11 COMMANDE\n            :\n            COMMANDE: Num commande, Date, Montant\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(total_distances, 1.0)\n\n    def test_1_1_link(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            PASSER, 0N CLIENT, 11 COMMANDE\n            \n            COMMANDE: Num commande, Date, Montant\n            :\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(total_distances, hypot(1, 1) - 1)\n\n    def test_2_1_link(self):\n        source = \"\"\"\n            :\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            PASSER, 0N CLIENT, 11 COMMANDE\n            \n            COMMANDE: Num commande, Date, Montant\n            :\n            :\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 0)\n        self.assertEqual(total_distances, hypot(2, 1) - 1)\n\n    def test_k33(self):\n        source = \"\"\"\n            DIGNISSIM: nec sem, nunc, vulputate\n            IMPERDIET: a praesent, nibh, semper\n            TINCIDUNT: faucibus, orci, cursus\n\n            RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n            SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n            QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 9)\n\n    def test_k33_better(self):\n        source = \"\"\"\n            DIGNISSIM: nec sem, nunc, vulputate\n            RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n            IMPERDIET: a praesent, nibh, semper\n\n            SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n            TINCIDUNT: faucibus, orci, cursus\n            QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT\n        \"\"\"\n        params = parsed_arguments([])\n        mcd = Mcd(source, params)\n        params.update(mcd.get_layout_data())\n        d = mcd.get_layout_data()\n        evaluate = fitness(d[\"links\"], d[\"multiplicity\"], d[\"col_count\"], d[\"row_count\"])\n        size = d[\"col_count\"] * d[\"row_count\"]\n        (crossing_count, total_distances) = evaluate(list(range(size)))\n        self.assertEqual(crossing_count, 3)\n    \n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_grid.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.grid import Grid\n\n\nclass GridTests(unittest.TestCase):\n    \n    def test_constructor(self):\n        grid = Grid(16)\n        assert grid == [None, (1, 1), (2, 1), (3, 1), (2, 2), (3, 2), (3, 2), (3, 3), (3, 3), (3, 3), (4, 3), (4, 3), (4, 3), (5, 3), (5, 3), (5, 3), (4, 4)]\n    \n    def test_nth_next(self):\n        grid = Grid(16)\n        assert grid[3] == (3, 1)\n        assert grid.get_nth_next(3, 0) == (3, 1)\n        assert grid.get_nth_next(3, 1) == (2, 2)\n        assert grid.get_nth_next(3, 2) == (3, 2)\n        assert grid.get_nth_next(3, 3) == (3, 3)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_guess_title.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.guess_title import guess_title\n\nclass TestDumps(unittest.TestCase):\n\n    def test_guess_title(self):\n        # The central entity is the most referenced one\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            PASSER, 0N CLIENT, 11 COMMANDE\n            COMMANDE: Num commande, Date, Montant\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n        \"\"\"\n        actual = guess_title(source, \"fr\")\n        self.assertEqual(actual, \"Commandes\")\n        # A more intricate case\n        source = \"\"\"\n            AYANT-DROIT: nom ayant-droit, lien\n            DIRIGER, 0N EMPLOYÉ, 01 PROJET\n            REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\n            PIÈCE: réf. pièce, libellé pièce\n            COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\n            DF, _11 AYANT-DROIT, 0N EMPLOYÉ\n            EMPLOYÉ: matricule, nom employé\n            PROJET: num. projet, nom projet\n            FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\n            DÉPARTEMENT: num. département, nom département\n            EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\n            TRAVAILLER, 0N EMPLOYÉ, 1N PROJET\n            SOCIÉTÉ: num. société, raison sociale\n            CONTRÔLER, 0N< [filiale] SOCIÉTÉ, 01 [mère] SOCIÉTÉ\n        \"\"\"\n        actual = guess_title(source, \"fr\")\n        self.assertEqual(actual, \"Employés\")\n        # A case showing that the numeric suffix is ignored\n        source = \"\"\"\n            Egestas: vivamus, semper, aliquam\n            Lorem1: ipsum\n            Pharetra, 0N Curabitur, 0N Lorem1, 0N Vitae justo: massa\n            Vitae justo: lobortis, purus\n\n            Ultricies, 11 Rhoncus, 0N Egestas\n            Imperdiet, 0N Egestas, 0N Curabitur, 0N Lorem1\n            Curabitur: blandit, suscipit\n            adipiscing, 0N Curabitur, 0N Vitae justo, 0N Lorem2\n\n            Rhoncus: dolor a, bibendum, euismod, consectetuer, leo\n            Porttitor, 1N Rhoncus, 0N Lorem2\n            Lorem2: dolor\n        \"\"\"\n        actual = guess_title(source, \"fr\")\n        self.assertEqual(actual, \"Lorems\")\n        # When the most referenced entity is a date,\n        # the second most referenced entity is chosen.\n        source = source.replace(\"Lorem\", \"Date\")\n        actual = guess_title(source, \"fr\")\n        self.assertEqual(actual, \"Curabiturs\")\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_inheritance.py",
    "content": "import gettext\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.inheritance import *\nfrom mocodo.tools.parser_tools import extract_clauses\n\n\ngettext.NullTranslations().install()\n\ndef inheritance_wrapper(s, **kargs):\n    return Inheritance(extract_clauses(s)[0], **kargs)\n\nclass parse_test(unittest.TestCase):\n    \n    def test_backslash_conservation(self):\n        a = inheritance_wrapper(r\"/XT\\ FOO => BAR\")\n        self.assertTrue(a.bid.startswith(\"FOO_PARENT\"))\n        self.assertEqual(a.name_view, \"XT\")\n        self.assertEqual(a.legs[0].entity_bid, \"FOO\")\n        self.assertEqual(a.legs[1].entity_bid, \"BAR\")\n        self.assertEqual(a.kind, \"=>\")\n\n    def test_numbered_inheritance(self):\n        a = inheritance_wrapper(r\"/XT1\\ FOO => BAR\")\n        self.assertTrue(a.bid.startswith(\"FOO_PARENT\"))\n        self.assertEqual(a.name_view, \"XT\")\n        self.assertEqual(a.legs[0].entity_bid, \"FOO\")\n        self.assertEqual(a.legs[1].entity_bid, \"BAR\")\n        self.assertEqual(a.kind, \"=>\")\n        a = inheritance_wrapper(r\"/1\\ FOO => BAR\")\n        self.assertTrue(a.bid.startswith(\"FOO_PARENT\"))\n        self.assertEqual(a.name_view, \"\")\n        self.assertEqual(a.legs[0].entity_bid, \"FOO\")\n        self.assertEqual(a.legs[1].entity_bid, \"BAR\")\n        self.assertEqual(a.kind, \"=>\")\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_mcd.py",
    "content": "import gettext\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.argument_parser import parsed_arguments\nfrom mocodo.mcd import *\n\n\ngettext.NullTranslations().install()\n\nparams = parsed_arguments([])\n\nclass McdTest(unittest.TestCase):\n\n    def test_entity_recognition(self):\n        clauses = [\n            \"PROJET: num. projet, nom projet, budget projet\",\n            \"PROJET ABC: num. projet, nom projet, budget projet\",\n            \"PROJET CDE:\",\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), **params)\n        self.assertEqual(mcd.box_count, len(clauses))\n        for box in mcd.boxes:\n            self.assertEqual(box.kind, \"entity\")\n\n    def test_association_recognition(self):\n        entities = [\"FONCTION:\", \"DEPARTEMENT:\", \"EMPLOYE:\", \"PERSONNE:\",\n                    \"ETUDIANT:\", \"DATE:\", \"CLIENT:\", \"COMMANDE:\", \"BANDIT:\", \"EMPLOYE_ABC:\"]\n        associations = [\n            \"ASSUMER, 1N EMPLOYÉ, 1N FONCTION: date début, date fin\",\n            \"DIRIGER, 11 DÉPARTEMENT, 01 EMPLOYÉ\",\n            \"ENGENDRER, 0N [Parent] PERSONNE, 1N [Enfant] PERSONNE\",\n            \"SOUTENIR, XX ÉTUDIANT, XX DATE: note stage\",\n            \"DF, 0N CLIENT, 11 COMMANDE\",\n            \"ÊTRE AMI, 0N BANDIT, 0N BANDIT\",\n            \"ASSURER2, 1N EMPLOYÉ ABC, 1N FONCTION: date début, date fin\",\n        ]\n        clauses = entities + associations\n        mcd = Mcd(\"\\n\".join(clauses), **params)\n        self.assertEqual(mcd.box_count, len(clauses))\n        for box in mcd.boxes:\n            if box.bid + \":\" in entities:\n                self.assertEqual(box.kind, \"entity\")\n            else:\n                self.assertIn(box.kind, [\"association\", \"df\"])\n\n    def test_constraint_recognition(self):\n        clauses = [\n            \"Lorem: lorem, ipsum\",\n            \"Ipsum, XX Lorem, XX Dolor\",\n            \"Dolor: dolor, sit\",\n            \"Sit, XX Dolor, XX Amet\",\n            \"Amet: consectetur, adipiscing\",\n            \"(A) --Lorem, ..Ipsum, Dolor: 30, 90\",\n            \"(B) ->Dolor, <-->Sit, -->Amet: 69, 90\",\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), **params)\n        self.assertEqual(mcd.box_count, len(clauses) - 2)\n        self.assertEqual(len(mcd.constraints), 2)\n        for constraint in mcd.constraints:\n            self.assertEqual(constraint.kind, \"constraint\")\n\n\n    def test_rows(self):\n        source = \"\"\"\n            BARATTE: piston, racloir, fusil\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            TINET: fendoir, grattoir\n            CROCHET: égrenoir, _gorgeoir, bouillie\n\n            DF, 11 BARATTE, 1N ROULEAU\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            PORTE, 11 CROCHET, 0N CROCHET\n\n            ROULEAU: tribulum\n            HERSE, 1N FLÉAU, 1N FLÉAU\n\n            FLÉAU: battadère, van, mesure\n        \"\"\"\n        mcd = Mcd(source, **params)\n        self.assertEqual([element.bid for element in mcd.rows[0]], [\"BARATTE\", \"MARTEAU\", \"TINET\", \"CROCHET\"])\n        self.assertEqual([element.bid for element in mcd.rows[1]], [\"DF0\", \"BALANCE\", \"BANNETON\", \"PORTE\"])\n        self.assertEqual([element.bid for element in mcd.rows[2]], ['PHANTOM_#1', 'ROULEAU', 'HERSE', 'PHANTOM_#2'])\n        self.assertEqual([element.bid for element in mcd.rows[3]], ['PHANTOM_#3', 'FLEAU', 'PHANTOM_#4', 'PHANTOM_#5'])\n\n    def test_layout(self):\n        clauses = [\n            \"BARATTE: piston, racloir, fusil\",\n            \"MARTEAU, 0N BARATTE, 11 TINET: ciseaux\",\n            \"TINET: fendoir, grattoir\",\n            \"CROCHET: égrenoir, _gorgeoir, bouillie\",\n            \"\",\n            \"DF, 11 BARATTE, 1N ROULEAU\",\n            \"BALANCE, 0N ROULEAU, 0N TINET: charrue\",\n            \"BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\",\n            \"PORTE, 11 CROCHET, 0N CROCHET\",\n            \"\",\n            \"ROULEAU: tribulum\",\n            \"HERSE, 1N FLÉAU, 1N FLÉAU\",\n            \"\",\n            \"FLÉAU: battadère, van, mesure\",\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), **params)\n        self.assertEqual(mcd.get_layout(), list(range(16)))\n        self.assertEqual(mcd.get_layout_data(), {\n            'col_count': 4,\n            'row_count': 4,\n            'links': (\n                (0, 1), # from BARATTE to MARTEAU\n                (0, 4), # from BARATTE to DF\n                (1, 2),\n                (2, 5),\n                (2, 6),\n                (3, 6),\n                (3, 7),\n                (4, 9),\n                (5, 9),\n                (6, 13),\n                (10, 13)\n            ),\n            'multiplicity': {\n                (0, 1): 1,\n                (0, 4): 1,\n                (1, 0): 1,\n                (1, 2): 1,\n                (2, 1): 1,\n                (2, 5): 1,\n                (2, 6): 1,\n                (3, 6): 1,\n                (3, 7): 2, # 2 links between CROCHET and PORTE\n                (4, 0): 1,\n                (4, 9): 1,\n                (5, 2): 1,\n                (5, 9): 1,\n                (6, 2): 1,\n                (6, 3): 1,\n                (6, 13): 1,\n                (7, 3): 2, # 2 links between PORTE and CROCHET\n                (9, 4): 1,\n                (9, 5): 1,\n                (10, 13): 2,\n                (13, 6): 1,\n                (13, 10): 2\n            },\n            'successors': [\n                {1, 4}, # BARATTE has MARTEAU and DF as successors\n                {0, 2},\n                {1, 5, 6},\n                {6, 7},\n                {0, 9},\n                {2, 9},\n                {2, 3, 13},\n                {3}, # reflexive association PORTE: no multiple edges\n                set(), # phantom\n                {4, 5},\n                {13},\n                set(),\n                set(),\n                {6, 10},\n                set(),\n                set()]\n            }\n        )\n        expected = \"\"\"\n            BARATTE: piston, racloir, fusil\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            TINET: fendoir, grattoir\n            CROCHET: égrenoir, _gorgeoir, bouillie\n\n            DF, 11 BARATTE, 1N ROULEAU\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            PORTE, 11 CROCHET, 0N CROCHET\n\n            :\n            ROULEAU: tribulum\n            HERSE, 1N FLÉAU, 1N FLÉAU\n            :\n\n            :\n            FLÉAU: battadère, van, mesure\n            :\n            :\n        \"\"\".strip().replace(\"  \", \"\")\n        mcd.set_layout(list(range(16)))\n        self.assertEqual(mcd.get_clauses(), expected)\n\n\n    def test_input_errors(self):\n        clauses = [\n            \"PROJET: num. projet, nom projet, budget projet\",\n            \"ASSUMER, 1N PROJET, 1N INDIVIDU\",\n        ]\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.1\", Mcd, \"\\n\".join(clauses), params)\n\n    def test_duplicate_errors(self):\n        clauses = [\n            \"DF, 11 BARATTE, 1N ROULEAU\",\n            \"BARATTE: piston, racloir, fusil\",\n            \"TINET: fendoir, grattoir\",\n            \"BALANCE, 0N ROULEAU, 0N TINET: charrue\",\n            \"BARATTE: tribulum\",\n        ]\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.6\", Mcd, \"\\n\".join(clauses), params)\n        clauses = [\n            \"BARATTE, 11 BARATTE, 1N ROULEAU\",\n            \"BARATTE: piston, racloir, fusil\",\n            \"TINET: fendoir, grattoir\",\n            \"BALANCE, 0N ROULEAU, 0N TINET: charrue\",\n            \"ROULEAU: tribulum\",\n        ]\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.8\", Mcd, \"\\n\".join(clauses), params)\n        clauses = [\n            \"BARATTE: piston, racloir, fusil\",\n            \"BARATTE, 11 BARATTE, 1N ROULEAU\",\n            \"TINET: fendoir, grattoir\",\n            \"BALANCE, 0N ROULEAU, 0N TINET: charrue\",\n            \"ROULEAU: tribulum\",\n        ]\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.8\", Mcd, \"\\n\".join(clauses), params)\n\n    def test_constraint_errors(self):\n        clauses = [\n            \"Lorem: lorem, ipsum\",\n            \"Ipsum, XX Lorem, XX Lorem\",\n            \"(A) --Lorem, ..Ipsum, Dolor: 30, 90\",\n        ]\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.40\", Mcd, \"\\n\".join(clauses), params)\n\n    def test_flip(self):\n        source = \"\"\"\n            % The comments are placed before\n            BARATTE: piston, racloir, fusil\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            TINET: fendoir, grattoir\n            CROCHET: égrenoir, _gorgeoir, bouillie\n\n            % ... the first line of the file\n            DF, 11 BARATTE, 1N ROULEAU\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            PORTE, 11 CROCHET, 0N CROCHET\n\n            ROULEAU: tribulum\n            HERSE, 1N FLÉAU, 1N FLÉAU\n\n            FLÉAU: battadère, van, mesure\n        \"\"\"\n        mcd = Mcd(source, **params)\n        expected = \"\"\"\n            % The comments are placed before\n            % ... the first line of the file\n            \n            :\n            FLÉAU: battadère, van, mesure\n            :\n            :\n\n            :\n            ROULEAU: tribulum\n            HERSE, 1N FLÉAU, 1N FLÉAU\n            :\n\n            DF, 11 BARATTE, 1N ROULEAU\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            PORTE, 11 CROCHET, 0N CROCHET\n\n            BARATTE: piston, racloir, fusil\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            TINET: fendoir, grattoir\n            CROCHET: égrenoir, _gorgeoir, bouillie\n        \"\"\".replace(\"    \", \"\").strip()\n        actual = mcd.get_vertically_flipped_clauses().replace(\"    \", \"\").strip()\n        self.assertEqual(actual, expected)\n        expected = \"\"\"\n            % The comments are placed before\n            % ... the first line of the file\n            \n            CROCHET: égrenoir, _gorgeoir, bouillie\n            TINET: fendoir, grattoir\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            BARATTE: piston, racloir, fusil\n\n            PORTE, 11 CROCHET, 0N CROCHET\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            DF, 11 BARATTE, 1N ROULEAU\n\n            :\n            HERSE, 1N FLÉAU, 1N FLÉAU\n            ROULEAU: tribulum\n            :\n\n            :\n            :\n            FLÉAU: battadère, van, mesure\n            :\n        \"\"\".strip().replace(\"  \", \"\")\n        actual = mcd.get_horizontally_flipped_clauses().replace(\"    \", \"\").strip()\n        self.assertEqual(actual, expected)\n        expected = \"\"\"\n            % The comments are placed before\n            % ... the first line of the file\n            \n            BARATTE: piston, racloir, fusil\n            DF, 11 BARATTE, 1N ROULEAU\n            :\n            :\n\n            MARTEAU, 0N BARATTE, 11 TINET: ciseaux\n            BALANCE, 0N ROULEAU, 0N TINET: charrue\n            ROULEAU: tribulum\n            FLÉAU: battadère, van, mesure\n\n            TINET: fendoir, grattoir\n            BANNETON, 01 CROCHET, 11 FLÉAU, 1N TINET: pulvérisateur\n            HERSE, 1N FLÉAU, 1N FLÉAU\n            :\n\n            CROCHET: égrenoir, _gorgeoir, bouillie\n            PORTE, 11 CROCHET, 0N CROCHET\n            :\n            :\n        \"\"\".strip().replace(\"  \", \"\")\n        actual = mcd.get_diagonally_flipped_clauses().replace(\"    \", \"\").strip()\n        self.assertEqual(actual, expected)\n\n    def test_explicit_fit(self):\n        # initially: (5, 4) for 11 nodes\n        source = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour, \n\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n            Pack, 1N Folk, 1N Seem \n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n            Flip : Gold, Ride\n\n            Call: Ride, Soon\n            Gear , 1N Call, 1N Folk\n        \"\"\"\n        mcd = Mcd(source, **params)\n        # minimal fit: (4, 3)\n        expected = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour,\n\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n            Pack, 1N Folk, 1N Seem\n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n\n            Flip : Gold, Ride\n            Call: Ride, Soon\n            Gear , 1N Call, 1N Folk\n            :\n        \"\"\".strip().replace(\"    \", \"\")\n        actual = mcd.get_refitted_clauses(0).strip().replace(\"    \", \"\")\n        self.assertEqual(actual, expected)\n        # 1st next fit: (5, 3)\n        expected = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour,\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n\n            Pack, 1N Folk, 1N Seem\n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n            Flip : Gold, Ride\n            Call: Ride, Soon\n\n            Gear , 1N Call, 1N Folk\n            :\n            :\n            :\n            :\n        \"\"\".strip().replace(\"    \", \"\")\n        actual = mcd.get_refitted_clauses(1).strip().replace(\"    \", \"\")\n        self.assertEqual(actual, expected)\n        # 2nd next fit: (4, 4)\n        expected = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour,\n\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n            Pack, 1N Folk, 1N Seem\n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n\n            Flip : Gold, Ride\n            Call: Ride, Soon\n            Gear , 1N Call, 1N Folk\n            :\n\n            :\n            :\n            :\n            :\n        \"\"\".strip().replace(\"    \", \"\")\n        actual = mcd.get_refitted_clauses(2).strip().replace(\"    \", \"\")\n        self.assertEqual(actual, expected)\n        \n    def test_implicit_fit_produces_min_grid_next(self):\n        # initially: (4, 5) for 11 nodes\n        source = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour, \n\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n\n            Pack, 1N Folk, 1N Seem\n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n            Flip : Gold, Ride\n\n            Call: Ride, Soon\n            Gear , 1N Call, 1N Folk\n        \"\"\"\n        mcd = Mcd(source, **params)\n        # (4, 5) not being a preferred grid, it is equivalent to nth_fit == 1\n        expected = \"\"\"\n            Item: Norm, Wash, Haul\n            Milk, 0N Item, 0N Draw\n            Draw: Lady, Face, Soon, Dish, Ever\n            Unit, 1N Draw, 11 Folk: Peer, Tour,\n            Folk: Hall, Fold, Baby, Bind, Gene, Aids, Free\n\n            Pack, 1N Folk, 1N Seem\n            Seem: Teen, Amid\n            Disk, 0N Flip, 1N Seem\n            Flip : Gold, Ride\n            Call: Ride, Soon\n\n            Gear , 1N Call, 1N Folk\n            :\n            :\n            :\n            :\n        \"\"\".strip().replace(\"  \", \"\")\n        actual = mcd.get_refitted_clauses(1).strip().replace(\"    \", \"\")\n        self.assertEqual(actual, expected)\n    \n    def test_no_overlapping(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            PASSER, 0N CLIENT, 11 COMMANDE\n            COMMANDE: Num commande, Date, Montant\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n        \"\"\".replace(\"    \", \"\")\n        mcd = Mcd(source, **params)\n        self.assertEqual(mcd.get_overlaps(), [])\n    \n    def test_no_overlapping_with_reflexive_associations(self):\n        source = \"\"\"\n            :\n            :\n                A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n            :\n\n            :\n            DF, 0N ESPÈCE, _11 ANIMAL\n            ANIMAL: nom, sexe, date naissance, date décès\n                A PÈRE, 0N ANIMAL, 0N> [père présumé] ANIMAL\n\n                PEUT COHABITER AVEC, 0N ESPÈCE, 0N [commensale] ESPÈCE: nb. max. commensaux\n            ESPÈCE: code espèce, libellé\n                OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\n                PÉRIODE: date début, _date fin\n\n            :\n            PEUT VIVRE DANS, 1N ESPÈCE, 1N ENCLOS: nb. max. congénères\n            ENCLOS: num. enclos\n            :       \n        \"\"\".replace(\"    \", \"\")\n        mcd = Mcd(source, **params)\n        self.assertEqual(mcd.get_overlaps(), [])\n    \n    def test_horizontal_legs_overlap(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n            COMMANDE: Num commande, Date, Montant\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n            PASSER, 0N CLIENT, 11 COMMANDE\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n        \"\"\".replace(\n            \"  \", \"\"\n        )\n        mcd = Mcd(source, **params)\n        self.assertEqual(\n            mcd.get_overlaps(),\n            [\n                (\"PASSER\", \"CLIENT\", \"COMMANDE\", \"COMMANDE\"),\n                (\"PASSER\", \"COMMANDE\", \"INCLURE\", \"COMMANDE\"),\n                (\"INCLURE\", \"COMMANDE\", \"PRODUIT\", \"PRODUIT\"),\n                (\"INCLURE\", \"PRODUIT\", \"PASSER\", \"PASSER\"),\n            ],\n        )\n\n    def test_vertical_legs_overlap(self):\n        source = \"\"\"\n            CLIENT: Réf. client, Nom, Prénom, Adresse\\n\n            COMMANDE: Num commande, Date, Montant\\n\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\\n\n            PASSER, 0N CLIENT, 11 COMMANDE\\n\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n        \"\"\"\n        mcd = Mcd(source, **params)\n        self.assertEqual(\n            mcd.get_overlaps(),\n            [\n                (\"PASSER\", \"CLIENT\", \"COMMANDE\", \"COMMANDE\"),\n                (\"PASSER\", \"COMMANDE\", \"INCLURE\", \"COMMANDE\"),\n                (\"INCLURE\", \"COMMANDE\", \"PRODUIT\", \"PRODUIT\"),\n                (\"INCLURE\", \"PRODUIT\", \"PASSER\", \"PASSER\"),\n            ],\n        )\n\n    def test_leg_overlaps_entity(self):\n        source = \"\"\"\n            COMMANDE: Num commande, Date, Montant\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n            PASSER, 0N CLIENT, 11 COMMANDE\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n\n            :\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n            :::\n        \"\"\"\n        mcd = Mcd(source, **params)\n        self.assertEqual(\n            mcd.get_overlaps(),\n            [('PASSER', 'COMMANDE', 'PRODUIT', 'PRODUIT')],\n        )\n\n    def test_leg_overlaps_association(self):\n        source = \"\"\"\n            PRODUIT: Réf. produit, Libellé, Prix unitaire\n\n            COMMANDE: Num commande, Date, Montant\n            PASSER, 0N CLIENT, 11 COMMANDE\n            CLIENT: Réf. client, Nom, Prénom, Adresse\n\n            INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n        \"\"\"\n        mcd = Mcd(source, **params)\n        self.assertEqual(\n            mcd.get_overlaps(),\n            [('INCLURE', 'PRODUIT', 'PASSER', 'PASSER')],\n        )\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_mcd_dimensions.py",
    "content": "import gettext\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.argument_parser import parsed_arguments\nfrom mocodo.mcd import *\n\ngettext.NullTranslations().install()\n\nparams = parsed_arguments([])\n\nstyle = {\n    \"cartouche_text_height_ratio\" : 0.85,\n    \"card_text_height_ratio\"      : 0.85,\n    \"df_text_height_ratio\"        : 1.1,\n    \"attribute_text_height_ratio\" : 0.65,\n    \"line_skip_height\"            : 0,\n    \"card_baseline\"               : 3,\n    \"card_underline_skip_height\"  : -2,\n    \"underline_skip_height\"       : -3,\n    \"underline_depth\"             : 1,\n    \"card_underline_depth\"        : 1,\n    \"dash_width\"                  : 4,\n    \"margin\"                 : 9,\n    \"box_stroke_depth\"            : 1.5,\n    \"inner_stroke_depth\"          : 1.5,\n    \"rect_margin_width\"           : 8,\n    \"rect_margin_height\"          : 6,\n    \"round_rect_margin_width\"     : 7,\n    \"round_rect_margin_height\"    : 5,\n    \"round_corner_radius\"         : 14,\n    \"leg_stroke_depth\"            : 1,\n    \"card_margin\"                 : 5,\n    \"arrow_width\"                 : 12,\n    \"arrow_half_height\"           : 6,\n    \"arrow_axis\"                  : 8,\n    \"note_overlay_height\"   : 40,\n    \"note_baseline\"         : 24,\n    \"entity_cartouche_font\"       : None,\n    \"association_cartouche_font\"  : None,\n    \"entity_attribute_font\"       : None,\n    \"association_attribute_font\"  : None,\n    \"card_font\"                   : None,\n    \"label_font\"                  : None,\n    \"note_font\"             : None\n}\n\ndef stub_for_get_font_metrics(s):\n    stub_for_get_font_metrics.get_pixel_width = lambda s: 5 * len(s)\n    stub_for_get_font_metrics.get_pixel_height = lambda: 10\n    return stub_for_get_font_metrics\n\ndef get_dimensions(mcd, verbose=False):\n    mcd.calculate_size(style)\n    result = []\n    log = [\"[\"]\n    for box in mcd.boxes:\n        log.append(\"{'bid': %s, \" % repr(box.bid))\n        d = {\"bid\": box.bid}\n        for key in \"xywh\":\n            d[key] = getattr(box, key)\n            log.append(\"'%s': %s, \" % (key, d[key]))\n        log[-1] = log[-1][:-2]\n        log.append(\"},\\n\")\n        result.append(d)\n    log[-1] = log[-1][:-2]\n    log.append(\"]\")\n    if verbose:\n        print(\"\".join(log))\n    return result\n\nclass McdGeometryTest(unittest.TestCase):\n\n    def test_simplest_mcd(self):\n        clauses = [\n            \"My entity: first, second\",\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), stub_for_get_font_metrics, **params)\n        self.assertEqual(get_dimensions(mcd), [{'bid': 'MY_ENTITY', 'x': 9, 'y': 9, 'w': 62, 'h': 54}])\n    \n    def test_read_me_mcd(self):\n        clauses = [\n            \"DF, 11 Élève, 1N Classe\",\n            \"Classe: Num. classe, Num. salle\",\n            \"Faire Cours, 1N Classe, 1N Prof: Vol. horaire\",\n            \"Catégorie: Code catégorie, Nom catégorie\",\n            \"\",\n            \"Élève: Num. élève, Nom élève\",\n            \"Noter, 1N Élève, 0N Prof, 0N Matière, 1N Date: Note\",\n            \"Prof: Num. prof, Nom prof\",\n            \"Relever, 0N Catégorie, 11 Prof\",\n            \"\",\n            \"Date: Date\",\n            \"Matière: Libellé matière\",\n            \"Enseigner, 11 Prof, 1N Matière\",\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), stub_for_get_font_metrics, **params)\n        self.assertEqual(get_dimensions(mcd), [\n            {'bid': 'DF0', 'x': 30, 'y': 24, 'w': 24, 'h': 24},\n            {'bid': 'CLASSE', 'x': 95, 'y': 9, 'w': 72, 'h': 54},\n            {'bid': 'FAIRE_COURS', 'x': 195, 'y': 15, 'w': 74, 'h': 42},\n            {'bid': 'CATEGORIE', 'x': 294, 'y': 9, 'w': 86, 'h': 54},\n            {'bid': 'ELEVE', 'x': 9, 'y': 83, 'w': 66, 'h': 54},\n            {'bid': 'NOTER', 'x': 111, 'y': 89, 'w': 40, 'h': 42},\n            {'bid': 'PROF', 'x': 201, 'y': 83, 'w': 62, 'h': 54},\n            {'bid': 'RELEVER', 'x': 312, 'y': 89, 'w': 50, 'h': 42},\n            {'bid': 'DATE', 'x': 24, 'y': 157, 'w': 36, 'h': 44},\n            {'bid': 'MATIERE', 'x': 85, 'y': 157, 'w': 92, 'h': 44},\n            {'bid': 'ENSEIGNER', 'x': 202, 'y': 158, 'w': 60, 'h': 42},\n            {'bid': 'PHANTOM_#1', 'x': 337, 'y': 179, 'w': 0, 'h': 0}\n        ])\n    \n    def test_mocodo_online_mcd(self):\n        clauses = [\n            \"PEUT VIVRE DANS, 1N ESPÈCE, 1N ENCLOS: nb. max. congénères\",\n            \"ENCLOS: num. enclos\",\n            \"OCCUPE, 1N ANIMAL, 1N PÉRIODE, 1N ENCLOS\",\n            \"PÉRIODE: date début, _date fin\",\n            \"\",\n            \"ESPÈCE: code espèce, libellé\",\n            \"DF, 0N ESPÈCE, _11 ANIMAL\",\n            \"ANIMAL: nom, sexe, date naissance, date décès\",\n            \"A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\",\n            \"\",\n            \"PEUT COHABITER AVEC, 0N ESPÈCE, 0N [commensale] ESPÈCE: nb. max. commensaux\",\n            \":\",\n            \"A PÈRE, 0N ANIMAL, 0N> [père présumé] ANIMAL\",\n            \"-INVISIBLE:\"\n        ]\n        mcd = Mcd(\"\\n\".join(clauses), stub_for_get_font_metrics, **params)\n        self.assertEqual(get_dimensions(mcd), [\n            {'bid': 'PEUT_VIVRE_DANS', 'x': 9, 'y': 15, 'w': 110, 'h': 42},\n            {'bid': 'ENCLOS', 'x': 144, 'y': 14, 'w': 72, 'h': 44},\n            {'bid': 'OCCUPE', 'x': 241, 'y': 15, 'w': 44, 'h': 42},\n            {'bid': 'PERIODE', 'x': 320, 'y': 9, 'w': 66, 'h': 54},\n            {'bid': 'ESPECE', 'x': 28, 'y': 93, 'w': 72, 'h': 54},\n            {'bid': 'DF0', 'x': 168, 'y': 108, 'w': 24, 'h': 24},\n            {'bid': 'ANIMAL', 'x': 220, 'y': 83, 'w': 86, 'h': 74},\n            {'bid': 'A_MERE', 'x': 331, 'y': 99, 'w': 44, 'h': 42},\n            {'bid': 'PEUT_COHABITER_AVEC', 'x': 9, 'y': 177, 'w': 110, 'h': 42},\n            {'bid': 'PHANTOM_#1', 'x': 180, 'y': 198, 'w': 0, 'h': 0},\n            {'bid': 'A_PERE', 'x': 241, 'y': 177, 'w': 44, 'h': 42},\n            {'bid': 'INVISIBLE', 'x': 353, 'y': 198, 'w': 0, 'h': 0}\n        ])\n    \nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_parser_tools.py",
    "content": "from pathlib import Path\nimport re\nimport gettext\nimport unittest\nimport pprint\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.parse_mcd import Lark_StandAlone, UnexpectedToken\nfrom mocodo.tools.parser_tools import reconstruct_source, parse_source, extract_clauses\nfrom mocodo.mocodo_error import MocodoError\n\ngettext.NullTranslations().install()\n\nparser = Lark_StandAlone()\n\nvalid_lines = r\"\"\"\n:\n:::\n:  :  :\n   :  :  :\n   % commented\n% commented %\n  % foo\\\\ , %  foo  /TX\\\\\nAYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\nCONTRÔLER, 0N< [filiale] SOCIÉTÉ, 01 [mère] SOCIÉTÉ\nDF, 0N> CLIENT, 11 COMMANDE\nGRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction\nPeut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin\nEngendre, 0N< Personne, 22> Personne\nAgent 0070: bar\nDF4, 11 Agent 0070, 1N Agent1\nAgent1: bar\nDF, _11 ŒUVRE, _11 EXEMPLAIRE\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\nLIGULA, 0N LACUS, /1N EROS, 0N TELLUS, 0N CONSEQUAT: metus\nRéserver: _Durée\n+LIGULA, 01 LACUS, 1N EROS: metus\n-LIGULA, 01 LACUS, 1N EROS: metus\nPASSER, 0N [Un client peut passer un nombre quelconque de commandes.] CLIENT, 11 [Toute commande est passée par un en un seul client.] COMMANDE\nINCLURE, 1N [Une commande peut inclure plusieurs produits distincts, et en inclut au moins un.] COMMANDE, 0N [Certains produits ne sont jamais commandés, d'autres le sont plusieurs fois.] PRODUIT: Quantité\nCLIENT: \nCLIENT: ,          ,,\nCOMMANDE: ,               ,\nPRODUIT: ,            , \nMEAN: wash, rest, king,\nHERE, 0N NICE, 0N MEAN: wood, much, , stop\nNICE: _poke, news, , lawn\nUnit, 1N Draw, 11 Folk: Peer, Tour, \nPASSER, XX CLIENT, XX COMMANDE\nINCLURE, XX COMMANDE, XX PRODUIT: \nŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\nEXEMPLAIRE2: 1, bon état, 12/6/1975\nEXEMPLAIRE3: 2, bon état, 1/8/1977\nEXEMPLAIRE4: 3, reliure rongée, 3/4/2005\nDF, -1N ŒUVRE, -_11 EXEMPLAIRE1\n+Prof: Num. prof, Nom prof\n-Prof: Num. prof, Nom prof\nEnseignant: num. ens. [numéro identifiant un enseignant], nom ens. [nom enseignant], tél. ens. [téléphone enseignant]\nCOMMANDE: Num commande, Date, Montant, #Réf. client>CLIENT>Réf. client\nCOMMANDE: Num commande, Date, Montant, #Réf. client > CLIENT > Réf. client\nINCLURE: #Num commande>COMMANDE>Num commande, _#Réf. produit>PRODUIT>Réf. produit, Quantité\nINCLURE: #Num commande > COMMANDE > Num commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\nCLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse [varchar(40)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]\nPARTICIPANT: numero [], nom, adresse [type3]\nCOMMANDE: Num commande, Date, Montant, #Réf. client!>CLIENT>Réf. client\nCOMMANDE: Num commande, Date, Montant, Réf. client!\nL33T, 0N> H4X0R, 0N< H4X0R\nL33T123, 0N> H4X0R12, 0N< H4X0R0\n   AYANT-DROIT: nom ayant-droit, lien\n   DIRIGER, 0N EMPLOYÉ, 01 PROJET\n   REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nDIRIGER, EMPLOYÉ, PROJET\nA, B, C\nFoo, Bar\nDIRIGER, EMPLOYÉ, PROJET: biz, buz\nA, B, C: biz, buz\nFoo, Bar: biz, buz\nAYANT-DROIT   :   nom ayant-droit   ,   lien   \nDIRIGER   ,    0N    EMPLOYÉ   ,    01    PROJET   : fizz,  buzz   \nAYANT-DROIT  :  nom ayant-droit  ,  lien  \nDIRIGER  ,  0N  EMPLOYÉ  ,  01  PROJET  : fizz, buzz  \nAYANT-DROIT\t :\t nom ayant-droit\t ,\t lien\t \nDIRIGER\t ,\t\t0N\t\tEMPLOYÉ\t ,\t\t01\t\tPROJET\t : fizz,\tbuzz\t \n() [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n(III) [bla bla.]\n(IV) \n(])\n(+)\n(/)\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n(III) [bla bla.]: 12.5, 30\n(IV) : 12.5, 30\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, 30\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, BAR\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, BAR\n(IV) : 12.5, 30\n(A) --Lorem, .....Ipsum, -Dolor: 30, 10\n(B) ->Dolor, <-->Sit, -->Amet: 69, 10\n(XX) ->foo, -->foo, -> foo, --> foo\n(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer\n/XT\\ Personne ==> Homme, Femme: sexe\n/XT1\\\\ Personne <= Homme, Femme: sexe\n/XT\\\\ Personne => Homme, Femme: sexe\n/T\\\\ Personne <= Homme, Femme: sexe\n/T\\\\ Personne => Homme, Femme: sexe\n/X\\\\ Personne <= Homme, Femme: sexe\n/X\\\\ Personne => Homme, Femme: sexe\n/\\\\ Personne <= Homme, Femme: sexe\n/\\\\ Personne => Homme, Femme: sexe\n/1\\\\ FOO => BAR\n/T\\\\foo==>foo11\nÉtudiant: num, 1_nom, 1_prénom, adresse, 2_mail\nÉtudiant: 0_num, 1_nom, 1_prénom, adresse, 2_mail\nPosition: 0_latitude, 0_longitude, altitude\nFoo: bar, 1_baz, 21_qux, 123_quux\nRéserver, 1N Client, 0N Chambre: _date, durée\n\"\"\".splitlines()\n\nline = \"-\" * 80\npath = Path(\"test/test_parser_tools_snapshot.txt\")\nwith path.open(mode=\"w\") as file:\n    for source in valid_lines:\n        file.write(f\"{line}\\n{source}\\n\")\n        tree = parse_source(source).pretty()\n        file.write(f\"{line}{tree}\".strip())\n        file.write(f\"\\n{line}\\n\")\n        clauses = extract_clauses(source)\n        output = pprint.pformat(clauses, sort_dicts=False)\n        file.write(f\"{output}\\n\\n\")\n\ndef fuzzer(seed=0):\n    import random\n    random.seed(seed)\n    for _ in range(50):\n        (left, right) = random.sample(valid_lines, 2)\n        source = f\"{left[:random.randint(0, len(left))]}{right[random.randint(0, len(right)):]}\"\n        try:\n            tree = parse_source(source)\n            print(source)\n        except Exception as error:\n            print(source)\n            print(error)\n        input()\n\n# fuzzer(4)\n\nmocodo_errors = [\n    *[(501, c) for c in \"0123456789!#$&')*,.;<=>?@[\\\\]^_`{|}~\"],\n    *[(501, f\" {c}\") for c in \"0123456789!#$&')*,.;<=>?@[\\\\]^_`{|}~\"],\n    (501, \": foobar\"),\n    (501, \" : foobar\"),\n    (502, \"AYANT-: nom ay, lien\"),\n    (502, \"FOO, 0N Bar, 1N Biz [bla]\"),\n    (502, \"FOO, 0N Bar, 1N Biz [bla], 0N Buz\"),\n    (502, \" foo /TX\\\\#  ]  #/ \"),\n    (502, \"BACK\\\\SLASH:\"),\n    (502, \" foo_11<11_ ]<-->]foo\"),\n    (503, \"FOOBAR\"),\n    (503, \"  FOOBAR>\"),\n    (503, \"  FOOBAR    >\"),\n    (503, \"  FOOBAR+\"),\n    (505, \"/T\\\\, foobar\"),\n    (506, \"DIRIGER, 0 EMPLOYÉ, 01 PROJET\"),\n    (506, \"DIRIGER, 0 EMPLOYÉ, 01 PROJET: biz, buz\"),\n    (506, \"DIRIGER, 0NV\"),\n    (507, \"/ANYTHING\\\\ Personne => Homme, Femme: sexe\"),\n    (507, \"/X12\\\\ Personne => Homme, Femme: sexe\"),\n    (507, \"/1N\\\\\"),\n    (508, \"(I) : 1, 2, 3\"),\n    (508, \"(I) : 1, 2,\"),\n    (509, \"DIRIGER,\"),\n    (509, \"DIRIGER,    \"),\n    (510, \"(I) : \"),\n    (510, \"(I) ->Foo ..Bar : \"),\n    (510, \"(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, \"),\n    (510, \"(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOOBAR, \"),\n    (510, \"(A) : Ipsum, --Lorem: 30, 90\"),\n    (511, \" +\"),\n    (511, \"   +#   \"),\n    (511, \"/T\\\\ \\\\.. ,\\\\foo\"),\n    (511, \"+..==>\"),\n    (511, \" /TX\\\\ foo -> .bar\"),\n    (512, \"PARTICIPANT: numero [, nom, adresse\"),\n    (514, \"(IIII)\"),\n    (514, \"(    )\"),\n    (514, \"(    )\"),\n    (515, \"(A) --Lorem, >Ipsum: 30, 90\"),\n    (515, \"(A) --Lorem, : Ipsum: 30, 90\"),\n    (515, \"(A) --Lorem 30, 90\"),\n    (516, \"(A) >Ipsum, --Lorem: 30, 90\"),\n    (516, \"())\"),\n    (516, \"((I))\"),\n    (517, \"/TX\\\\ foo bar \"),\n    (518, \"COMMANDE: Num commande, Date, Montant, #Réf. client->CLIENT->Réf. client\"),\n    (518, \"INCLURE: #Num commande->COMMANDE->Num commande, _#Réf. produit->PRODUIT->Réf. produit, Quantité\"),\n    (519, \"(A) ->Ipsum ->Lorem: 30, 90\"),\n    (500, \"FOOBAR: foo, /bar\"),\n    (500, \"FOO, 1N Bar: -->Amet\"),\n    (521, \"FOOBAR: foo>bar, biz\"),\n    (522, \"FOO: #bar, biz\"),\n    (522, \"FOO: #bar!, biz\"),\n    (522, \"FOO: #bar\"),\n    (522, \"FOO: #bar!\"),\n    (522, \"FOO: biz, #bar\"),\n    (522, \"FOO: #bar>buzz, biz\"),\n    (522, \"FOO: #bar>buzz!, biz\"),\n    (522, \"FOO: #bar!>buzz, biz\"),\n    (522, \"FOO: #bar>buzz\"),\n    (522, \"FOO: biz, #bar>buzz\"),\n    (523, \"FOO: #bar>buzz>, biz\"),\n    (523, \"FOO: #bar>buzz>\"),\n    (523, \"FOO: biz, #bar>buzz>  \"),\n    (524, \"DIRIGER, 0N EMPLOYÉ > PRODUIT, Quantité\"),\n    (525, \"(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5\"),\n    (526, \"(A) ->Ipsum, ->Lorem: 30, 9N\"),\n    (527, \"(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 3,14 3,14\"),\n    (528, \"FOO: bar!?, biz\"),\n]\n\nclass MocodoErrorTest(unittest.TestCase):\n    def test_mocodo_errors(self):\n        for n, source in mocodo_errors:\n            try:\n                parse_source(source)\n            except MocodoError as e:\n                actual_error_number = re.search(r\"\\d+\", str(e)).group()\n                assert actual_error_number == str(n), f\"Expected error {n} for:\\n{source}\"\n            except Exception as e:\n                print(source)\n                pin = e.get_context(source)\n                print(f\"{line}\\n{source}\\n{line}\\n{pin}\")\n                if isinstance(e, UnexpectedToken):\n                    print(f'Unexpected token \"{repr(e.token)}\" at line {e.line}, column {e.column}.')\n                    print(f\"Expected: {set(e.expected)}.\\n\")\n                assert False\n            else:\n                assert False, f\"\\n\\nExpected Mocodo Error {n} for:\\n{source}\"\n\n\nclass TestReconstructSource(unittest.TestCase):\n    def test_reconstruct_source(self):\n        for source in valid_lines:\n            if not source:\n                continue\n            tree = parse_source(source)\n            new_source = reconstruct_source(tree)\n            self.assertEqual(source.strip(), new_source.strip())\n\n    def test_alignment(self):\n        source = \"\"\"\n            AYANT-DROIT: nom ayant-droit, lien\n            DIRIGER, 0N EMPLOYÉ, 01 PROJET\n            \n            \n            REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\n            ::\n\n            % comment\n            \n            PIÈCE: réf. pièce, libellé pièce\n\n              (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET        \n        \"\"\"\n        clauses = extract_clauses(source)\n        for raw_line, clause in zip(source.splitlines(), clauses):\n            self.assertEqual(clause[\"source\"].lstrip(), raw_line.lstrip())\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_parser_tools_snapshot.txt",
    "content": "--------------------------------------------------------------------------------\n\n--------------------------------------------------------------------------------start\n  break_\n--------------------------------------------------------------------------------\n[{'type': 'break'}]\n\n--------------------------------------------------------------------------------\n:\n--------------------------------------------------------------------------------start\n  line\n    phantoms\t:\n--------------------------------------------------------------------------------\n[{'type': 'phantoms', 'count': 1, 'indent': '', 'source': ':'}]\n\n--------------------------------------------------------------------------------\n:::\n--------------------------------------------------------------------------------start\n  line\n    phantoms\t:::\n--------------------------------------------------------------------------------\n[{'type': 'phantoms', 'count': 3, 'indent': '', 'source': ':::'}]\n\n--------------------------------------------------------------------------------\n:  :  :\n--------------------------------------------------------------------------------start\n  line\n    phantoms\t:  :  :\n--------------------------------------------------------------------------------\n[{'type': 'phantoms', 'count': 3, 'indent': '', 'source': ':  :  :'}]\n\n--------------------------------------------------------------------------------\n   :  :  :\n--------------------------------------------------------------------------------start\n  line\n    indent\t   \n    phantoms\t:  :  :\n--------------------------------------------------------------------------------\n[{'type': 'phantoms', 'indent': '  ', 'count': 3, 'source': '  :  :  :'}]\n\n--------------------------------------------------------------------------------\n   % commented\n--------------------------------------------------------------------------------start\n  line\n    indent\t   \n    comment\n      %\n       commented\n--------------------------------------------------------------------------------\n[{'type': 'comment',\n  'indent': '  ',\n  'text': '% commented',\n  'source': '  % commented'}]\n\n--------------------------------------------------------------------------------\n% commented %\n--------------------------------------------------------------------------------start\n  line\n    comment\n      %\n       commented %\n--------------------------------------------------------------------------------\n[{'type': 'comment',\n  'text': '% commented %',\n  'indent': '',\n  'source': '% commented %'}]\n\n--------------------------------------------------------------------------------\n  % foo\\\\ , %  foo  /TX\\\\\n--------------------------------------------------------------------------------start\n  line\n    indent\t  \n    comment\n      %\n       foo\\\\ , %  foo  /TX\\\\\n--------------------------------------------------------------------------------\n[{'type': 'comment',\n  'indent': '  ',\n  'text': '% foo\\\\\\\\ , %  foo  /TX\\\\\\\\',\n  'source': '  % foo\\\\\\\\ , %  foo  /TX\\\\\\\\'}]\n\n--------------------------------------------------------------------------------\nAYANT-DROIT: nom ayant-droit, lien\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAYANT-DROIT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnom ayant-droit\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tlien\n--------------------------------------------------------------------------------\n[{'name': 'AYANT-DROIT',\n  'attrs': [{'attribute_label': 'nom ayant-droit', 'rank': 0},\n            {'attribute_label': 'lien', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'AYANT-DROIT: nom ayant-droit, lien'}]\n\n--------------------------------------------------------------------------------\nDIRIGER, 0N EMPLOYÉ, 01 PROJET\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n      , \n      seq\n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tEMPLOYÉ\n        , \n        assoc_leg\n          card\t01\n           \n          entity_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 0},\n           {'card': '01', 'entity': 'PROJET', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER, 0N EMPLOYÉ, 01 PROJET'}]\n\n--------------------------------------------------------------------------------\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tREQUÉRIR\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tPROJET\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tPIÈCE\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tqté requise\n--------------------------------------------------------------------------------\n[{'name': 'REQUÉRIR',\n  'legs': [{'card': '1N', 'entity': 'PROJET', 'rank': 0},\n           {'card': '0N', 'entity': 'PIÈCE', 'rank': 1}],\n  'attrs': [{'attribute_label': 'qté requise', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise'}]\n\n--------------------------------------------------------------------------------\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tCOMPOSER\n      , \n      seq\n        assoc_leg\n          card\t0N\n           [\n          leg_note\tcomposée\n          ] \n          entity_name_ref\n            box_name\tPIÈCE\n        , \n        assoc_leg\n          card\t0N\n           [\n          leg_note\tcomposante\n          ] \n          entity_name_ref\n            box_name\tPIÈCE\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tquantité\n--------------------------------------------------------------------------------\n[{'name': 'COMPOSER',\n  'legs': [{'card': '0N', 'leg_note': 'composée', 'entity': 'PIÈCE', 'rank': 0},\n           {'card': '0N',\n            'leg_note': 'composante',\n            'entity': 'PIÈCE',\n            'rank': 1}],\n  'attrs': [{'attribute_label': 'quantité', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité'}]\n\n--------------------------------------------------------------------------------\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDF\n      , \n      seq\n        assoc_leg\n          card_prefix\t_\n          card\t11\n           \n          entity_name_ref\n            box_name\tAYANT-DROIT\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tEMPLOYÉ\n--------------------------------------------------------------------------------\n[{'name': 'DF',\n  'legs': [{'card_prefix': '_',\n            'card': '11',\n            'entity': 'AYANT-DROIT',\n            'rank': 0},\n           {'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DF, _11 AYANT-DROIT, 0N EMPLOYÉ'}]\n\n--------------------------------------------------------------------------------\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tFOURNIR\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tPROJET\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tPIÈCE\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tSOCIÉTÉ\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tqté fournie\n--------------------------------------------------------------------------------\n[{'name': 'FOURNIR',\n  'legs': [{'card': '1N', 'entity': 'PROJET', 'rank': 0},\n           {'card': '1N', 'entity': 'PIÈCE', 'rank': 1},\n           {'card': '1N', 'entity': 'SOCIÉTÉ', 'rank': 2}],\n  'attrs': [{'attribute_label': 'qté fournie', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie'}]\n\n--------------------------------------------------------------------------------\nCONTRÔLER, 0N< [filiale] SOCIÉTÉ, 01 [mère] SOCIÉTÉ\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tCONTRÔLER\n      , \n      seq\n        assoc_leg\n          card\t0N\n          leg_arrow\t<\n           [\n          leg_note\tfiliale\n          ] \n          entity_name_ref\n            box_name\tSOCIÉTÉ\n        , \n        assoc_leg\n          card\t01\n           [\n          leg_note\tmère\n          ] \n          entity_name_ref\n            box_name\tSOCIÉTÉ\n--------------------------------------------------------------------------------\n[{'name': 'CONTRÔLER',\n  'legs': [{'card': '0N',\n            'leg_arrow': '<',\n            'leg_note': 'filiale',\n            'entity': 'SOCIÉTÉ',\n            'rank': 0},\n           {'card': '01', 'leg_note': 'mère', 'entity': 'SOCIÉTÉ', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'CONTRÔLER, 0N< [filiale] SOCIÉTÉ, 01 [mère] SOCIÉTÉ'}]\n\n--------------------------------------------------------------------------------\nDF, 0N> CLIENT, 11 COMMANDE\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDF\n      , \n      seq\n        assoc_leg\n          card\t0N\n          leg_arrow\t>\n           \n          entity_name_ref\n            box_name\tCLIENT\n        , \n        assoc_leg\n          card\t11\n           \n          entity_name_ref\n            box_name\tCOMMANDE\n--------------------------------------------------------------------------------\n[{'name': 'DF',\n  'legs': [{'card': '0N', 'leg_arrow': '>', 'entity': 'CLIENT', 'rank': 0},\n           {'card': '11', 'entity': 'COMMANDE', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DF, 0N> CLIENT, 11 COMMANDE'}]\n\n--------------------------------------------------------------------------------\nGRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tGRATTE-CIEL\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tlatitude\n        , \n        entity_or_table_attr\n          id_mark\t_\n          typed_attr\n            attr\tlongitude\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tnom\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\thauteur\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tannée de construction\n--------------------------------------------------------------------------------\n[{'name': 'GRATTE-CIEL',\n  'attrs': [{'attribute_label': 'latitude', 'rank': 0},\n            {'id_mark': '_', 'attribute_label': 'longitude', 'rank': 1},\n            {'attribute_label': 'nom', 'rank': 2},\n            {'attribute_label': 'hauteur', 'rank': 3},\n            {'attribute_label': 'année de construction', 'rank': 4}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'GRATTE-CIEL: latitude, _longitude, nom, hauteur, année de '\n            'construction'}]\n\n--------------------------------------------------------------------------------\nPeut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tPeut recevoir\n      , \n      seq\n        assoc_leg\n          card\t1N\n          leg_arrow\t>\n           \n          entity_name_ref\n            box_name\tGroupe sanguin\n        , \n        assoc_leg\n          card\t1N\n          leg_arrow\t<\n           \n          entity_name_ref\n            box_name\tGroupe sanguin\n--------------------------------------------------------------------------------\n[{'name': 'Peut recevoir',\n  'legs': [{'card': '1N',\n            'leg_arrow': '>',\n            'entity': 'Groupe sanguin',\n            'rank': 0},\n           {'card': '1N',\n            'leg_arrow': '<',\n            'entity': 'Groupe sanguin',\n            'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Peut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin'}]\n\n--------------------------------------------------------------------------------\nEngendre, 0N< Personne, 22> Personne\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tEngendre\n      , \n      seq\n        assoc_leg\n          card\t0N\n          leg_arrow\t<\n           \n          entity_name_ref\n            box_name\tPersonne\n        , \n        assoc_leg\n          card\t22\n          leg_arrow\t>\n           \n          entity_name_ref\n            box_name\tPersonne\n--------------------------------------------------------------------------------\n[{'name': 'Engendre',\n  'legs': [{'card': '0N', 'leg_arrow': '<', 'entity': 'Personne', 'rank': 0},\n           {'card': '22', 'leg_arrow': '>', 'entity': 'Personne', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Engendre, 0N< Personne, 22> Personne'}]\n\n--------------------------------------------------------------------------------\nAgent 0070: bar\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAgent 0070\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tbar\n--------------------------------------------------------------------------------\n[{'name': 'Agent 0070',\n  'attrs': [{'attribute_label': 'bar', 'rank': 0}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Agent 0070: bar'}]\n\n--------------------------------------------------------------------------------\nDF4, 11 Agent 0070, 1N Agent1\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDF4\n      , \n      seq\n        assoc_leg\n          card\t11\n           \n          entity_name_ref\n            box_name\tAgent 0070\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tAgent1\n--------------------------------------------------------------------------------\n[{'name': 'DF4',\n  'legs': [{'card': '11', 'entity': 'Agent 0070', 'rank': 0},\n           {'card': '1N', 'entity': 'Agent1', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DF4, 11 Agent 0070, 1N Agent1'}]\n\n--------------------------------------------------------------------------------\nAgent1: bar\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAgent1\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tbar\n--------------------------------------------------------------------------------\n[{'name': 'Agent1',\n  'attrs': [{'attribute_label': 'bar', 'rank': 0}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Agent1: bar'}]\n\n--------------------------------------------------------------------------------\nDF, _11 ŒUVRE, _11 EXEMPLAIRE\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDF\n      , \n      seq\n        assoc_leg\n          card_prefix\t_\n          card\t11\n           \n          entity_name_ref\n            box_name\tŒUVRE\n        , \n        assoc_leg\n          card_prefix\t_\n          card\t11\n           \n          entity_name_ref\n            box_name\tEXEMPLAIRE\n--------------------------------------------------------------------------------\n[{'name': 'DF',\n  'legs': [{'card_prefix': '_', 'card': '11', 'entity': 'ŒUVRE', 'rank': 0},\n           {'card_prefix': '_',\n            'card': '11',\n            'entity': 'EXEMPLAIRE',\n            'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DF, _11 ŒUVRE, _11 EXEMPLAIRE'}]\n\n--------------------------------------------------------------------------------\nRéserver, /1N Client, 1N Chambre, 0N Date: Durée\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tRéserver\n      , \n      seq\n        assoc_leg\n          card_prefix\t/\n          card\t1N\n           \n          entity_name_ref\n            box_name\tClient\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tChambre\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tDate\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tDurée\n--------------------------------------------------------------------------------\n[{'name': 'Réserver',\n  'legs': [{'card_prefix': '/', 'card': '1N', 'entity': 'Client', 'rank': 0},\n           {'card': '1N', 'entity': 'Chambre', 'rank': 1},\n           {'card': '0N', 'entity': 'Date', 'rank': 2}],\n  'attrs': [{'attribute_label': 'Durée', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Réserver, /1N Client, 1N Chambre, 0N Date: Durée'}]\n\n--------------------------------------------------------------------------------\nLIGULA, 0N LACUS, /1N EROS, 0N TELLUS, 0N CONSEQUAT: metus\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tLIGULA\n      , \n      seq\n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tLACUS\n        , \n        assoc_leg\n          card_prefix\t/\n          card\t1N\n           \n          entity_name_ref\n            box_name\tEROS\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tTELLUS\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tCONSEQUAT\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tmetus\n--------------------------------------------------------------------------------\n[{'name': 'LIGULA',\n  'legs': [{'card': '0N', 'entity': 'LACUS', 'rank': 0},\n           {'card_prefix': '/', 'card': '1N', 'entity': 'EROS', 'rank': 1},\n           {'card': '0N', 'entity': 'TELLUS', 'rank': 2},\n           {'card': '0N', 'entity': 'CONSEQUAT', 'rank': 3}],\n  'attrs': [{'attribute_label': 'metus', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'LIGULA, 0N LACUS, /1N EROS, 0N TELLUS, 0N CONSEQUAT: metus'}]\n\n--------------------------------------------------------------------------------\nRéserver: _Durée\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tRéserver\n      : \n      seq\n        entity_or_table_attr\n          id_mark\t_\n          typed_attr\n            attr\tDurée\n--------------------------------------------------------------------------------\n[{'name': 'Réserver',\n  'attrs': [{'id_mark': '_', 'attribute_label': 'Durée', 'rank': 0}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Réserver: _Durée'}]\n\n--------------------------------------------------------------------------------\n+LIGULA, 01 LACUS, 1N EROS: metus\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      box_def_prefix\t+\n      assoc_name_def\n        box_name\tLIGULA\n      , \n      seq\n        assoc_leg\n          card\t01\n           \n          entity_name_ref\n            box_name\tLACUS\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tEROS\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tmetus\n--------------------------------------------------------------------------------\n[{'box_def_prefix': '+',\n  'name': 'LIGULA',\n  'legs': [{'card': '01', 'entity': 'LACUS', 'rank': 0},\n           {'card': '1N', 'entity': 'EROS', 'rank': 1}],\n  'attrs': [{'attribute_label': 'metus', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': '+LIGULA, 01 LACUS, 1N EROS: metus'}]\n\n--------------------------------------------------------------------------------\n-LIGULA, 01 LACUS, 1N EROS: metus\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      box_def_prefix\t-\n      assoc_name_def\n        box_name\tLIGULA\n      , \n      seq\n        assoc_leg\n          card\t01\n           \n          entity_name_ref\n            box_name\tLACUS\n        , \n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tEROS\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tmetus\n--------------------------------------------------------------------------------\n[{'box_def_prefix': '-',\n  'name': 'LIGULA',\n  'legs': [{'card': '01', 'entity': 'LACUS', 'rank': 0},\n           {'card': '1N', 'entity': 'EROS', 'rank': 1}],\n  'attrs': [{'attribute_label': 'metus', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': '-LIGULA, 01 LACUS, 1N EROS: metus'}]\n\n--------------------------------------------------------------------------------\nPASSER, 0N [Un client peut passer un nombre quelconque de commandes.] CLIENT, 11 [Toute commande est passée par un en un seul client.] COMMANDE\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tPASSER\n      , \n      seq\n        assoc_leg\n          card\t0N\n           [\n          leg_note\tUn client peut passer un nombre quelconque de commandes.\n          ] \n          entity_name_ref\n            box_name\tCLIENT\n        , \n        assoc_leg\n          card\t11\n           [\n          leg_note\tToute commande est passée par un en un seul client.\n          ] \n          entity_name_ref\n            box_name\tCOMMANDE\n--------------------------------------------------------------------------------\n[{'name': 'PASSER',\n  'legs': [{'card': '0N',\n            'leg_note': 'Un client peut passer un nombre quelconque de '\n                        'commandes.',\n            'entity': 'CLIENT',\n            'rank': 0},\n           {'card': '11',\n            'leg_note': 'Toute commande est passée par un en un seul client.',\n            'entity': 'COMMANDE',\n            'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'PASSER, 0N [Un client peut passer un nombre quelconque de '\n            'commandes.] CLIENT, 11 [Toute commande est passée par un en un '\n            'seul client.] COMMANDE'}]\n\n--------------------------------------------------------------------------------\nINCLURE, 1N [Une commande peut inclure plusieurs produits distincts, et en inclut au moins un.] COMMANDE, 0N [Certains produits ne sont jamais commandés, d'autres le sont plusieurs fois.] PRODUIT: Quantité\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tINCLURE\n      , \n      seq\n        assoc_leg\n          card\t1N\n           [\n          leg_note\tUne commande peut inclure plusieurs produits distincts, et en inclut au moins un.\n          ] \n          entity_name_ref\n            box_name\tCOMMANDE\n        , \n        assoc_leg\n          card\t0N\n           [\n          leg_note\tCertains produits ne sont jamais commandés, d'autres le sont plusieurs fois.\n          ] \n          entity_name_ref\n            box_name\tPRODUIT\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tQuantité\n--------------------------------------------------------------------------------\n[{'name': 'INCLURE',\n  'legs': [{'card': '1N',\n            'leg_note': 'Une commande peut inclure plusieurs produits '\n                        'distincts, et en inclut au moins un.',\n            'entity': 'COMMANDE',\n            'rank': 0},\n           {'card': '0N',\n            'leg_note': \"Certains produits ne sont jamais commandés, d'autres \"\n                        'le sont plusieurs fois.',\n            'entity': 'PRODUIT',\n            'rank': 1}],\n  'attrs': [{'attribute_label': 'Quantité', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'INCLURE, 1N [Une commande peut inclure plusieurs produits '\n            'distincts, et en inclut au moins un.] COMMANDE, 0N [Certains '\n            \"produits ne sont jamais commandés, d'autres le sont plusieurs \"\n            'fois.] PRODUIT: Quantité'}]\n\n--------------------------------------------------------------------------------\nCLIENT: \n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCLIENT\n      :\n--------------------------------------------------------------------------------\n[{'name': 'CLIENT', 'type': 'entity', 'indent': '', 'source': 'CLIENT: '}]\n\n--------------------------------------------------------------------------------\nCLIENT: ,          ,,\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCLIENT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n        ,          \n        entity_or_table_attr\n          typed_attr\n        ,\n        entity_or_table_attr\n          typed_attr\n        ,\n        entity_or_table_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'CLIENT',\n  'attrs': [{'rank': 0}, {'rank': 1}, {'rank': 2}, {'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'CLIENT: ,          ,,'}]\n\n--------------------------------------------------------------------------------\nCOMMANDE: ,               ,\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCOMMANDE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n        ,               \n        entity_or_table_attr\n          typed_attr\n        ,\n        entity_or_table_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'COMMANDE',\n  'attrs': [{'rank': 0}, {'rank': 1}, {'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'COMMANDE: ,               ,'}]\n\n--------------------------------------------------------------------------------\nPRODUIT: ,            , \n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tPRODUIT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n        ,            \n        entity_or_table_attr\n          typed_attr\n        , \n        entity_or_table_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'PRODUIT',\n  'attrs': [{'rank': 0}, {'rank': 1}, {'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'PRODUIT: ,            , '}]\n\n--------------------------------------------------------------------------------\nMEAN: wash, rest, king,\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tMEAN\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\twash\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\trest\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tking\n        ,\n        entity_or_table_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'MEAN',\n  'attrs': [{'attribute_label': 'wash', 'rank': 0},\n            {'attribute_label': 'rest', 'rank': 1},\n            {'attribute_label': 'king', 'rank': 2},\n            {'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'MEAN: wash, rest, king,'}]\n\n--------------------------------------------------------------------------------\nHERE, 0N NICE, 0N MEAN: wood, much, , stop\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tHERE\n      , \n      seq\n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tNICE\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tMEAN\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\twood\n        , \n        assoc_attr\n          typed_attr\n            attr\tmuch\n        , \n        assoc_attr\n          typed_attr\n        , \n        assoc_attr\n          typed_attr\n            attr\tstop\n--------------------------------------------------------------------------------\n[{'name': 'HERE',\n  'legs': [{'card': '0N', 'entity': 'NICE', 'rank': 0},\n           {'card': '0N', 'entity': 'MEAN', 'rank': 1}],\n  'attrs': [{'attribute_label': 'wood', 'rank': 0},\n            {'attribute_label': 'much', 'rank': 1},\n            {'rank': 2},\n            {'attribute_label': 'stop', 'rank': 3}],\n  'type': 'association',\n  'indent': '',\n  'source': 'HERE, 0N NICE, 0N MEAN: wood, much, , stop'}]\n\n--------------------------------------------------------------------------------\nNICE: _poke, news, , lawn\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tNICE\n      : \n      seq\n        entity_or_table_attr\n          id_mark\t_\n          typed_attr\n            attr\tpoke\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tnews\n        , \n        entity_or_table_attr\n          typed_attr\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tlawn\n--------------------------------------------------------------------------------\n[{'name': 'NICE',\n  'attrs': [{'id_mark': '_', 'attribute_label': 'poke', 'rank': 0},\n            {'attribute_label': 'news', 'rank': 1},\n            {'rank': 2},\n            {'attribute_label': 'lawn', 'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'NICE: _poke, news, , lawn'}]\n\n--------------------------------------------------------------------------------\nUnit, 1N Draw, 11 Folk: Peer, Tour, \n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tUnit\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tDraw\n        , \n        assoc_leg\n          card\t11\n           \n          entity_name_ref\n            box_name\tFolk\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tPeer\n        , \n        assoc_attr\n          typed_attr\n            attr\tTour\n        , \n        assoc_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'Unit',\n  'legs': [{'card': '1N', 'entity': 'Draw', 'rank': 0},\n           {'card': '11', 'entity': 'Folk', 'rank': 1}],\n  'attrs': [{'attribute_label': 'Peer', 'rank': 0},\n            {'attribute_label': 'Tour', 'rank': 1},\n            {'rank': 2}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Unit, 1N Draw, 11 Folk: Peer, Tour, '}]\n\n--------------------------------------------------------------------------------\nPASSER, XX CLIENT, XX COMMANDE\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tPASSER\n      , \n      seq\n        assoc_leg\n          card\tXX\n           \n          entity_name_ref\n            box_name\tCLIENT\n        , \n        assoc_leg\n          card\tXX\n           \n          entity_name_ref\n            box_name\tCOMMANDE\n--------------------------------------------------------------------------------\n[{'name': 'PASSER',\n  'legs': [{'card': 'XX', 'entity': 'CLIENT', 'rank': 0},\n           {'card': 'XX', 'entity': 'COMMANDE', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'PASSER, XX CLIENT, XX COMMANDE'}]\n\n--------------------------------------------------------------------------------\nINCLURE, XX COMMANDE, XX PRODUIT: \n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tINCLURE\n      , \n      seq\n        assoc_leg\n          card\tXX\n           \n          entity_name_ref\n            box_name\tCOMMANDE\n        , \n        assoc_leg\n          card\tXX\n           \n          entity_name_ref\n            box_name\tPRODUIT\n      : \n      seq\n        assoc_attr\n          typed_attr\n--------------------------------------------------------------------------------\n[{'name': 'INCLURE',\n  'legs': [{'card': 'XX', 'entity': 'COMMANDE', 'rank': 0},\n           {'card': 'XX', 'entity': 'PRODUIT', 'rank': 1}],\n  'attrs': [{'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'INCLURE, XX COMMANDE, XX PRODUIT: '}]\n\n--------------------------------------------------------------------------------\nŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tŒUVRE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\t612.NAT.34\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tJ'apprends à lire à mes souris blanches\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tmai 1975\n--------------------------------------------------------------------------------\n[{'name': 'ŒUVRE',\n  'attrs': [{'attribute_label': '612.NAT.34', 'rank': 0},\n            {'attribute_label': \"J'apprends à lire à mes souris blanches\",\n             'rank': 1},\n            {'attribute_label': 'mai 1975', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': \"ŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai \"\n            '1975'}]\n\n--------------------------------------------------------------------------------\nEXEMPLAIRE2: 1, bon état, 12/6/1975\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tEXEMPLAIRE2\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\t1\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tbon état\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\t12/6/1975\n--------------------------------------------------------------------------------\n[{'name': 'EXEMPLAIRE2',\n  'attrs': [{'attribute_label': '1', 'rank': 0},\n            {'attribute_label': 'bon état', 'rank': 1},\n            {'attribute_label': '12/6/1975', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'EXEMPLAIRE2: 1, bon état, 12/6/1975'}]\n\n--------------------------------------------------------------------------------\nEXEMPLAIRE3: 2, bon état, 1/8/1977\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tEXEMPLAIRE3\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\t2\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tbon état\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\t1/8/1977\n--------------------------------------------------------------------------------\n[{'name': 'EXEMPLAIRE3',\n  'attrs': [{'attribute_label': '2', 'rank': 0},\n            {'attribute_label': 'bon état', 'rank': 1},\n            {'attribute_label': '1/8/1977', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'EXEMPLAIRE3: 2, bon état, 1/8/1977'}]\n\n--------------------------------------------------------------------------------\nEXEMPLAIRE4: 3, reliure rongée, 3/4/2005\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tEXEMPLAIRE4\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\t3\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\treliure rongée\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\t3/4/2005\n--------------------------------------------------------------------------------\n[{'name': 'EXEMPLAIRE4',\n  'attrs': [{'attribute_label': '3', 'rank': 0},\n            {'attribute_label': 'reliure rongée', 'rank': 1},\n            {'attribute_label': '3/4/2005', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'EXEMPLAIRE4: 3, reliure rongée, 3/4/2005'}]\n\n--------------------------------------------------------------------------------\nDF, -1N ŒUVRE, -_11 EXEMPLAIRE1\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDF\n      , \n      seq\n        assoc_leg\n          card_hidden\t-\n          card\t1N\n           \n          entity_name_ref\n            box_name\tŒUVRE\n        , \n        assoc_leg\n          card_hidden\t-\n          card_prefix\t_\n          card\t11\n           \n          entity_name_ref\n            box_name\tEXEMPLAIRE1\n--------------------------------------------------------------------------------\n[{'name': 'DF',\n  'legs': [{'card_hidden': '-', 'card': '1N', 'entity': 'ŒUVRE', 'rank': 0},\n           {'card_hidden': '-',\n            'card_prefix': '_',\n            'card': '11',\n            'entity': 'EXEMPLAIRE1',\n            'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DF, -1N ŒUVRE, -_11 EXEMPLAIRE1'}]\n\n--------------------------------------------------------------------------------\n+Prof: Num. prof, Nom prof\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      box_def_prefix\t+\n      entity_name_def\n        box_name\tProf\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum. prof\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tNom prof\n--------------------------------------------------------------------------------\n[{'box_def_prefix': '+',\n  'name': 'Prof',\n  'attrs': [{'attribute_label': 'Num. prof', 'rank': 0},\n            {'attribute_label': 'Nom prof', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': '+Prof: Num. prof, Nom prof'}]\n\n--------------------------------------------------------------------------------\n-Prof: Num. prof, Nom prof\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      box_def_prefix\t-\n      entity_name_def\n        box_name\tProf\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum. prof\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tNom prof\n--------------------------------------------------------------------------------\n[{'box_def_prefix': '-',\n  'name': 'Prof',\n  'attrs': [{'attribute_label': 'Num. prof', 'rank': 0},\n            {'attribute_label': 'Nom prof', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': '-Prof: Num. prof, Nom prof'}]\n\n--------------------------------------------------------------------------------\nEnseignant: num. ens. [numéro identifiant un enseignant], nom ens. [nom enseignant], tél. ens. [téléphone enseignant]\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tEnseignant\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnum. ens.\n             [\n            datatype\tnuméro identifiant un enseignant\n            ]\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tnom ens.\n             [\n            datatype\tnom enseignant\n            ]\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\ttél. ens.\n             [\n            datatype\ttéléphone enseignant\n            ]\n--------------------------------------------------------------------------------\n[{'name': 'Enseignant',\n  'attrs': [{'attribute_label': 'num. ens.',\n             'datatype': 'numéro identifiant un enseignant',\n             'rank': 0},\n            {'attribute_label': 'nom ens.',\n             'datatype': 'nom enseignant',\n             'rank': 1},\n            {'attribute_label': 'tél. ens.',\n             'datatype': 'téléphone enseignant',\n             'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Enseignant: num. ens. [numéro identifiant un enseignant], nom '\n            'ens. [nom enseignant], tél. ens. [téléphone enseignant]'}]\n\n--------------------------------------------------------------------------------\nCOMMANDE: Num commande, Date, Montant, #Réf. client>CLIENT>Réf. client\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCOMMANDE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum commande\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tDate\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tMontant\n        , \n        entity_or_table_attr\n          #\n          foreign_reference\n            this_table_attr\n              attr\tRéf. client\n            >\n            that_table\n              entity_name_ref\n                box_name\tCLIENT\n            >\n            that_table_attr\n              attr\tRéf. client\n--------------------------------------------------------------------------------\n[{'name': 'COMMANDE',\n  'attrs': [{'attribute_label': 'Num commande', 'rank': 0},\n            {'attribute_label': 'Date', 'rank': 1},\n            {'attribute_label': 'Montant', 'rank': 2},\n            {'attribute_label': 'Réf. client',\n             'that_table': 'CLIENT',\n             'that_table_attribute_label': 'Réf. client',\n             'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'COMMANDE: Num commande, Date, Montant, #Réf. client>CLIENT>Réf. '\n            'client'}]\n\n--------------------------------------------------------------------------------\nCOMMANDE: Num commande, Date, Montant, #Réf. client > CLIENT > Réf. client\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCOMMANDE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum commande\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tDate\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tMontant\n        , \n        entity_or_table_attr\n          #\n          foreign_reference\n            this_table_attr\n              attr\tRéf. client\n             > \n            that_table\n              entity_name_ref\n                box_name\tCLIENT\n             > \n            that_table_attr\n              attr\tRéf. client\n--------------------------------------------------------------------------------\n[{'name': 'COMMANDE',\n  'attrs': [{'attribute_label': 'Num commande', 'rank': 0},\n            {'attribute_label': 'Date', 'rank': 1},\n            {'attribute_label': 'Montant', 'rank': 2},\n            {'attribute_label': 'Réf. client',\n             'that_table': 'CLIENT',\n             'that_table_attribute_label': 'Réf. client',\n             'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'COMMANDE: Num commande, Date, Montant, #Réf. client > CLIENT > '\n            'Réf. client'}]\n\n--------------------------------------------------------------------------------\nINCLURE: #Num commande>COMMANDE>Num commande, _#Réf. produit>PRODUIT>Réf. produit, Quantité\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tINCLURE\n      : \n      seq\n        entity_or_table_attr\n          #\n          foreign_reference\n            this_table_attr\n              attr\tNum commande\n            >\n            that_table\n              entity_name_ref\n                box_name\tCOMMANDE\n            >\n            that_table_attr\n              attr\tNum commande\n        , \n        entity_or_table_attr\n          id_mark\t_\n          #\n          foreign_reference\n            this_table_attr\n              attr\tRéf. produit\n            >\n            that_table\n              entity_name_ref\n                box_name\tPRODUIT\n            >\n            that_table_attr\n              attr\tRéf. produit\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tQuantité\n--------------------------------------------------------------------------------\n[{'name': 'INCLURE',\n  'attrs': [{'attribute_label': 'Num commande',\n             'that_table': 'COMMANDE',\n             'that_table_attribute_label': 'Num commande',\n             'rank': 0},\n            {'id_mark': '_',\n             'attribute_label': 'Réf. produit',\n             'that_table': 'PRODUIT',\n             'that_table_attribute_label': 'Réf. produit',\n             'rank': 1},\n            {'attribute_label': 'Quantité', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'INCLURE: #Num commande>COMMANDE>Num commande, _#Réf. '\n            'produit>PRODUIT>Réf. produit, Quantité'}]\n\n--------------------------------------------------------------------------------\nINCLURE: #Num commande > COMMANDE > Num commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tINCLURE\n      : \n      seq\n        entity_or_table_attr\n          #\n          foreign_reference\n            this_table_attr\n              attr\tNum commande\n             > \n            that_table\n              entity_name_ref\n                box_name\tCOMMANDE\n             > \n            that_table_attr\n              attr\tNum commande\n        , \n        entity_or_table_attr\n          id_mark\t_\n          #\n          foreign_reference\n            this_table_attr\n              attr\tRéf. produit\n             > \n            that_table\n              entity_name_ref\n                box_name\tPRODUIT\n             > \n            that_table_attr\n              attr\tRéf. produit\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tQuantité\n--------------------------------------------------------------------------------\n[{'name': 'INCLURE',\n  'attrs': [{'attribute_label': 'Num commande',\n             'that_table': 'COMMANDE',\n             'that_table_attribute_label': 'Num commande',\n             'rank': 0},\n            {'id_mark': '_',\n             'attribute_label': 'Réf. produit',\n             'that_table': 'PRODUIT',\n             'that_table_attribute_label': 'Réf. produit',\n             'rank': 1},\n            {'attribute_label': 'Quantité', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'INCLURE: #Num commande > COMMANDE > Num commande, _#Réf. produit '\n            '> PRODUIT > Réf. produit, Quantité'}]\n\n--------------------------------------------------------------------------------\nCLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse [varchar(40)]\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCLIENT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tRéf. client\n             [\n            datatype\tvarchar(8)\n            ]\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tNom\n             [\n            datatype\tvarchar(20)\n            ]\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tAdresse\n             [\n            datatype\tvarchar(40)\n            ]\n--------------------------------------------------------------------------------\n[{'name': 'CLIENT',\n  'attrs': [{'attribute_label': 'Réf. client',\n             'datatype': 'varchar(8)',\n             'rank': 0},\n            {'attribute_label': 'Nom', 'datatype': 'varchar(20)', 'rank': 1},\n            {'attribute_label': 'Adresse',\n             'datatype': 'varchar(40)',\n             'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'CLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse '\n            '[varchar(40)]'}]\n\n--------------------------------------------------------------------------------\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tINCLURE\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tCOMMANDE\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tPRODUIT\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tQuantité\n             [\n            datatype\ttinyint(4)\n            ]\n--------------------------------------------------------------------------------\n[{'name': 'INCLURE',\n  'legs': [{'card': '1N', 'entity': 'COMMANDE', 'rank': 0},\n           {'card': '0N', 'entity': 'PRODUIT', 'rank': 1}],\n  'attrs': [{'attribute_label': 'Quantité',\n             'datatype': 'tinyint(4)',\n             'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]'}]\n\n--------------------------------------------------------------------------------\nPARTICIPANT: numero [], nom, adresse [type3]\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tPARTICIPANT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnumero\n             [\n            ]\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tnom\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tadresse\n             [\n            datatype\ttype3\n            ]\n--------------------------------------------------------------------------------\n[{'name': 'PARTICIPANT',\n  'attrs': [{'attribute_label': 'numero', 'rank': 0},\n            {'attribute_label': 'nom', 'rank': 1},\n            {'attribute_label': 'adresse', 'datatype': 'type3', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'PARTICIPANT: numero [], nom, adresse [type3]'}]\n\n--------------------------------------------------------------------------------\nCOMMANDE: Num commande, Date, Montant, #Réf. client!>CLIENT>Réf. client\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCOMMANDE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum commande\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tDate\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tMontant\n        , \n        entity_or_table_attr\n          #\n          foreign_reference\n            this_table_attr\n              attr\tRéf. client!\n            >\n            that_table\n              entity_name_ref\n                box_name\tCLIENT\n            >\n            that_table_attr\n              attr\tRéf. client\n--------------------------------------------------------------------------------\n[{'name': 'COMMANDE',\n  'attrs': [{'attribute_label': 'Num commande', 'rank': 0},\n            {'attribute_label': 'Date', 'rank': 1},\n            {'attribute_label': 'Montant', 'rank': 2},\n            {'attribute_label': 'Réf. client!',\n             'that_table': 'CLIENT',\n             'that_table_attribute_label': 'Réf. client',\n             'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'COMMANDE: Num commande, Date, Montant, #Réf. client!>CLIENT>Réf. '\n            'client'}]\n\n--------------------------------------------------------------------------------\nCOMMANDE: Num commande, Date, Montant, Réf. client!\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tCOMMANDE\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tNum commande\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tDate\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tMontant\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tRéf. client!\n--------------------------------------------------------------------------------\n[{'name': 'COMMANDE',\n  'attrs': [{'attribute_label': 'Num commande', 'rank': 0},\n            {'attribute_label': 'Date', 'rank': 1},\n            {'attribute_label': 'Montant', 'rank': 2},\n            {'attribute_label': 'Réf. client!', 'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'COMMANDE: Num commande, Date, Montant, Réf. client!'}]\n\n--------------------------------------------------------------------------------\nL33T, 0N> H4X0R, 0N< H4X0R\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tL33T\n      , \n      seq\n        assoc_leg\n          card\t0N\n          leg_arrow\t>\n           \n          entity_name_ref\n            box_name\tH4X0R\n        , \n        assoc_leg\n          card\t0N\n          leg_arrow\t<\n           \n          entity_name_ref\n            box_name\tH4X0R\n--------------------------------------------------------------------------------\n[{'name': 'L33T',\n  'legs': [{'card': '0N', 'leg_arrow': '>', 'entity': 'H4X0R', 'rank': 0},\n           {'card': '0N', 'leg_arrow': '<', 'entity': 'H4X0R', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'L33T, 0N> H4X0R, 0N< H4X0R'}]\n\n--------------------------------------------------------------------------------\nL33T123, 0N> H4X0R12, 0N< H4X0R0\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tL33T123\n      , \n      seq\n        assoc_leg\n          card\t0N\n          leg_arrow\t>\n           \n          entity_name_ref\n            box_name\tH4X0R12\n        , \n        assoc_leg\n          card\t0N\n          leg_arrow\t<\n           \n          entity_name_ref\n            box_name\tH4X0R0\n--------------------------------------------------------------------------------\n[{'name': 'L33T123',\n  'legs': [{'card': '0N', 'leg_arrow': '>', 'entity': 'H4X0R12', 'rank': 0},\n           {'card': '0N', 'leg_arrow': '<', 'entity': 'H4X0R0', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'L33T123, 0N> H4X0R12, 0N< H4X0R0'}]\n\n--------------------------------------------------------------------------------\n   AYANT-DROIT: nom ayant-droit, lien\n--------------------------------------------------------------------------------start\n  line\n    indent\t   \n    entity_clause\n      entity_name_def\n        box_name\tAYANT-DROIT\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnom ayant-droit\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tlien\n--------------------------------------------------------------------------------\n[{'type': 'entity',\n  'indent': '  ',\n  'name': 'AYANT-DROIT',\n  'attrs': [{'attribute_label': 'nom ayant-droit', 'rank': 0},\n            {'attribute_label': 'lien', 'rank': 1}],\n  'source': '  AYANT-DROIT: nom ayant-droit, lien'}]\n\n--------------------------------------------------------------------------------\n   DIRIGER, 0N EMPLOYÉ, 01 PROJET\n--------------------------------------------------------------------------------start\n  line\n    indent\t   \n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n      , \n      seq\n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tEMPLOYÉ\n        , \n        assoc_leg\n          card\t01\n           \n          entity_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'type': 'association',\n  'indent': '  ',\n  'name': 'DIRIGER',\n  'legs': [{'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 0},\n           {'card': '01', 'entity': 'PROJET', 'rank': 1}],\n  'source': '  DIRIGER, 0N EMPLOYÉ, 01 PROJET'}]\n\n--------------------------------------------------------------------------------\n   REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\n--------------------------------------------------------------------------------start\n  line\n    indent\t   \n    assoc_clause\n      assoc_name_def\n        box_name\tREQUÉRIR\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tPROJET\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tPIÈCE\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tqté requise\n--------------------------------------------------------------------------------\n[{'type': 'association',\n  'indent': '  ',\n  'name': 'REQUÉRIR',\n  'legs': [{'card': '1N', 'entity': 'PROJET', 'rank': 0},\n           {'card': '0N', 'entity': 'PIÈCE', 'rank': 1}],\n  'attrs': [{'attribute_label': 'qté requise', 'rank': 0}],\n  'source': '  REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise'}]\n\n--------------------------------------------------------------------------------\nDIRIGER, EMPLOYÉ, PROJET\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tEMPLOYÉ\n        , \n        assoc_leg\n          entity_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'entity': 'EMPLOYÉ', 'rank': 0}, {'entity': 'PROJET', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER, EMPLOYÉ, PROJET'}]\n\n--------------------------------------------------------------------------------\nA, B, C\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tA\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tB\n        , \n        assoc_leg\n          entity_name_ref\n            box_name\tC\n--------------------------------------------------------------------------------\n[{'name': 'A',\n  'legs': [{'entity': 'B', 'rank': 0}, {'entity': 'C', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'A, B, C'}]\n\n--------------------------------------------------------------------------------\nFoo, Bar\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tFoo\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tBar\n--------------------------------------------------------------------------------\n[{'name': 'Foo',\n  'legs': [{'entity': 'Bar', 'rank': 0}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Foo, Bar'}]\n\n--------------------------------------------------------------------------------\nDIRIGER, EMPLOYÉ, PROJET: biz, buz\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tEMPLOYÉ\n        , \n        assoc_leg\n          entity_name_ref\n            box_name\tPROJET\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tbiz\n        , \n        assoc_attr\n          typed_attr\n            attr\tbuz\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'entity': 'EMPLOYÉ', 'rank': 0}, {'entity': 'PROJET', 'rank': 1}],\n  'attrs': [{'attribute_label': 'biz', 'rank': 0},\n            {'attribute_label': 'buz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER, EMPLOYÉ, PROJET: biz, buz'}]\n\n--------------------------------------------------------------------------------\nA, B, C: biz, buz\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tA\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tB\n        , \n        assoc_leg\n          entity_name_ref\n            box_name\tC\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tbiz\n        , \n        assoc_attr\n          typed_attr\n            attr\tbuz\n--------------------------------------------------------------------------------\n[{'name': 'A',\n  'legs': [{'entity': 'B', 'rank': 0}, {'entity': 'C', 'rank': 1}],\n  'attrs': [{'attribute_label': 'biz', 'rank': 0},\n            {'attribute_label': 'buz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'A, B, C: biz, buz'}]\n\n--------------------------------------------------------------------------------\nFoo, Bar: biz, buz\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tFoo\n      , \n      seq\n        assoc_leg\n          entity_name_ref\n            box_name\tBar\n      : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tbiz\n        , \n        assoc_attr\n          typed_attr\n            attr\tbuz\n--------------------------------------------------------------------------------\n[{'name': 'Foo',\n  'legs': [{'entity': 'Bar', 'rank': 0}],\n  'attrs': [{'attribute_label': 'biz', 'rank': 0},\n            {'attribute_label': 'buz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Foo, Bar: biz, buz'}]\n\n--------------------------------------------------------------------------------\nAYANT-DROIT   :   nom ayant-droit   ,   lien   \n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAYANT-DROIT\n         :   \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnom ayant-droit\n           ,   \n        entity_or_table_attr\n          typed_attr\n            attr\tlien\n--------------------------------------------------------------------------------\n[{'name': 'AYANT-DROIT',\n  'attrs': [{'attribute_label': 'nom ayant-droit', 'rank': 0},\n            {'attribute_label': 'lien', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'AYANT-DROIT   :   nom ayant-droit   ,   lien   '}]\n\n--------------------------------------------------------------------------------\nDIRIGER   ,    0N    EMPLOYÉ   ,    01    PROJET   : fizz,  buzz   \n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n         ,    \n      seq\n        assoc_leg\n          card\t0N\n              \n          entity_name_ref\n            box_name\tEMPLOYÉ\n           ,    \n        assoc_leg\n          card\t01\n              \n          entity_name_ref\n            box_name\tPROJET\n         : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tfizz\n        ,  \n        assoc_attr\n          typed_attr\n            attr\tbuzz\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 0},\n           {'card': '01', 'entity': 'PROJET', 'rank': 1}],\n  'attrs': [{'attribute_label': 'fizz', 'rank': 0},\n            {'attribute_label': 'buzz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER   ,    0N    EMPLOYÉ   ,    01    PROJET   : fizz,  '\n            'buzz   '}]\n\n--------------------------------------------------------------------------------\nAYANT-DROIT  :  nom ayant-droit  ,  lien  \n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAYANT-DROIT\n        :  \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnom ayant-droit\n          ,  \n        entity_or_table_attr\n          typed_attr\n            attr\tlien\n--------------------------------------------------------------------------------\n[{'name': 'AYANT-DROIT',\n  'attrs': [{'attribute_label': 'nom ayant-droit', 'rank': 0},\n            {'attribute_label': 'lien', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'AYANT-DROIT\\xa0 :\\xa0 nom ayant-droit\\xa0 ,\\xa0 lien\\xa0 '}]\n\n--------------------------------------------------------------------------------\nDIRIGER  ,  0N  EMPLOYÉ  ,  01  PROJET  : fizz, buzz  \n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n        ,  \n      seq\n        assoc_leg\n          card\t0N\n            \n          entity_name_ref\n            box_name\tEMPLOYÉ\n          ,  \n        assoc_leg\n          card\t01\n            \n          entity_name_ref\n            box_name\tPROJET\n        : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tfizz\n        , \n        assoc_attr\n          typed_attr\n            attr\tbuzz\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 0},\n           {'card': '01', 'entity': 'PROJET', 'rank': 1}],\n  'attrs': [{'attribute_label': 'fizz', 'rank': 0},\n            {'attribute_label': 'buzz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER\\xa0 ,\\xa0\\xa00N\\xa0\\xa0EMPLOYÉ\\xa0 ,\\xa0\\xa001\\xa0\\xa0'\n            'PROJET\\xa0 : fizz,\\xa0buzz\\xa0 '}]\n\n--------------------------------------------------------------------------------\nAYANT-DROIT\t :\t nom ayant-droit\t ,\t lien\t \n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tAYANT-DROIT\n      \t :\t \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnom ayant-droit\n        \t ,\t \n        entity_or_table_attr\n          typed_attr\n            attr\tlien\n--------------------------------------------------------------------------------\n[{'name': 'AYANT-DROIT',\n  'attrs': [{'attribute_label': 'nom ayant-droit', 'rank': 0},\n            {'attribute_label': 'lien', 'rank': 1}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'AYANT-DROIT\\t :\\t nom ayant-droit\\t ,\\t lien\\t '}]\n\n--------------------------------------------------------------------------------\nDIRIGER\t ,\t\t0N\t\tEMPLOYÉ\t ,\t\t01\t\tPROJET\t : fizz,\tbuzz\t \n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tDIRIGER\n      \t ,\t\t\n      seq\n        assoc_leg\n          card\t0N\n          \t\t\n          entity_name_ref\n            box_name\tEMPLOYÉ\n        \t ,\t\t\n        assoc_leg\n          card\t01\n          \t\t\n          entity_name_ref\n            box_name\tPROJET\n      \t : \n      seq\n        assoc_attr\n          typed_attr\n            attr\tfizz\n        ,\t\n        assoc_attr\n          typed_attr\n            attr\tbuzz\n--------------------------------------------------------------------------------\n[{'name': 'DIRIGER',\n  'legs': [{'card': '0N', 'entity': 'EMPLOYÉ', 'rank': 0},\n           {'card': '01', 'entity': 'PROJET', 'rank': 1}],\n  'attrs': [{'attribute_label': 'fizz', 'rank': 0},\n            {'attribute_label': 'buzz', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'DIRIGER\\t ,\\t\\t0N\\t\\tEMPLOYÉ\\t ,\\t\\t01\\t\\tPROJET\\t : fizz,\\t'\n            'buzz\\t '}]\n\n--------------------------------------------------------------------------------\n() [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'type': 'constraint',\n  'indent': '',\n  'source': '() [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET'}]\n\n--------------------------------------------------------------------------------\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET'}]\n\n--------------------------------------------------------------------------------\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tII\n      ) \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n--------------------------------------------------------------------------------\n[{'name': 'II',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET'}]\n\n--------------------------------------------------------------------------------\n(III) [bla bla.]\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tIII\n      ) \n      [\n      constraint_note\tbla bla.\n      ]\n--------------------------------------------------------------------------------\n[{'name': 'III',\n  'constraint_note': 'bla bla.',\n  'type': 'constraint',\n  'indent': '',\n  'source': '(III) [bla bla.]'}]\n\n--------------------------------------------------------------------------------\n(IV) \n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tIV\n      )\n--------------------------------------------------------------------------------\n[{'name': 'IV', 'type': 'constraint', 'indent': '', 'source': '(IV) '}]\n\n--------------------------------------------------------------------------------\n(])\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\t]\n      )\n--------------------------------------------------------------------------------\n[{'name': ']', 'type': 'constraint', 'indent': '', 'source': '(])'}]\n\n--------------------------------------------------------------------------------\n(+)\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\t+\n      )\n--------------------------------------------------------------------------------\n[{'name': '+', 'type': 'constraint', 'indent': '', 'source': '(+)'}]\n\n--------------------------------------------------------------------------------\n(/)\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\t/\n      )\n--------------------------------------------------------------------------------\n[{'name': '/', 'type': 'constraint', 'indent': '', 'source': '(/)'}]\n\n--------------------------------------------------------------------------------\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n      : \n      constraint_coords\n        12.5\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'constraint_coords': [12.5, 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30'}]\n\n--------------------------------------------------------------------------------\n(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tII\n      ) \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n      : \n      constraint_coords\n        12.5\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'II',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'constraint_coords': [12.5, 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(II) ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, 30'}]\n\n--------------------------------------------------------------------------------\n(III) [bla bla.]: 12.5, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tIII\n      ) \n      [\n      constraint_note\tbla bla.\n      ]\n      : \n      constraint_coords\n        12.5\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'III',\n  'constraint_note': 'bla bla.',\n  'constraint_coords': [12.5, 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(III) [bla bla.]: 12.5, 30'}]\n\n--------------------------------------------------------------------------------\n(IV) : 12.5, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tIV\n      ) \n      : \n      constraint_coords\n        12.5\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'IV',\n  'constraint_coords': [12.5, 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(IV) : 12.5, 30'}]\n\n--------------------------------------------------------------------------------\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n      : \n      constraint_coords\n        box_name_ref\n          box_name\tFOO\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'constraint_coords': ['FOO', 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, 30'}]\n\n--------------------------------------------------------------------------------\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, BAR\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n      : \n      constraint_coords\n        12.5\n        , \n        box_name_ref\n          box_name\tBAR\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'constraint_coords': [12.5, 'BAR'],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: 12.5, BAR'}]\n\n--------------------------------------------------------------------------------\n(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, BAR\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      [\n      constraint_note\tbla bla.\n      ] \n      seq\n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tPIÈCE\n        , \n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tREQUÉRIR\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tFOURNIR\n        , \n        constraint_target\n          box_name_ref\n            box_name\tPROJET\n      : \n      constraint_coords\n        box_name_ref\n          box_name\tFOO\n        , \n        box_name_ref\n          box_name\tBAR\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_note': 'bla bla.',\n  'constraint_targets': [{'constraint_leg': '..', 'name': 'PIÈCE', 'rank': 0},\n                         {'constraint_leg': '->',\n                          'name': 'REQUÉRIR',\n                          'rank': 1},\n                         {'constraint_leg': '--', 'name': 'FOURNIR', 'rank': 2},\n                         {'name': 'PROJET', 'rank': 3}],\n  'constraint_coords': ['FOO', 'BAR'],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) [bla bla.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET: FOO, BAR'}]\n\n--------------------------------------------------------------------------------\n(IV) : 12.5, 30\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tIV\n      ) \n      : \n      constraint_coords\n        12.5\n        , \n        30\n--------------------------------------------------------------------------------\n[{'name': 'IV',\n  'constraint_coords': [12.5, 30],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(IV) : 12.5, 30'}]\n\n--------------------------------------------------------------------------------\n(A) --Lorem, .....Ipsum, -Dolor: 30, 10\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tA\n      ) \n      seq\n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tLorem\n        , \n        constraint_target\n          constraint_leg\t.....\n          box_name_ref\n            box_name\tIpsum\n        , \n        constraint_target\n          constraint_leg\t-\n          box_name_ref\n            box_name\tDolor\n      : \n      constraint_coords\n        30\n        , \n        10\n--------------------------------------------------------------------------------\n[{'name': 'A',\n  'constraint_targets': [{'constraint_leg': '--', 'name': 'Lorem', 'rank': 0},\n                         {'constraint_leg': '.....',\n                          'name': 'Ipsum',\n                          'rank': 1},\n                         {'constraint_leg': '-', 'name': 'Dolor', 'rank': 2}],\n  'constraint_coords': [30, 10],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(A) --Lorem, .....Ipsum, -Dolor: 30, 10'}]\n\n--------------------------------------------------------------------------------\n(B) ->Dolor, <-->Sit, -->Amet: 69, 10\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tB\n      ) \n      seq\n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tDolor\n        , \n        constraint_target\n          constraint_leg\t<-->\n          box_name_ref\n            box_name\tSit\n        , \n        constraint_target\n          constraint_leg\t-->\n          box_name_ref\n            box_name\tAmet\n      : \n      constraint_coords\n        69\n        , \n        10\n--------------------------------------------------------------------------------\n[{'name': 'B',\n  'constraint_targets': [{'constraint_leg': '->', 'name': 'Dolor', 'rank': 0},\n                         {'constraint_leg': '<-->', 'name': 'Sit', 'rank': 1},\n                         {'constraint_leg': '-->', 'name': 'Amet', 'rank': 2}],\n  'constraint_coords': [69, 10],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(B) ->Dolor, <-->Sit, -->Amet: 69, 10'}]\n\n--------------------------------------------------------------------------------\n(XX) ->foo, -->foo, -> foo, --> foo\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tXX\n      ) \n      seq\n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tfoo\n        , \n        constraint_target\n          constraint_leg\t-->\n          box_name_ref\n            box_name\tfoo\n        , \n        constraint_target\n          constraint_leg\t->\n           \n          box_name_ref\n            box_name\tfoo\n        , \n        constraint_target\n          constraint_leg\t-->\n           \n          box_name_ref\n            box_name\tfoo\n--------------------------------------------------------------------------------\n[{'name': 'XX',\n  'constraint_targets': [{'constraint_leg': '->', 'name': 'foo', 'rank': 0},\n                         {'constraint_leg': '-->', 'name': 'foo', 'rank': 1},\n                         {'constraint_leg': '->', 'name': 'foo', 'rank': 2},\n                         {'constraint_leg': '-->', 'name': 'foo', 'rank': 3}],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(XX) ->foo, -->foo, -> foo, --> foo'}]\n\n--------------------------------------------------------------------------------\n(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer\n--------------------------------------------------------------------------------start\n  line\n    constraint_clause\n      (\n      constraint_name\tI\n      ) \n      seq\n        constraint_target\n          constraint_leg\t->\n          box_name_ref\n            box_name\tStocker\n        , \n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tDépôt\n        , \n        constraint_target\n          constraint_leg\t..\n          box_name_ref\n            box_name\tArticle\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tComposer\n        , \n        constraint_target\n          constraint_leg\t--\n          box_name_ref\n            box_name\tLouer\n--------------------------------------------------------------------------------\n[{'name': 'I',\n  'constraint_targets': [{'constraint_leg': '->', 'name': 'Stocker', 'rank': 0},\n                         {'constraint_leg': '..', 'name': 'Dépôt', 'rank': 1},\n                         {'constraint_leg': '..', 'name': 'Article', 'rank': 2},\n                         {'constraint_leg': '--',\n                          'name': 'Composer',\n                          'rank': 3},\n                         {'constraint_leg': '--', 'name': 'Louer', 'rank': 4}],\n  'type': 'constraint',\n  'indent': '',\n  'source': '(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer'}]\n\n--------------------------------------------------------------------------------\n/XT\\ Personne ==> Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tXT\n      \\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t==>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'XT',\n  'inheritance_arrow': '==>',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/XT\\\\ Personne ==> Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/XT1\\\\ Personne <= Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tXT1\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t<=\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'XT1',\n  'inheritance_arrow': '<=',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/XT1\\\\\\\\ Personne <= Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/XT\\\\ Personne => Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tXT\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t=>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'XT',\n  'inheritance_arrow': '=>',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/XT\\\\\\\\ Personne => Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/T\\\\ Personne <= Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tT\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t<=\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'T',\n  'inheritance_arrow': '<=',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/T\\\\\\\\ Personne <= Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/T\\\\ Personne => Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tT\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t=>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'T',\n  'inheritance_arrow': '=>',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/T\\\\\\\\ Personne => Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/X\\\\ Personne <= Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tX\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t<=\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'X',\n  'inheritance_arrow': '<=',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/X\\\\\\\\ Personne <= Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/X\\\\ Personne => Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tX\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t=>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'name': 'X',\n  'inheritance_arrow': '=>',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/X\\\\\\\\ Personne => Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/\\\\ Personne <= Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t<=\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'inheritance_arrow': '<=',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'name': '',\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/\\\\\\\\ Personne <= Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/\\\\ Personne => Homme, Femme: sexe\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tPersonne\n       \n      inheritance_arrow\t=>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tHomme\n        , \n        inheritance_child\n          entity_name_ref\n            box_name\tFemme\n      : \n      seq\n        typed_attr\n          attr\tsexe\n--------------------------------------------------------------------------------\n[{'inheritance_arrow': '=>',\n  'legs': [{'entity': 'Personne', 'rank': -1},\n           {'entity': 'Homme', 'rank': 0},\n           {'entity': 'Femme', 'rank': 1}],\n  'attrs': [{'attribute_label': 'sexe', 'rank': 0}],\n  'name': '',\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/\\\\\\\\ Personne => Homme, Femme: sexe'}]\n\n--------------------------------------------------------------------------------\n/1\\\\ FOO => BAR\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\t1\n      \\\\\n       \n      inheritance_parent\n        entity_name_ref\n          box_name\tFOO\n       \n      inheritance_arrow\t=>\n       \n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tBAR\n--------------------------------------------------------------------------------\n[{'name': '1',\n  'inheritance_arrow': '=>',\n  'legs': [{'entity': 'FOO', 'rank': -1}, {'entity': 'BAR', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/1\\\\\\\\ FOO => BAR'}]\n\n--------------------------------------------------------------------------------\n/T\\\\foo==>foo11\n--------------------------------------------------------------------------------start\n  line\n    inheritance_clause\n      /\n      inheritance_name\tT\n      \\\\\n      inheritance_parent\n        entity_name_ref\n          box_name\tfoo\n      inheritance_arrow\t==>\n      seq\n        inheritance_child\n          entity_name_ref\n            box_name\tfoo11\n--------------------------------------------------------------------------------\n[{'name': 'T',\n  'inheritance_arrow': '==>',\n  'legs': [{'entity': 'foo', 'rank': -1}, {'entity': 'foo11', 'rank': 0}],\n  'type': 'inheritance',\n  'indent': '',\n  'source': '/T\\\\\\\\foo==>foo11'}]\n\n--------------------------------------------------------------------------------\nÉtudiant: num, 1_nom, 1_prénom, adresse, 2_mail\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tÉtudiant\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tnum\n        , \n        entity_or_table_attr\n          id_groups\t1\n          id_mark\t_\n          typed_attr\n            attr\tnom\n        , \n        entity_or_table_attr\n          id_groups\t1\n          id_mark\t_\n          typed_attr\n            attr\tprénom\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tadresse\n        , \n        entity_or_table_attr\n          id_groups\t2\n          id_mark\t_\n          typed_attr\n            attr\tmail\n--------------------------------------------------------------------------------\n[{'name': 'Étudiant',\n  'attrs': [{'attribute_label': 'num', 'rank': 0},\n            {'id_groups': '1',\n             'id_mark': '_',\n             'attribute_label': 'nom',\n             'rank': 1},\n            {'id_groups': '1',\n             'id_mark': '_',\n             'attribute_label': 'prénom',\n             'rank': 2},\n            {'attribute_label': 'adresse', 'rank': 3},\n            {'id_groups': '2',\n             'id_mark': '_',\n             'attribute_label': 'mail',\n             'rank': 4}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Étudiant: num, 1_nom, 1_prénom, adresse, 2_mail'}]\n\n--------------------------------------------------------------------------------\nÉtudiant: 0_num, 1_nom, 1_prénom, adresse, 2_mail\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tÉtudiant\n      : \n      seq\n        entity_or_table_attr\n          id_groups\t0\n          id_mark\t_\n          typed_attr\n            attr\tnum\n        , \n        entity_or_table_attr\n          id_groups\t1\n          id_mark\t_\n          typed_attr\n            attr\tnom\n        , \n        entity_or_table_attr\n          id_groups\t1\n          id_mark\t_\n          typed_attr\n            attr\tprénom\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\tadresse\n        , \n        entity_or_table_attr\n          id_groups\t2\n          id_mark\t_\n          typed_attr\n            attr\tmail\n--------------------------------------------------------------------------------\n[{'name': 'Étudiant',\n  'attrs': [{'id_groups': '0',\n             'id_mark': '_',\n             'attribute_label': 'num',\n             'rank': 0},\n            {'id_groups': '1',\n             'id_mark': '_',\n             'attribute_label': 'nom',\n             'rank': 1},\n            {'id_groups': '1',\n             'id_mark': '_',\n             'attribute_label': 'prénom',\n             'rank': 2},\n            {'attribute_label': 'adresse', 'rank': 3},\n            {'id_groups': '2',\n             'id_mark': '_',\n             'attribute_label': 'mail',\n             'rank': 4}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Étudiant: 0_num, 1_nom, 1_prénom, adresse, 2_mail'}]\n\n--------------------------------------------------------------------------------\nPosition: 0_latitude, 0_longitude, altitude\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tPosition\n      : \n      seq\n        entity_or_table_attr\n          id_groups\t0\n          id_mark\t_\n          typed_attr\n            attr\tlatitude\n        , \n        entity_or_table_attr\n          id_groups\t0\n          id_mark\t_\n          typed_attr\n            attr\tlongitude\n        , \n        entity_or_table_attr\n          typed_attr\n            attr\taltitude\n--------------------------------------------------------------------------------\n[{'name': 'Position',\n  'attrs': [{'id_groups': '0',\n             'id_mark': '_',\n             'attribute_label': 'latitude',\n             'rank': 0},\n            {'id_groups': '0',\n             'id_mark': '_',\n             'attribute_label': 'longitude',\n             'rank': 1},\n            {'attribute_label': 'altitude', 'rank': 2}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Position: 0_latitude, 0_longitude, altitude'}]\n\n--------------------------------------------------------------------------------\nFoo: bar, 1_baz, 21_qux, 123_quux\n--------------------------------------------------------------------------------start\n  line\n    entity_clause\n      entity_name_def\n        box_name\tFoo\n      : \n      seq\n        entity_or_table_attr\n          typed_attr\n            attr\tbar\n        , \n        entity_or_table_attr\n          id_groups\t1\n          id_mark\t_\n          typed_attr\n            attr\tbaz\n        , \n        entity_or_table_attr\n          id_groups\t21\n          id_mark\t_\n          typed_attr\n            attr\tqux\n        , \n        entity_or_table_attr\n          id_groups\t123\n          id_mark\t_\n          typed_attr\n            attr\tquux\n--------------------------------------------------------------------------------\n[{'name': 'Foo',\n  'attrs': [{'attribute_label': 'bar', 'rank': 0},\n            {'id_groups': '1',\n             'id_mark': '_',\n             'attribute_label': 'baz',\n             'rank': 1},\n            {'id_groups': '12',\n             'id_mark': '_',\n             'attribute_label': 'qux',\n             'rank': 2},\n            {'id_groups': '123',\n             'id_mark': '_',\n             'attribute_label': 'quux',\n             'rank': 3}],\n  'type': 'entity',\n  'indent': '',\n  'source': 'Foo: bar, 1_baz, 21_qux, 123_quux'}]\n\n--------------------------------------------------------------------------------\nRéserver, 1N Client, 0N Chambre: _date, durée\n--------------------------------------------------------------------------------start\n  line\n    assoc_clause\n      assoc_name_def\n        box_name\tRéserver\n      , \n      seq\n        assoc_leg\n          card\t1N\n           \n          entity_name_ref\n            box_name\tClient\n        , \n        assoc_leg\n          card\t0N\n           \n          entity_name_ref\n            box_name\tChambre\n      : \n      seq\n        assoc_attr\n          _\n          typed_attr\n            attr\tdate\n        , \n        assoc_attr\n          typed_attr\n            attr\tdurée\n--------------------------------------------------------------------------------\n[{'name': 'Réserver',\n  'legs': [{'card': '1N', 'entity': 'Client', 'rank': 0},\n           {'card': '0N', 'entity': 'Chambre', 'rank': 1}],\n  'attrs': [{'attribute_label': 'date', 'id_mark': '_', 'rank': 0},\n            {'attribute_label': 'durée', 'rank': 1}],\n  'type': 'association',\n  'indent': '',\n  'source': 'Réserver, 1N Client, 0N Chambre: _date, durée'}]\n\n"
  },
  {
    "path": "test/test_read_template.py",
    "content": "import gettext\nimport unittest\nfrom pathlib import Path\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.convert.read_template import read_template\nfrom mocodo.tools import load_mini_yaml\nfrom mocodo.mocodo_error import MocodoError\nfrom mocodo.dev import update_transfo_metadata # just update the graph and index\n\ngettext.NullTranslations().install()\n\nTEMPLATE_FOLDER = Path(\"test\", \"test_data\", \"templates\")\n\nclass TestReadTemplate(unittest.TestCase):\n\n    def test_root_template(self):\n        template = read_template(\"root\", TEMPLATE_FOLDER)\n        expected = load_mini_yaml.run(Path(TEMPLATE_FOLDER, \"root.yaml\"))\n        self.assertEqual(template, expected)\n    \n    def test_child_template(self):\n        template = read_template(\"child\", TEMPLATE_FOLDER)\n        expected = load_mini_yaml.run(Path(TEMPLATE_FOLDER, \"expected_child.yaml\"))\n        self.assertEqual(template, expected)\n    \n    def test_grandchild_template(self):\n        template = read_template(\"grandchild\", TEMPLATE_FOLDER)\n        expected = load_mini_yaml.run(Path(TEMPLATE_FOLDER, \"expected_grandchild.yaml\"))\n        self.assertEqual(template, expected)\n    \n    def test_errors(self):\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.30\", read_template, \"bad_circular_1\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.31\", read_template, \"not_a_file\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.32\", read_template, \"bad_array_element\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.32\", read_template, \"bad_not_an_object\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.32\", read_template, \"bad_object_value\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.36\", read_template, \"bad_no_order\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.38\", read_template, \"bad_non_numeric_order\", TEMPLATE_FOLDER)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.39\", read_template, \"bad_non_increasing_order\", TEMPLATE_FOLDER)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_relations.py",
    "content": "from pathlib import Path\nimport unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.argument_parser import parsed_arguments\nfrom mocodo.mcd import Mcd\nfrom mocodo.convert.relations import *\nfrom mocodo.tools.string_tools import markdown_table\nfrom mocodo.tools.load_mini_yaml import run as load_mini_yaml\n\n\nminimal_template = load_mini_yaml(Path(\"mocodo/resources/relation_templates/text.yaml\"))\ndebug_template = load_mini_yaml(Path(\"mocodo/resources/relation_templates/debug.yaml\"))\nparams = parsed_arguments([])\nparams[\"title\"] = \"Untitled\"\nparams[\"guess_title\"] = False\n\ndef debug_table(t):\n    tsv = t.get_text(debug_template).rstrip(\"\\n\")\n    tsv = tsv.replace(\"this relation name\", \"relation\")\n    rows = [line.split(\"\\t\") for line in tsv.split(\"\\n\")]\n    return re.sub(\"(?m)^\", \"            \", markdown_table(rows))\n\nclass relationsTest(unittest.TestCase):\n    \n    def test_arrows_are_ignored(self):\n        source = \"\"\"\n            Personne: Num. SS, Nom, Prénom, Sexe\n            Engendrer, 0N< Personne, 22> Personne\n        \"\"\"\n        t = Relations(Mcd(source, params), params)\n        d1 = t.get_text(debug_template)\n        source = \"\"\"\n            Personne: Num. SS, Nom, Prénom, Sexe\n            Engendrer, 0N Personne, 22 Personne\n        \"\"\"\n        t = Relations(Mcd(source, params), params)\n        d2 = t.get_text(debug_template)\n        self.assertEqual(d1, d2)\n    \n    def test_reciprocical_relative_entities(self):\n        source = \"\"\"\n            Aids: Norm, Free, Soon, Pack, Face, Seem, Teen\n            Yard, 0N Unit, ON Aids\n            Ever, 1N Unit, 1N Item\n            Item: Norm, Wash, Haul, Milk, Draw, Lady, Face, Soon, Dish\n            :\n\n            Amid, 1n Aids, 1n Disk, _11 Flip: Gold\n            Same, _11 Unit, 0N Flip\n            Unit: Folk, Peer, Tour, Hall\n            Fold, _11 Unit, 1N Baby, _11 Item\n            Baby: Soon\n\n            Disk: Soon, Ride, Folk, Call, Gear, Tent, Lean\n            Flip: Lend\n            Pump, _11 Flip, 1N Unit: Both, Raid\n            Gene: Soon\n            Bind, _11 Baby, 1n Gene\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.11\", Relations, mcd, params)\n        source = \"\"\"\n            Disk: Soon, Ride, Folk, Call, Gear, Tent, Lean\n            Flip: Lend\n            Pump, _11 Flip, 1N Unit: Both, Raid\n            Gene: Soon\n            Bind, _11 Baby, 1n Gene\n\n            Amid, 1n Aids, 1n Disk, _11 Flip: Gold\n            Same, _11 Unit, 0N Flip\n            Unit: Folk, Peer, Tour, Hall\n            Fold, _11 Unit, 1N Baby, _11 Item\n            Baby: Soon\n\n            Aids: Norm, Free, Soon, Pack, Face, Seem, Teen\n            Yard, 0N Unit, ON Aids\n            Ever, 1N Unit, 1N Item\n            Item: Norm, Wash, Haul, Milk, Draw, Lady, Face, Soon, Dish\n            :\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.11\", Relations, mcd, params)\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.11\", Relations, mcd, params)\n        source = \"\"\"\n            ITEM, 1N NORM, 1N WASH\n            NORM: haul\n            \n            WASH: soon\n            BABY, 1N WASH, 1N FACE\n            FACE: gene\n            \n            AAA, _11 FLIP, 1N WASH\n            FLIP: soona\n            GEAR, _11 FLIP, _11 FACE\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.11\", Relations, mcd, params)\n        source = \"\"\"\n            ITEM, 1N NORM, 1N WASH\n            NORM: haul\n            \n            WASH: soon\n            BABY, 1N WASH, 1N FACE\n            FACE: gene\n            \n            CCC, _11 FLIP, 1N WASH\n            FLIP: soona\n            GEAR, _11 FLIP, _11 FACE\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.11\", Relations, mcd, params)\n\n    def test_association_attributes(self):\n        source = \"\"\"\n            Client: Id. client\n            Réserver, 1N Client, 0N Chambre: _Date, Durée\n            Chambre: Num. chambre, Prix\n        \"\"\"\n        expected = \"\"\"\n            Chambre (_Num. chambre_, Prix)\n            Réserver (_Id. client_, _#Num. chambre_, _Date_, Durée)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), expected)\n    \n    def test_weak_entities_strengthened_by_itself(self):\n        source = \"\"\"\n            SCELERISQUE: blandit, elit\n            DF, _11 SCELERISQUE, 1N SCELERISQUE\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.16\", Relations, mcd, params)\n    \n    def test_weak_entities_strengthened_by_several_entities(self):\n        source = \"\"\"\n            Baby: Soon, protect_baby\n            Yard, _11 Unit, ON Baby: Hall\n            \n            :\n            Unit: Folk, Peer\n            \n            \n            Item: Norm, Wash\n            Ever, _11 Unit, 1N Item: Tour\n        \"\"\"\n        expected = \"\"\"\n            Baby (_Soon_, protect_baby)\n            Item (_Norm_, Wash)\n            Unit (_#Norm_, _#Soon_, _Folk_, Peer, Hall, Tour)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), expected)\n    \n    def test_weak_entities_with_cycle(self):\n        source = \"\"\"\n            ITEM: norm, wash, haul\n            MILK, _11 ITEM, 1N DRAW: lady, face\n\n            SOON, 1N ITEM, _11 DRAW\n            DRAW: ever, unit, tour, fold\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.17\", Relations, mcd, params)\n\n    def test_disambiguation_by_role(self):\n        source = \"\"\"\n            Entité A: id. entité A \n            DF, 11 Entité centrale, 1N Entité A\n            DF, 11 Entité centrale, 1N [-nouveau nom B] Entité B\n            Entité B: id. entité B\n\n            Entité E: id. entité E \n            DF, 11 Entité centrale, 1N [suffixe] Entité E\n            Entité centrale: id. entité centrale\n            DF, 11 Entité centrale, 1N [+hérissons] Entité C\n\n            :\n            Entité D: id. entité D\n            DF, 11 Entité centrale, 1N [Description affichée au survol.] Entité D\n            Entité C: id. entité C\n        \"\"\"\n        expected = \"\"\"\n            Entité centrale (_id. entité centrale_, id. entité A, nouveau nom B, id. entité E suffixe, id. entité Chérissons, id. entité D)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), expected)\n\n    def test_disambiguation_by_number(self):\n        source = \"\"\"\n            Entité A: id\n            DF, 11 Entité centrale, 1N Entité A\n            DF, 11 Entité centrale, 1N Entité B\n            Entité B: id\n\n            Entité E: id\n            DF, 11 Entité centrale, 1N [Description affichée au survol.] Entité E\n            Entité centrale: id\n            DF, 11 Entité centrale, 1N [suffixe] Entité C\n\n            :\n            Entité D: id\n            DF, 11 Entité centrale, 1N [suffixe] Entité D\n            Entité C: id\n        \"\"\"\n        expected = \"\"\"\n            Entité centrale (_id_, id 2, id 3, id 4, id suffixe 1, id suffixe 2)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), expected)\n\n    def test_disambiguation_by_role_then_number(self):\n        source = \"\"\"\n            FOO: id\n            BAR: id\n            DF, 11 FOO, 1N BAR\n            DF, 11 FOO, 1N BAR\n            DF, 11 FOO, 1N [role] BAR\n            DF, 11 FOO, 1N [+role] BAR\n            DF, 11 FOO, 1N [+_role] BAR\n            DF, 11 FOO, 1N [-role] BAR\n            DF, 11 FOO, 1N [string containing spaces] BAR\n        \"\"\"\n        expected = \"\"\"\n            FOO (_id_, id 2, id 3, id role, idrole, id_role, role, id 4)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), expected)\n\n    def test_inheritance_leftwards_double_arrow(self):\n        source = \"\"\"\n            /\\\\ ANIMAL <= CARNIVORE, HERBIVORE\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        text = \"\"\"\n            ANIMAL (_animal_, poids, est carnivore, quantité viande, est herbivore, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        mcd = Mcd(source, params)\n        t = Relations(mcd, params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation | attribute       | optionality | unicities | nature                    | is primary | adjacent source | outer source | association name | datatype            | leg note |\n            |:---------|:----------------|:------------|:----------|:--------------------------|:-----------|:----------------|:-------------|:-----------------|:--------------------|:---------|\n            | ANIMAL   | animal          | !           |           | primary_key               | True       |                 |              |                  |                     |          |\n            | ANIMAL   | poids           |             |           | normal_attribute          | False      |                 |              |                  |                     |          |\n            | ANIMAL   | est carnivore   | !           |           | deleted_child_entity_name | False      | CARNIVORE       | CARNIVORE    |                  | BOOLEAN_PLACEHOLDER |          |\n            | ANIMAL   | quantité viande | ?           |           | deleted_child_attribute   | False      | CARNIVORE       |              |                  |                     |          |\n            | ANIMAL   | est herbivore   | !           |           | deleted_child_entity_name | False      | HERBIVORE       | HERBIVORE    |                  | BOOLEAN_PLACEHOLDER |          |\n            | ANIMAL   | plante préférée | ?           |           | deleted_child_attribute   | False      | HERBIVORE       |              |                  |                     |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_leftwards_simple_arrow(self):\n        source = \"\"\"\n            /\\\\ ANIMAL <- CARNIVORE, HERBIVORE: type\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        text = \"\"\"\n            ANIMAL (_animal_, poids, type, quantité viande, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        mcd = Mcd(source, params)\n        t = Relations(mcd, params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation | attribute       | optionality | unicities | nature                       | is primary | adjacent source | outer source | association name | datatype                 | leg note |\n            |:---------|:----------------|:------------|:----------|:-----------------------------|:-----------|:----------------|:-------------|:-----------------|:-------------------------|:---------|\n            | ANIMAL   | animal          | !           |           | primary_key                  | True       |                 |              |                  |                          |          |\n            | ANIMAL   | poids           |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n            | ANIMAL   | type            | ?           |           | deleted_child_discriminator_ | False      |                 |              |                  | UNSIGNED_INT_PLACEHOLDER |          |\n            | ANIMAL   | quantité viande | ?           |           | deleted_child_attribute      | False      | CARNIVORE       |              |                  |                          |          |\n            | ANIMAL   | plante préférée | ?           |           | deleted_child_attribute      | False      | HERBIVORE       |              |                  |                          |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_rightwards_simple_arrow(self):\n        source = \"\"\"\n            /\\\\ ANIMAL -> CARNIVORE, HERBIVORE: type\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        text = \"\"\"\n            ANIMAL (_animal_, poids, type)\n            CARNIVORE (_#animal_, quantité viande)\n            HERBIVORE (_#animal_, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation  | attribute       | optionality | unicities | nature                       | is primary | adjacent source | outer source | association name | datatype                 | leg note |\n            |:----------|:----------------|:------------|:----------|:-----------------------------|:-----------|:----------------|:-------------|:-----------------|:-------------------------|:---------|\n            | ANIMAL    | animal          | !           |           | primary_key                  | True       |                 |              |                  |                          |          |\n            | ANIMAL    | poids           |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n            | ANIMAL    | type            | ?           |           | deleted_child_discriminator_ | False      |                 |              |                  | UNSIGNED_INT_PLACEHOLDER |          |\n            | CARNIVORE | animal          | !           |           | parent_primary_key           | True       | ANIMAL          | ANIMAL       |                  |                          |          |\n            | CARNIVORE | quantité viande |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n            | HERBIVORE | animal          | !           |           | parent_primary_key           | True       | ANIMAL          | ANIMAL       |                  |                          |          |\n            | HERBIVORE | plante préférée |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_rightwards_double_arrow_with_totality(self):\n        source = \"\"\"\n            /T\\\\ ANIMAL => CARNIVORE, HERBIVORE: type\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        text = \"\"\"\n            CARNIVORE (_animal_, poids, quantité viande)\n            HERBIVORE (_animal_, poids, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        mcd = Mcd(source, params)\n        t = Relations(mcd, params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation  | attribute       | optionality | unicities | nature                     | is primary | adjacent source | outer source | association name | datatype | leg note |\n            |:----------|:----------------|:------------|:----------|:---------------------------|:-----------|:----------------|:-------------|:-----------------|:---------|:---------|\n            | CARNIVORE | animal          | !           |           | deleted_parent_primary_key | True       | ANIMAL          | ANIMAL       | T                |          |          |\n            | CARNIVORE | poids           |             |           | deleted_parent_attribute   | False      | ANIMAL          |              | T                |          |          |\n            | CARNIVORE | quantité viande |             |           | normal_attribute           | False      |                 |              |                  |          |          |\n            | HERBIVORE | animal          | !           |           | deleted_parent_primary_key | True       | ANIMAL          | ANIMAL       | T                |          |          |\n            | HERBIVORE | poids           |             |           | deleted_parent_attribute   | False      | ANIMAL          |              | T                |          |          |\n            | HERBIVORE | plante préférée |             |           | normal_attribute           | False      |                 |              |                  |          |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_rightwards_double_arrow_without_totality(self):\n        source = \"\"\"\n            /X\\\\ ANIMAL => CARNIVORE, HERBIVORE: type\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        mcd = Mcd(source, params)\n        self.assertRaisesRegex(MocodoError, r\"Mocodo Err\\.25\", Relations, mcd, params)\n\n    def test_inheritance_leftwards_simple_arrow_unpretty(self):\n        source = \"\"\"\n            /\\\\ ANIMAL <-- CARNIVORE, HERBIVORE: type\n            ANIMAL: animal, poids\n            CARNIVORE: quantité viande\n            HERBIVORE: plante préférée\n        \"\"\"\n        text = \"\"\"\n            ANIMAL (_animal_, poids, type, quantité viande, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation | attribute       | optionality | unicities | nature                       | is primary | adjacent source | outer source | association name | datatype                 | leg note |\n            |:---------|:----------------|:------------|:----------|:-----------------------------|:-----------|:----------------|:-------------|:-----------------|:-------------------------|:---------|\n            | ANIMAL   | animal          | !           |           | primary_key                  | True       |                 |              |                  |                          |          |\n            | ANIMAL   | poids           |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n            | ANIMAL   | type            | ?           |           | deleted_child_discriminator_ | False      |                 |              |                  | UNSIGNED_INT_PLACEHOLDER |          |\n            | ANIMAL   | quantité viande | ?           |           | deleted_child_attribute      | False      | CARNIVORE       |              |                  |                          |          |\n            | ANIMAL   | plante préférée | ?           |           | deleted_child_attribute      | False      | HERBIVORE       |              |                  |                          |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_with_unique_child(self):\n        source = \"\"\"\n            CARNIVORE: quantité viande\n            /\\\\ ANIMAL -> CARNIVORE: type\n            ANIMAL: animal, poids\n        \"\"\"\n        text = \"\"\"\n            ANIMAL (_animal_, poids, type)\n            CARNIVORE (_#animal_, quantité viande)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n        expected = \"\"\"\n            | relation  | attribute       | optionality | unicities | nature                       | is primary | adjacent source | outer source | association name | datatype                 | leg note |\n            |:----------|:----------------|:------------|:----------|:-----------------------------|:-----------|:----------------|:-------------|:-----------------|:-------------------------|:---------|\n            | ANIMAL    | animal          | !           |           | primary_key                  | True       |                 |              |                  |                          |          |\n            | ANIMAL    | poids           |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n            | ANIMAL    | type            | ?           |           | deleted_child_discriminator_ | False      |                 |              |                  | UNSIGNED_INT_PLACEHOLDER |          |\n            | CARNIVORE | animal          | !           |           | parent_primary_key           | True       | ANIMAL          | ANIMAL       |                  |                          |          |\n            | CARNIVORE | quantité viande |             |           | normal_attribute             | False      |                 |              |                  |                          |          |\n        \"\"\"\n        actual = debug_table(t)\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_inheritance_with_distant_leg_note(self):\n        source = \"\"\"\n            HERBIVORE: plante préférée\n            :\n            :\n\n            /XT\\\\ ANIMAL => CARNIVORE, HERBIVORE: type alimentation\n            ANIMAL: nom, sexe, date naissance, date décès\n            A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n\n            CARNIVORE: quantité viande\n            :\n            :        \n        \"\"\"\n        text = \"\"\"\n            CARNIVORE (_nom_, sexe, date naissance, date décès, nom mère, quantité viande)\n            HERBIVORE (_nom_, sexe, date naissance, date décès, nom mère, plante préférée)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n    \n    def test_two_same_type_inheritances(self):\n        # example from user fduchatea on https://github.com/laowantong/mocodo/issues/64\n        source = \"\"\"\n            :\n            :\n            Inscrites :\n            :\n\n            :\n            UtilisatricesPlus : nom, prénom\n            /XT\\\\ UtilisatricesPlus --> Inscrites, Abonnées : catégorie\n            Abonnées :\n\n            Utilisatrices : idU, email\n            /XT\\\\ Utilisatrices --> Invitées, UtilisatricesPlus : catégorie\n            Invitées : adresseIP\n            :\n        \"\"\"\n        text = \"\"\"\n            Invitées (_#idU_, adresseIP)\n            Utilisatrices (_idU_, email, catégorie)\n            UtilisatricesPlus (_#idU_, nom, prénom, catégorie)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n    \n    def test_roles_with_inheritance(self):\n        # https://github.com/laowantong/mocodo/issues/110\n        source = \"\"\"\n            Équipe: id équipe,nom équipe\n            Accueille, 11 Match, 0N [-hôte] Équipe\n\n            Reçoit, 11 Match, 0N [-visiteur] Équipe\n            Match: id match\n\n            Rencontre: id rencontre\n            /XT\\\\ Rencontre <- Match: type rencontre\n        \"\"\"\n        text = \"\"\"\n            Équipe (_id équipe_, nom équipe)\n            Rencontre (_id rencontre_, type rencontre, id match, #hôte, #visiteur)\n        \"\"\".strip().replace(\"    \", \"\")\n        t = Relations(Mcd(source, params), params)\n        self.assertEqual(t.get_text(minimal_template), text)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "test/test_rewrite_cards.py",
    "content": "import unittest\nimport random\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite import op_tk\n\n\nclass TestUpdateCards(unittest.TestCase):\n\n    def test_infer_df(self):\n        # Actually not a card update, but I don't want to create a new test file just for this.\n        source = \"\"\"\n            BAKE, 0N TEND, 01 TALL\n            FISH, -1N TALL, -11 TOUR: slot\n            DOWN, 0N [cold] TOUR, 0N [echo] TOUR: hang\n            WRAP, _11 PORK, 0N TEND\n            FINE, 11 DRAW, 0N BULK\n            HERE, 1N TALL, 1N TOUR, /11 HOST: mask\n            GOAL, 11 TEND, 1N AIDS\n            ZONE, 0N TEND, /1N TALL\n            LUCK, 0N< [find] HOST, /11 [hill] HOST\n            AIDS, XX VARY, ?? WRAP\n        \"\"\"\n        actual = op_tk.run(source, \"create\", {\"df\": 1}, {\"df\": \"DF\"})\n        expected = \"\"\"\n            BAKE, 0N TEND, 01 TALL\n            DF, -1N TALL, -11 TOUR: slot\n            DOWN, 0N [cold] TOUR, 0N [echo] TOUR: hang\n            DF, _11 PORK, 0N TEND\n            DF, 11 DRAW, 0N BULK\n            HERE, 1N TALL, 1N TOUR, /11 HOST: mask\n            DF, 11 TEND, 1N AIDS\n            ZONE, 0N TEND, /1N TALL\n            LUCK, 0N< [find] HOST, /11 [hill] HOST\n            AIDS, XX VARY, ?? WRAP\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_fix_cards(self):\n        source = \"A, ON B, No No\"\n        actual = op_tk.run(source, \"fix\", {\"cards\": 1}, {}).strip()\n        expected = \"A, 0N B, 0N No\"\n        self.assertEqual(actual, expected)\n\n    def test_delete_cards(self):\n        source = \"A, 01 B, 0N C\"\n        actual = op_tk.run(source, \"delete\", {\"cards\": 1}, {}).strip()\n        expected = \"A, XX B, XX C\"\n        self.assertEqual(actual, expected)\n\n    def test_change_capitalization_cards(self):\n        source = \"A, 0N B, _1N No\"\n        actual = op_tk.run(source, \"lower\", {\"cards\": 1}, {}).strip()\n        expected = \"A, 0n B, _1n No\"\n        self.assertEqual(actual, expected)\n        source = expected\n        actual = op_tk.run(source, \"upper\", {\"cards\": 1}, {}).strip()\n        expected = \"A, 0N B, _1N No\"\n        self.assertEqual(actual, expected)\n    \n    def test_infer_roles(self):\n\n        # Cases *N vs *1\n\n        source = \"Rule, 0N Else, 11 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 0N [Rule] Else, 11 Peel\"\n        self.assertEqual(actual, expected)\n        \n        source = \"Rule, 1N Else, 11 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 1N [Rule] Else, 11 Peel\"\n        self.assertEqual(actual, expected)\n\n        source = \"Rule, 0N Else, 01 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 0N [Rule] Else, 01 Peel\"\n        self.assertEqual(actual, expected)\n        \n        source = \"Rule, 1N Else, 01 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 1N [Rule] Else, 01 Peel\"\n        self.assertEqual(actual, expected)\n\n        source = \"Rule, XX Else, 11 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, XX [Rule] Else, 11 Peel\"\n        self.assertEqual(actual, expected)\n\n        source = \"Rule, XX Else, 01 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, XX [Rule] Else, 01 Peel\"\n        self.assertEqual(actual, expected)\n\n        # Cases *1 vs *1\n        \n        source = \"Rule, 01 Else, 11 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 01 [Rule] Else, 11 Peel\"\n        self.assertEqual(actual, expected)\n        \n        source = \"Rule, 11 Else, 11 Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 11 [Rule] Else, 11 [Rule] Peel\"  # slightly overkill\n        self.assertEqual(actual, expected)\n\n        # Other cases\n\n        source = \"Rule, 0N Else, 1N Peel\"\n        actual = op_tk.run(source, \"create\", {\"roles\": 1}, {}).strip()\n        expected = \"Rule, 0N Else, 1N Peel\"\n        self.assertEqual(actual, expected)\n\n    \nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_rewrite_decompose.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite import (\n    _explode as explode,\n    _drain as drain,\n    _split as split,\n)\n\n\nclass TestUpdater(unittest.TestCase):\n    def test_split(self):\n        source = \"\"\"\n            Easy, 0N Team, 0N Tire, 11 Bath: foo, bar\n            Plea, 0N Toll, 01 Calm, 0N Path\n            Busy, 0N Vast, 0N Goal, 0N Chop\n            Pole, 0N Snap, 11 Vary, 0N Tide, 1N Peak\n            Loop, 0N Soil, 11 Cute\n            +Aunt, 01 Dirt, 1N Path, 0N Meat\n            Come, -01 Suit, 1N Plea, 0N Each\n            Body, 11> File, 1N< Dust, 0N Peak\n            Odds, 1N Tone, 01 Peak, 0N Bold, 0N Slip: item, snap\n            Chef, 1N Skip, 01 City, 0N Cell: bold [VARCHAR(42)], dead [DATE]\n            Victima, 11 Tradidit, 01 Periculosum, 0N Superbiam\n            Clamorem, 01 Priorum, 0N Iret, 11 Loquatur\n            Tuam, 11 Initiis, 01 Genua, 01 Haesit\n            Commemorat, 01 Furius, 01 Sermonis, 01 Panem\n            Anus, 11 Dianam, 11 Emplastrum, 1N Piscium\n        \"\"\"\n        actual = split.run(source)\n        expected = \"\"\"\n            Easy0, 11 Bath, 0N Team: foo, bar\n            Easy1, 11 Bath, 0N Tire\n            Plea0, 01 Calm, 0N Toll\n            Plea1, 01 Calm, 0N Path\n            Busy, 0N Vast, 0N Goal, 0N Chop\n            Pole0, 11 Vary, 0N Snap\n            Pole1, 11 Vary, 0N Tide\n            Pole2, 11 Vary, 1N Peak\n            Loop, 0N Soil, 11 Cute\n            +Aunt0, 01 Dirt, 1N Path\n            +Aunt1, 01 Dirt, 0N Meat\n            Come0, -01 Suit, 1N Plea\n            Come1, -01 Suit, 0N Each\n            Body0, 11> File, 1N< Dust\n            Body1, 11> File, 0N Peak\n            Odds0, 01 Peak, 1N Tone: item, snap\n            Odds1, 01 Peak, 0N Bold\n            Odds2, 01 Peak, 0N Slip\n            Chef0, 01 City, 1N Skip: bold [VARCHAR(42)], dead [DATE]\n            Chef1, 01 City, 0N Cell\n            Victima0, 11 Tradidit, 01 Periculosum\n            Victima1, 11 Tradidit, 0N Superbiam\n            Clamorem0, 11 Loquatur, 01 Priorum\n            Clamorem1, 11 Loquatur, 0N Iret\n            Tuam0, 11 Initiis, 01 Genua\n            Tuam1, 11 Initiis, 01 Haesit\n            Commemorat0, 01 Furius, 01 Sermonis\n            Commemorat1, 01 Furius, 01 Panem\n            Anus0, 11 Dianam, 11 Emplastrum\n            Anus1, 11 Dianam, 1N Piscium\n         \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_explode_weak(self):\n        source = \"\"\"\n            Wake: tend, bath\n            Bowl, 0N Wake, 1N Move, 0N Poet: turn, from\n            Poet: edge, skip\n            Move: aids\n        \"\"\"\n        actual = explode.run(source, {\"weak\": True})\n        expected = \"\"\"\n            Wake: tend, bath\n            Bowl: _turn, from\n            DF, _11 Bowl, 0N Wake\n            DF, _11 Bowl, 1N Move\n            DF, _11 Bowl, 0N Poet\n            Poet: edge, skip\n            Move: aids\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())   \n        actual = explode.run(source)\n        expected = \"\"\"\n            Wake: tend, bath\n            Bowl: id. bowl, turn, from\n            DF, 11 Bowl, 0N Wake\n            DF, 11 Bowl, 1N Move\n            DF, 11 Bowl, 0N Poet\n            Poet: edge, skip\n            Move: aids\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())   \n\n    def test_explode_arity(self): # TODO: more cases\n        source = \"\"\"\n            Edge: what, call\n            Love, 0N Edge, 1N Ruin: toss, noon\n            Ruin: area, slip\n            Gene: five, away\n            Hate, 0N Gene, 1N Rain\n            Rain: iron, pose\n        \"\"\"\n        actual = explode.run(source, {\"arity\": \"3\"})\n        expected = source # no change\n        self.assertEqual(actual.strip(), expected.strip())   \n        actual = explode.run(source, {\"arity\": \"2\"})\n        expected = \"\"\"\n            Edge: what, call\n            Love: id. love, toss, noon\n            DF, 11 Love, 0N Edge\n            DF, 11 Love, 1N Ruin\n            Ruin: area, slip\n            Gene: five, away\n            Hate: id. hate\n            DF, 11 Hate, 0N Gene\n            DF, 11 Hate, 1N Rain\n            Rain: iron, pose\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())   \n\n    def test_explode_cluster(self):\n        source = \"\"\"\n            Date: Date\n            Réserver, /1N Client, 1N Chambre, 0N Date: Durée\n            Chambre: Numéro, Prix\n            Client: Id. client, Nom client\n        \"\"\"\n        actual = explode.run(source, {\"weak\": True})\n        expected = \"\"\"\n            Date: Date\n            Réserver: _Durée\n            DF, 11 Réserver, 1N Client\n            DF, _11 Réserver, 1N Chambre\n            DF, _11 Réserver, 0N Date\n            Chambre: Numéro, Prix\n            Client: Id. client, Nom client\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())   \n\n    def test_drain(self):\n        source = \"\"\"\n            Wake: tend, bath\n            Bowl, 0N Wake, 11 Move: turn [type 1], from [type 2]\n            Move: aids\n            Hour, 01 Poet, 11 Move: chew\n            Poet: edge, skip\n            Draw, 01 Poet, 0N Rice: road\n            Rice: easy, link\n        \"\"\"\n        actual = drain.run(source)\n        expected = \"\"\"\n            Wake: tend, bath\n            Bowl, 0N Wake, 11 Move\n            Move: aids, turn [type 1], from [type 2], chew\n            Hour, 01 Poet, 11 Move\n            Poet: edge, skip\n            Draw, 01 Poet, 0N Rice: road\n            Rice: easy, link\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_rewrite_grow.py",
    "content": "import unittest\nimport random\nimport gettext\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite._grow import run as grow\n\nclass TestGrow(unittest.TestCase):\n\n    def test_default(self):\n        gettext.NullTranslations().install()\n        random.seed(1)\n        actual = grow(\"FOO: bar, biz\", {})\n        expected = \"\"\"\n            FOO: bar, biz\n            Reflexive 2_, 1N FOO, 0N FOO\n            Entity 3_: id 3 1, attr 3 2\n            Binary 4_, 1N Entity 3_, 11 FOO: attr 4 1\n            Reflexive 5_, 0N Entity 3_, 11 Entity 3_\n            Entity 6_: id 6 1, _id 6 2, attr 6 3\n            Ternary 7_, 1N Entity 6_, 1N FOO, 1N Entity 3_\n            Entity 8_: id 8 1, attr 8 2, attr 8 3, attr 8 4\n            Binary 9_, 0N Entity 8_, 0N Entity 6_\n            Entity 10_: id 10 1, attr 10 2, attr 10 3, attr 10 4\n            Binary 11_, 0N Entity 10_, 1N Entity 8_\n            Entity 12_: id 12 1\n            Binary 13_, 0N Entity 12_, 1N Entity 8_: attr 13 1\n            Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n            Binary 15_, 11 Entity 14_, 01 Entity 10_\n            Entity 16_: id 16 1, attr 16 2\n            Binary 17_, 0N Entity 16_, 1N Entity 14_\n            Binary 18_, 1N Entity 14_, 01 Entity 10_\n        \"\"\".replace(\"    \", \"\")\n        self.assertEqual(actual.strip(), expected.strip())\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_rewrite_labels.py",
    "content": "import unittest\nimport random\nimport gettext\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite import op_tk\n\ngettext.NullTranslations().install()\n\nclass TestUpdateLabels(unittest.TestCase):\n\n    def test_upper(self):\n        source = \"composer, 0n [composée] pièce, 0n [composante] pièce: quantité\"\n        actual = op_tk.run(source, \"upper\", {\"labels\": \"\"}, {})\n        expected = \"COMPOSER, 0n [composée] PIÈCE, 0n [composante] PIÈCE: QUANTITÉ\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_obfuscate(self):\n        source = \"\"\"\n            Vitae justo: lobortis, purus\n            adipiscing, 0N Curabitur, 0N Vitae justo, 0N DATE2\n            DATE2: date\n            Pharetra, 0N Curabitur, 0N DATE, 0N Vitae justo: massa\n            Curabitur: blandit, suscipit\n            Porttitor, 1N Rhoncus, 0N DATE2\n            DATE: date\n            Imperdiet, 0N Egestas, 0N Curabitur, 0N DATE\n            Rhoncus: dolor a, bibendum, euismod, consectetuer, leo\n            Egestas: vivamus, semper, aliquam\n            Ultricies, 11 Rhoncus, 0N Egestas\n        \"\"\"\n        subargs = {\"labels\": \"en4.txt\"}\n        params = {\"script_directory\": \"mocodo\", \"df\": \"DF\"}\n        random.seed(42)\n        actual = op_tk.run(source, \"randomize\", subargs, params)\n        expected = \"\"\"\n            Feel: turn, grin\n            land, 0N Near, 0N Feel, 0N SILK\n            SILK: debt\n            Shoe, 0N Near, 0N LOSS, 0N Feel: poet\n            Near: stir, auto\n            Slew, 1N Tape, 0N SILK\n            LOSS: debt\n            Knee, 0N Code, 0N Near, 0N LOSS\n            Tape: they, bath, unit, haul, draw\n            Code: four, duck, icon\n            Golf, 11 Tape, 0N Code\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_obfuscate_df(self):\n        source = \"\"\"\n            DF, 11 Curabitur, 0N Vitae justo, 0N DATE2\n            DF, 1N Rhoncus, 11 DATE2\n            DF, 11 Rhoncus, 0N Egestas\n        \"\"\"\n        subargs = {\"labels\": \"en4.txt\"}\n        params = {\"script_directory\": \"mocodo\", \"df\": \"DF\"}\n        random.seed(42)\n        actual = op_tk.run(source, \"randomize\", subargs, params)\n        expected = \"\"\"\n            FEEL, 11 Turn, 0N Grin, 0N LAND\n            NEAR, 1N Silk, 11 LAND\n            DEBT, 11 Silk, 0N Shoe\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n    \n    def test_obfuscate_pool_too_small(self):\n        source = \"\"\"\n            DF, 11 Curabitur, 0N Vitae justo, 0N DATE2\n            DF, 1N Rhoncus, 11 DATE2\n            DF, 11 Rhoncus, 0N Egestas\n        \"\"\"\n        subargs = {\"labels\": \"test/test_data/small_pool.txt\"}\n        params = {\"script_directory\": \"mocodo\", \"df\": \"DF\"}\n        random.seed(42)\n        self.assertRaises(op_tk.MocodoError, op_tk.run, source, \"randomize\", subargs, params)\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_rewrite_types.py",
    "content": "import unittest\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\n\nfrom mocodo.rewrite.types import guess_types, create_type_placeholders\n\n\nclass TestUpdateTypes(unittest.TestCase):\n\n    def test_create(self):\n        source = \"\"\"\n            MEAN: wash, rest [], king [int],\n            HERE, 0N NICE, 0N MEAN: wood, much [], stop [int]\n            NICE: _poke, news [], , lawn [int]\n        \"\"\"\n        actual = create_type_placeholders(source, \"TODO\")\n        expected = \"\"\"\n            MEAN: wash [TODO], rest [], king [int],\n            HERE, 0N NICE, 0N MEAN: wood [TODO], much [], stop [int]\n            NICE: _poke [TODO], news [], , lawn [int]\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\n    def test_guess_types(self):\n        source = \"\"\"\n            ALREADY_TYPED: foo [int], bar [float], baz [date]\n            EMPTY_BRACKETS: foo [], bar [], baz []\n            NON_TYPABLE: foo, bar, baz\n            TYPABLE: person id, name, birth date\n        \"\"\"\n        actual = guess_types(source, {\"script_directory\": \"mocodo\"})\n        expected = \"\"\"\n            ALREADY_TYPED: foo [int], bar [float], baz [date]\n            EMPTY_BRACKETS: foo [], bar [], baz []\n            NON_TYPABLE: foo [], bar [], baz []\n            TYPABLE: person id [VARCHAR(8)], name [VARCHAR(255)], birth date [DATE]\n        \"\"\"\n        self.assertEqual(actual.strip(), expected.strip())\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_string_tools.py",
    "content": "import unittest\nfrom pathlib import Path\n\n__import__(\"sys\").path[0:0] = [\"mocodo\"]\nfrom mocodo.tools.string_tools import *\n\n\nclass StringToolsTest(unittest.TestCase):\n    \n    def test_wrap_label(self):\n        sample = [\n            \"Adresse 1\",\n            \"Adresse 1 du détenteur\",\n            \"Apporteur\",\n            \"Ayant-droit\",\n            \"Code pays\",\n            \"Code pays de résidence du détenteur\",\n            \"Code pays détenteur\",\n            \"Code postal\",\n            \"Commune du détenteur\",\n            \"Date de création\",\n            \"Date de création en BDNI\",\n            \"Date de réception\",\n            \"Date de réception en BDNI\",\n            \"Nom\",\n            \"Nom du détenteur\",\n            \"Numéro de SIREN du détenteur\",\n            \"Numéro détenteur\",\n            \"Raison sociale\",\n            \"Raison sociale ou situation civile\",\n        ]\n        wrapped = [\n            [\"Adresse\", \"1\"],\n            [\"Adresse 1\", \"du\", \"détenteur\"],\n            [\"Apporteur\"],\n            [\"Ayant-\", \"droit\"],\n            [\"Code pays\"],\n            [\"Code pays de\", \"résidence du\", \"détenteur\"],\n            [\"Code pays\", \"détenteur\"],\n            [\"Code\", \"postal\"],\n            [\"Commune\", \"du\", \"détenteur\"],\n            [\"Date de\", \"création\"],\n            [\"Date de\", \"création\", \"en BDNI\"],\n            [\"Date de\", \"réception\"],\n            [\"Date de\", \"réception\", \"en BDNI\"],\n            [\"Nom\"],\n            [\"Nom du\", \"détenteur\"],\n            [\"Numéro de\", \"SIREN du\", \"détenteur\"],\n            [\"Numéro\", \"détenteur\"],\n            [\"Raison\", \"sociale\"],\n            [\"Raison\", \"sociale ou\", \"situation\", \"civile\"],\n        ]\n        for (label, expected) in zip(sample, wrapped):\n            self.assertEqual(wrap_label(label), expected)\n\n    def test_rstrip_digit_or_underline(self):\n        self.assertEqual(rstrip_digit_or_underline(\"foo\"), \"foo\")\n        self.assertEqual(rstrip_digit_or_underline(\"foo1\"), \"foo\")\n        self.assertEqual(rstrip_digit_or_underline(\"foo12\"), \"foo1\")\n        self.assertEqual(rstrip_digit_or_underline(\"\"), \"\")\n        self.assertEqual(rstrip_digit_or_underline(\"1\"), \"\")\n        self.assertEqual(rstrip_digit_or_underline(\"foo_\"), \"foo\")\n        self.assertEqual(rstrip_digit_or_underline(\"foo1_\"), \"foo1\")\n        self.assertEqual(rstrip_digit_or_underline(\"_\"), \"\")\n\n    def test_surrounds(self):\n        self.assertTrue(surrounds(\"(foobar)\", \"()\"))\n        self.assertTrue(surrounds(\"_foobar_\", \"_\"))\n        self.assertTrue(surrounds(\"_foobar_\", \"__\"))\n        self.assertFalse(surrounds(\"(foobar)\", \")(\"))\n        self.assertTrue(surrounds(\"()\", \"()\"))\n        self.assertFalse(surrounds(\"\", \"()\"))\n        self.assertFalse(surrounds(\"foobar\", \"fo\"))\n\n    def test_snake(self):\n        self.assertEqual(snake(\"foo\"), \"foo\")\n        self.assertEqual(snake(\"Foo\"), \"Foo\")\n        self.assertEqual(snake(\"FOO\"), \"FOO\")\n        self.assertEqual(snake(\"fooBar\"), \"foo_Bar\")\n        self.assertEqual(snake(\"fooBar\"), \"foo_Bar\")\n        self.assertEqual(snake(\"FOOBar\"), \"FOOBar\")\n        self.assertEqual(snake(\"fooBAR\"), \"foo_BAR\")\n        self.assertEqual(snake(\"foo bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo  bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo-bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo--bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo_bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo__bar\"), \"foo_bar\")\n        self.assertEqual(snake(\"foo1bar\"), \"foo_1_bar\")\n        self.assertEqual(snake(\"foo1Bar\"), \"foo_1_Bar\")\n        self.assertEqual(snake(\"foO1Bar\"), \"fo_O_1_Bar\")\n        self.assertEqual(snake(\"FOO BAR\"), \"FOO_BAR\")\n        self.assertEqual(snake(\"-FOO-BAR-\"), \"FOO_BAR\")\n        self.assertEqual(snake(\"_FOO_BAR_\"), \"FOO_BAR_\")\n        self.assertEqual(snake(\"_FOO_BAR1\"), \"FOO_BAR1\")\n    \n    def test_camel(self):\n        self.assertEqual(camel(\"foo\"), \"foo\")\n        self.assertEqual(camel(\"Foo\"), \"foo\")\n        self.assertEqual(camel(\"FOO\"), \"foo\")\n        self.assertEqual(camel(\"fooBar\"), \"fooBar\")\n        self.assertEqual(camel(\"FooBar\"), \"fooBar\")\n        self.assertEqual(camel(\"FOOBar\"), \"foobar\")\n        self.assertEqual(camel(\"fooBAR\"), \"fooBar\")\n        self.assertEqual(camel(\"foo bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo  bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo-bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo--bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo_bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo__bar\"), \"fooBar\")\n        self.assertEqual(camel(\"foo1bar\"), \"foo1Bar\")\n        self.assertEqual(camel(\"foo1Bar\"), \"foo1Bar\")\n        self.assertEqual(camel(\"foO1Bar\"), \"foO1Bar\")\n        self.assertEqual(camel(\"FOO BAR\"), \"fooBar\")\n        self.assertEqual(camel(\"-FOO-BAR-\"), \"fooBar\")\n        self.assertEqual(camel(\"-FOO-BAR_\"), \"fooBar_\")\n        self.assertEqual(camel(\"-FOO-BAR1\"), \"fooBar1\")\n    \n    def test_pascal(self):\n        self.assertEqual(pascal(\"foo\"), \"Foo\")\n        self.assertEqual(pascal(\"Foo\"), \"Foo\")\n        self.assertEqual(pascal(\"FOO\"), \"Foo\")\n        self.assertEqual(pascal(\"fooBar\"), \"FooBar\")\n        self.assertEqual(pascal(\"FooBar\"), \"FooBar\")\n        self.assertEqual(pascal(\"FOOBar\"), \"Foobar\")\n        self.assertEqual(pascal(\"fooBAR\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo  bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo-bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo--bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo_bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo__bar\"), \"FooBar\")\n        self.assertEqual(pascal(\"foo1bar\"), \"Foo1Bar\")\n        self.assertEqual(pascal(\"foo1Bar\"), \"Foo1Bar\")\n        self.assertEqual(pascal(\"foO1Bar\"), \"FoO1Bar\")\n        self.assertEqual(pascal(\"FOO BAR\"), \"FooBar\")\n        self.assertEqual(pascal(\"-FOO-BAR-\"), \"FooBar\")\n        self.assertEqual(pascal(\"-FOO-BAR_\"), \"FooBar_\")\n        self.assertEqual(pascal(\"-FOO-BAR1\"), \"FooBar1\")\n\n    def test_aggressive_split(self):\n        f = aggressive_split\n        self.assertEqual(f(''), [])\n        self.assertEqual(f('p'), ['p'])\n        self.assertEqual(f('3-'), ['3'])\n        self.assertEqual(f('NOM'), ['NOM'])\n        self.assertEqual(f('CONTRÔLER'), ['CONTRÔLER'])\n        self.assertEqual(f('Nom'), ['Nom'])\n        self.assertEqual(f('nom'), ['nom'])\n        self.assertEqual(f('Nom lieu'), ['Nom', 'lieu'])\n        self.assertEqual(f('nom de compte'), ['nom', 'de', 'compte'])\n        self.assertEqual(f('Nom_lieu'), ['Nom', 'lieu'])\n        self.assertEqual(f('Nom_Lieu'), ['Nom', 'Lieu'])\n        self.assertEqual(f('NomLieu'), ['Nom', 'Lieu'])\n        self.assertEqual(f('nomlieu'), ['nomlieu'])\n        self.assertEqual(f('Gratte-ciel'), ['Gratte', 'ciel'])\n        self.assertEqual(f('Identité_pays'), ['Identité', 'pays'])\n        self.assertEqual(f('ID_Produit'), ['ID', 'Produit'])\n        self.assertEqual(f('FolderID'), ['Folder', 'ID'])\n        self.assertEqual(f('IdVoyage-'), ['Id', 'Voyage'])\n        self.assertEqual(f('N°Lieu'), ['N', 'Lieu'])\n        self.assertEqual(f('N°lieu'), ['N', 'lieu'])\n        self.assertEqual(f('NumLieuTournage-'), ['Num', 'Lieu', 'Tournage'])\n        self.assertEqual(f('nomPays_EN'), ['nom', 'Pays', 'EN'])\n        self.assertEqual(f('Conditions(Affichage)'), ['Conditions', 'Affichage'])\n        self.assertEqual(f('Conditions (Affichage)'), ['Conditions', 'Affichage'])\n        self.assertEqual(f('COMPOSE3'), ['COMPOSE', '3'])\n        self.assertEqual(f('téléphone2'), ['téléphone', '2'])\n        self.assertEqual(f('téléphone23'), ['téléphone', '23'])\n        self.assertEqual(f('téléphone 2'), ['téléphone', '2'])\n        self.assertEqual(f('beginning-date'), ['beginning', 'date'])\n        self.assertEqual(f('latitude_L'), ['latitude', 'L'])\n        self.assertEqual(f('id_insert → equipement_id'), ['id', 'insert', 'equipement', 'id'])\n        self.assertEqual(f('CNIPays'), ['CNIPays'])\n        self.assertEqual(f('réf. client'), ['réf', 'client'])\n        self.assertEqual(f('kWday_summer'), ['k', 'Wday', 'summer'])\n        self.assertEqual(f('DescriptionŒuvre'), ['Description', 'Œuvre'])\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_zoo.py",
    "content": "import json\nimport time\nfrom pathlib import Path\nimport shutil\nfrom mocodo.argument_parser import parsed_arguments, init_localization\nfrom mocodo.common import Common\nfrom mocodo.convert.read_template import read_template\nfrom mocodo.font_metrics import font_metrics_factory\nfrom mocodo.mcd import Mcd\nfrom mocodo.convert.relations import Relations\nfrom mocodo.mocodo_error import MocodoError\nimport random\nimport re\nfrom mocodo.convert import (\n    _chen as chen,\n    _crow as crow,\n    _uml as uml,\n)\nfrom mocodo.rewrite import (\n    op_tk,\n    _explode as explode,\n    _drain as drain,\n    _split as split,\n    _drown as drown,\n)\nfrom mocodo.rewrite.arrange_bb import arrange\nfrom mocodo.mcd_to_svg import main as dump_mcd_to_svg\nimport os\n\n\nTEMPLATE_DIR = Path(\"mocodo/resources/relation_templates/\")\nZOO_DIR = Path(\"test/zoo\")\n\ndef save(path, text):\n    text = re.sub(r\"(?m)^.+Generated by Mocodo.*\\n+\", \"\", text)\n    Path(path).write_text(text, encoding=\"utf8\")\n\n\ndef main():\n\n    def dump_static_svg(mcd, mcd_path):\n        output_name = params[\"output_name\"] = str(mcd_path)[:-4]\n        Path(f\"{output_name}_geo.json\").unlink(missing_ok=True)\n        dump_mcd_to_svg(mcd, common, suppress_mocodo_header=True)\n        if Path(f\"{output_name}_static.svg\").is_file():\n            Path(f\"{output_name}.svg\").unlink()\n            Path(f\"{output_name}_static.svg\").rename(f\"{output_name}.svg\")\n        Path(f\"{output_name}_geo.json\").unlink(missing_ok=True)\n    \n    def convert_dot_to_svg(dot_path):\n        svg_path = dot_path.with_suffix(\".svg\")\n        os.system(f\"dot -Tsvg {dot_path} -o {svg_path}\")\n        return svg_path\n\n    def may_dump_rewritten_version(subfolder, source, stem, operation_name, subargs=None):\n        try:\n            module = globals()[operation_name] # e.g., explode, drain, ...\n        except KeyError:\n            module = op_tk\n        result = module.run(source, op_name=operation_name, subargs=subargs, params=params).rstrip()\n        suffix = \",\".join(f\"{k}={v}\" if v else k for (k, v) in subargs.items())\n        if suffix:\n            suffix = f\"_{suffix}\"\n        new_mcd_path = subfolder / f\"{stem}_rw_{operation_name}{suffix}.mcd\"\n        if result == source:\n            result = \"% same as the source file\"\n            save(new_mcd_path, result + \"\\n\")\n            return\n        for path in subfolder.glob(f\"{stem}_rw_{operation_name}*.mcd\"):\n            if result == path.read_text(encoding=\"utf8\"):\n                result = f\"% same as {path.name}\"\n                save(new_mcd_path, result + \"\\n\")\n                return\n        if operation_name in (\"explode\", \"split\"):\n            random.seed(42)\n            result = arrange(result, {}, has_expired=lambda: False)\n        mcd = Mcd(result, get_font_metrics, **params)\n        save(new_mcd_path, result + \"\\n\")\n        dump_static_svg(mcd, new_mcd_path)\n\n\n    templates = []\n    template_index = json.loads(Path(TEMPLATE_DIR / \"_index.json\").read_text(encoding=\"utf8\"))\n    for name in template_index:\n        if re.match(r\"html|markdown|latex|text\", name):\n            name += \"-bce\"\n        elif re.match(r\"mysql|oracle|postgresql|sqlite|mssql\", name):\n            continue\n        templates.append(read_template(name, TEMPLATE_DIR))\n\n    params = parsed_arguments([])\n    params[\"guess_title\"] = False\n    params[\"id_gutter_visibility\"] = \"auto\"\n    params[\"id_gutter_strong_string\"] = \"ID\"\n    params[\"id_gutter_weak_string\"] = \"id\"\n    params[\"id_gutter_alts\"] = dict(zip(\"123456789\", \"123456789\"))\n    params[\"guess_title\"] = False\n    params[\"language\"] = \"fr\"\n    params[\"df\"] = \"DF\"\n    params[\"seed\"] = 42 # only to be dumped in graphviz files\n    common = Common(params)\n    init_localization(\"fr\")\n    get_font_metrics = font_metrics_factory(params)\n    for path in ZOO_DIR.glob(\"*/*\"):\n        if path.is_dir():\n            shutil.rmtree(path, ignore_errors=True) # suppress all subfolders\n        elif not path.name.startswith(\"_\"):\n            path.unlink() # suppress all files except those starting with \"_\"\n    for source_path in sorted(ZOO_DIR.glob(\"*/*.mcd\")):\n        print(f\"Processing {source_path.name}\")\n        params[\"title\"] = source_path.parent.name\n\n        source = source_path.read_text(encoding=\"utf8\").rstrip()\n\n        # Create some rewritten versions of the source file.\n        subfolder = Path(source_path.parent / \"rewritten\")\n        subfolder.mkdir(exist_ok=True)\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 2, \"weak\": \"\"})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 2.5, \"weak\": \"\"})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 3, \"weak\": \"\"})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 2})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 2.5})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"explode\", {\"arity\": 3})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"drain\", {})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"split\", {})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"drown\", {})\n        may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"create\", {\"df_arrows\": \"across\"})\n        if source_path.name.startswith(\"_triple_N11\"):\n            may_dump_rewritten_version(subfolder, source, source_path.stem[1:], \"create\", {\"cifs\": \"\"})\n\n        mcd = Mcd(source, get_font_metrics, **params)\n\n        # Create some converted files.\n        subfolder = Path(source_path.parent / \"exported\")\n        subfolder.mkdir(exist_ok=True)\n\n        text = chen.run(source, {}, common, testing=True).replace(\"    \", \"\") + \"\\n\"\n        save(subfolder / f\"{source_path.stem[1:]}_erd_chen.txt\", text)\n\n        text = chen.run(source, {\"attrs\": 1}, common)[\"text\"]\n        save(subfolder / f\"{source_path.stem[1:]}_erd_chen.gv\", text)\n        convert_dot_to_svg(subfolder / f\"{source_path.stem[1:]}_erd_chen.gv\")\n\n        text = uml.run(source, {\"plantuml\": \"-\"}, common)[\"text\"] # delete the default preamble\n        save(subfolder / f\"{source_path.stem[1:]}_uml.puml\", text)\n\n        try:\n            text = crow.run(source, {\"mmd\": True}, common)[\"text\"]\n            save(subfolder / f\"{source_path.stem[1:]}_erd_crow.mmd\", text)\n\n            text = crow.run(source, {\"gv\": True}, common)[\"text\"]\n            save(subfolder / f\"{source_path.stem[1:]}_erd_crow.gv\", text)\n            convert_dot_to_svg(subfolder / f\"{source_path.stem[1:]}_erd_crow.gv\")\n        except AssertionError:\n            save(subfolder / f\"{source_path.stem[1:]}_erd_crow.mmd\", \"Not implemented for n-ary associations.\")\n\n        # Create the non-sql output files.\n        subfolder = Path(source_path.parent / \"mld\")\n        subfolder.mkdir(exist_ok=True)\n        for template in templates:\n            if template[\"extension\"] in (\"sql\", \"dbml\", \"d2\"):\n                continue\n            relations = Relations(mcd, params)\n            output = relations.get_text(template).strip() + \"\\n\"\n            output_path = subfolder / f\"{source_path.stem[1:]}{template['stem_suffix']}.{template['extension']}\"\n            save(output_path, output)\n            if template[\"extension\"] == \"gv\":\n                convert_dot_to_svg(output_path)\n            elif template[\"extension\"] == \"mcd\":\n                try:\n                    relational_diagram_mcd = Mcd(output, get_font_metrics, **params)\n                except MocodoError as e:\n                    assert e.args[0].startswith(\"Mocodo Err.4\") # Empty MCD\n                else:\n                    dump_static_svg(relational_diagram_mcd, output_path)\n\n        # Create the svg output file.\n        dump_static_svg(mcd, source_path.parent / f\"{source_path.stem[1:]}.mcd\")\n\n        # Create the dbml and d2 output files.\n        subfolder = Path(source_path.parent / \"ddl\")\n        subfolder.mkdir(exist_ok=True)\n        for template in templates:\n            if template[\"extension\"] in (\"dbml\", \"d2\"):\n                output = relations.get_text(template).strip() + \"\\n\"\n                save(subfolder / f\"{source_path.stem[1:]}{template['stem_suffix']}.{template['extension']}\", output)\n\n        # Create the sql output files. Warning: modifies source. Must be final.\n        subfolder = Path(source_path.parent / \"ddl\")\n        subfolder.mkdir(exist_ok=True)\n        source = op_tk.run(source, \"create\", {\"types\": None}, params) # guess types\n        source = op_tk.run(source, \"ascii\", {\"labels\": 1, \"roles\": 1}, params)\n        source = op_tk.run(source, \"snake\", {\"labels\": 1}, params)\n        source = op_tk.run(source, \"lower\", {\"attrs\": 1, \"roles\": 1}, params)\n        source = op_tk.run(source, \"upper\", {\"boxes\": 1}, params)\n        mcd = Mcd(source, get_font_metrics, **params)\n        for template in templates:\n            if template[\"extension\"] != \"sql\":\n                continue\n            relations = Relations(mcd, params)\n            output = relations.get_text(template).strip() + \"\\n\"\n            save(subfolder / f\"{source_path.stem[1:]}{template['stem_suffix']}.sql\", output)\n\ndef test_launch_snapshot(capsys):\n    with capsys.disabled():\n        print(\"\\nCancel the long snapshot calculation by pressing Ctrl+C within 5 seconds\", end=\"\")\n        for _ in range(5):\n            time.sleep(1)\n            print(\".\", end=\"\", flush=True)\n        print(\"\\nLet's be crazy!\")\n        main()\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "test/zoo/alt/_alt_0.mcd",
    "content": "CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail\nFOO: foo, 1_bar, 12_biz, 2_buz, 3_qux, 123_quux\nUTILISER: 1_carnet, 02_projet, 12_technicien\n"
  },
  {
    "path": "test/zoo/alt/ddl/alt_0_ddl.d2",
    "content": "\"CLIENT\": { shape: sql_table\n  \"Réf. client\": VARCHAR(42) {constraint: PK}\n  \"Nom\":         VARCHAR(42) {constraint: UNQ1}\n  \"Prénom\":      VARCHAR(42) {constraint: UNQ1}\n  \"Adresse\":     VARCHAR(42) \n  \"Mail\":        VARCHAR(42) {constraint: UNQ2}\n}\n\n\"FOO\": { shape: sql_table\n  \"foo\":  VARCHAR(42) {constraint: PK}\n  \"bar\":  VARCHAR(42) {constraint: UNQ1}\n  \"biz\":  VARCHAR(42) {constraint: [UNQ1; UNQ2]}\n  \"buz\":  VARCHAR(42) {constraint: UNQ2}\n  \"qux\":  VARCHAR(42) {constraint: UNQ3}\n  \"quux\": VARCHAR(42) {constraint: [UNQ1; UNQ2; UNQ3]}\n}\n\n\"UTILISER\": { shape: sql_table\n  \"carnet\":     VARCHAR(42) {constraint: [PK; UNQ1]}\n  \"projet\":     VARCHAR(42) {constraint: [PK; UNQ2]}\n  \"technicien\": VARCHAR(42) {constraint: [UNQ1; UNQ2]}\n}\n"
  },
  {
    "path": "test/zoo/alt/ddl/alt_0_ddl.dbml",
    "content": "Table \"CLIENT\" {\n  \"Réf. client\" VARCHAR(42) [pk, NOT NULL]\n  \"Nom\"         VARCHAR(42)\n  \"Prénom\"      VARCHAR(42)\n  \"Adresse\"     VARCHAR(42)\n  \"Mail\"        VARCHAR(42)\n  Indexes {\n    (\"Nom\", \"Prénom\") [unique]\n    \"Mail\" [unique]\n  }\n}\n\nTable \"FOO\" {\n  \"foo\"  VARCHAR(42) [pk, NOT NULL]\n  \"bar\"  VARCHAR(42)\n  \"biz\"  VARCHAR(42)\n  \"buz\"  VARCHAR(42)\n  \"qux\"  VARCHAR(42)\n  \"quux\" VARCHAR(42)\n  Indexes {\n    (\"biz\", \"quux\", \"buz\") [unique]\n    (\"quux\", \"qux\") [unique]\n    (\"bar\", \"biz\", \"quux\") [unique]\n  }\n}\n\nTable \"UTILISER\" {\n  \"carnet\"     VARCHAR(42) [NOT NULL]\n  \"projet\"     VARCHAR(42) [NOT NULL]\n  \"technicien\" VARCHAR(42)\n  Indexes {\n    (\"carnet\", \"projet\") [pk]\n    (\"technicien\", \"projet\") [unique]\n    (\"carnet\", \"technicien\") [unique]\n  }\n}\n"
  },
  {
    "path": "test/zoo/alt/ddl/alt_0_ddl.sql",
    "content": "CREATE TABLE CLIENT (\n  PRIMARY KEY (ref_client),\n  ref_client VARCHAR(8) NOT NULL,\n  nom        VARCHAR(255),\n  prenom     VARCHAR(255),\n  adresse    VARCHAR(30),\n  mail       VARCHAR(255),\n  UNIQUE (nom, prenom),\n  UNIQUE (mail)\n);\n\nCREATE TABLE FOO (\n  PRIMARY KEY (foo),\n  foo  VARCHAR(42) NOT NULL,\n  bar  VARCHAR(42),\n  biz  VARCHAR(42),\n  buz  VARCHAR(42),\n  qux  VARCHAR(42),\n  quux VARCHAR(42),\n  UNIQUE (bar, biz, quux),\n  UNIQUE (biz, buz, quux),\n  UNIQUE (qux, quux)\n);\n\nCREATE TABLE UTILISER (\n  PRIMARY KEY (carnet, projet),\n  carnet     VARCHAR(42) NOT NULL,\n  projet     VARCHAR(42) NOT NULL,\n  technicien VARCHAR(42),\n  UNIQUE (carnet, technicien),\n  UNIQUE (projet, technicien)\n);\n"
  },
  {
    "path": "test/zoo/alt/exported/alt_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Associative entities\n  1 [label=\"CLIENT\",shape=Mdiamond]\n  7 [label=\"FOO\",shape=Mdiamond]\n  14 [label=\"UTILISER\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Nom\"]\n  4 [label=\"Prénom\"]\n  5 [label=\"Adresse\"]\n  6 [label=\"Mail\"]\n  9 [label=\"bar\"]\n  10 [label=\"biz\"]\n  11 [label=\"buz\"]\n  12 [label=\"qux\"]\n  13 [label=\"quux\"]\n  17 [label=\"technicien\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>Réf.<br/>client</u>>]\n  8 [label=<<u>foo</u>>]\n  15 [label=<<u>carnet</u>>]\n  16 [label=<<u>projet</u>>]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  1 -- 5\n  1 -- 6\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  7 -- 11\n  7 -- 12\n  7 -- 13\n  14 -- 15\n  14 -- 16\n  14 -- 17\n}"
  },
  {
    "path": "test/zoo/alt/exported/alt_0_erd_chen.txt",
    "content": "\n"
  },
  {
    "path": "test/zoo/alt/exported/alt_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CLIENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. client</td></tr>\n        <tr><td> </td><td align=\"left\">Nom</td></tr>\n        <tr><td> </td><td align=\"left\">Prénom</td></tr>\n        <tr><td> </td><td align=\"left\">Adresse</td></tr>\n        <tr><td> </td><td align=\"left\">Mail</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >FOO</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">foo</td></tr>\n        <tr><td> </td><td align=\"left\">bar</td></tr>\n        <tr><td> </td><td align=\"left\">biz</td></tr>\n        <tr><td> </td><td align=\"left\">buz</td></tr>\n        <tr><td> </td><td align=\"left\">qux</td></tr>\n        <tr><td> </td><td align=\"left\">quux</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >UTILISER</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">carnet</td></tr>\n        <tr><td>PK</td><td align=\"left\">projet</td></tr>\n        <tr><td> </td><td align=\"left\">technicien</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n}"
  },
  {
    "path": "test/zoo/alt/exported/alt_0_erd_crow.mmd",
    "content": "erDiagram\n  CLIENT {\n    TYPE Ref_client PK\n    TYPE Nom\n    TYPE Prenom\n    TYPE Adresse\n    TYPE Mail\n  }\n  FOO {\n    TYPE foo PK\n    TYPE bar\n    TYPE biz\n    TYPE buz\n    TYPE qux\n    TYPE quux\n  }\n  UTILISER {\n    TYPE carnet PK\n    TYPE projet PK\n    TYPE technicien\n  }"
  },
  {
    "path": "test/zoo/alt/exported/alt_0_uml.puml",
    "content": "@startuml \"alt\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"CLIENT\") {\n    {field} + pk(Réf. client)\n    {field} + Nom\n    {field} + Prénom\n    {field} + Adresse\n    {field} + Mail\n}\n\nTable(\"FOO\") {\n    {field} + pk(foo)\n    {field} + bar\n    {field} + biz\n    {field} + buz\n    {field} + qux\n    {field} + quux\n}\n\nTable(\"UTILISER\") {\n    {field} + pk(carnet)\n    {field} + pk(projet)\n    {field} + technicien\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCLIENT\tRéf. client\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCLIENT\tNom\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tPrénom\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tAdresse\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tMail\t\t2\tnormal_attribute\tFalse\t\t\t\t\t\nFOO\tfoo\t!\t\tprimary_key\tTrue\t\t\t\t\t\nFOO\tbar\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nFOO\tbiz\t\t12\tnormal_attribute\tFalse\t\t\t\t\t\nFOO\tbuz\t\t2\tnormal_attribute\tFalse\t\t\t\t\t\nFOO\tqux\t\t3\tnormal_attribute\tFalse\t\t\t\t\t\nFOO\tquux\t\t123\tnormal_attribute\tFalse\t\t\t\t\t\nUTILISER\tcarnet\t!\t1\tprimary_key\tTrue\t\t\t\t\t\nUTILISER\tprojet\t!\t2\tprimary_key\tTrue\t\t\t\t\t\nUTILISER\ttechnicien\t\t12\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"alt_0_mld.svg\"/></center><figcaption>MCD <i>alt</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CLIENT</span> (\n    <span class='primary'>Réf. client</span>,\n    <span class='normal'>Nom</span> <sup>u1</sup>,\n    <span class='normal'>Prénom</span> <sup>u1</sup>,\n    <span class='normal'>Adresse</span>,\n    <span class='normal'>Mail</span> <sup>u2</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. client</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CLIENT</i>.</li>\n    <li>Les champs <i>Nom</i> et <i>Prénom</i> étaient déjà de simples attributs de l'entité <i>CLIENT</i>. Il obéit à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>Adresse</i> était déjà un simple attribut de l'entité <i>CLIENT</i>.</li>\n    <li>Le champ <i>Mail</i> était déjà un simple attribut de l'entité <i>CLIENT</i>. Il obéit à la contrainte d'unicité 2.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>FOO</span> (\n    <span class='primary'>foo</span>,\n    <span class='normal'>bar</span> <sup>u1</sup>,\n    <span class='normal'>biz</span> <sup>u1 u2</sup>,\n    <span class='normal'>buz</span> <sup>u2</sup>,\n    <span class='normal'>qux</span> <sup>u3</sup>,\n    <span class='normal'>quux</span> <sup>u1 u2 u3</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>foo</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>FOO</i>.</li>\n    <li>Le champ <i>bar</i> était déjà un simple attribut de l'entité <i>FOO</i>. Il obéit à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>biz</i> était déjà un simple attribut de l'entité <i>FOO</i>. Il obéit aux contraintes d'unicité 1 et 2.</li>\n    <li>Le champ <i>buz</i> était déjà un simple attribut de l'entité <i>FOO</i>. Il obéit à la contrainte d'unicité 2.</li>\n    <li>Le champ <i>qux</i> était déjà un simple attribut de l'entité <i>FOO</i>. Il obéit à la contrainte d'unicité 3.</li>\n    <li>Le champ <i>quux</i> était déjà un simple attribut de l'entité <i>FOO</i>. Il obéit aux contraintes d'unicité 1, 2 et 3.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>UTILISER</span> (\n    <span class='primary'>carnet</span> <sup>u1</sup>,\n    <span class='primary'>projet</span> <sup>u2</sup>,\n    <span class='normal'>technicien</span> <sup>u1 u2</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>carnet</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>UTILISER</i>. Il obéit en outre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>UTILISER</i>. Il obéit en outre à la contrainte d'unicité 2.</li>\n    <li>Le champ <i>technicien</i> était déjà un simple attribut de l'entité <i>UTILISER</i>. Il obéit aux contraintes d'unicité 1 et 2.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_mld.mcd",
    "content": "%%mocodo\n:\nCLIENT: Réf. client, Nom, Prénom, Adresse, Mail\n:\nFOO: foo, bar, biz, buz, qux, quux\n:\nUTILISER: carnet, _projet, technicien\n:\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_mld.md",
    "content": "- **CLIENT** (<u>Réf. client</u>, Nom <sup>u1</sup>, Prénom <sup>u1</sup>, Adresse, Mail <sup>u2</sup>)\n  - Le champ _Réf. client_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CLIENT_.\n  - Les champs _Nom_ et _Prénom_ étaient déjà de simples attributs de l'entité _CLIENT_. Il obéit à la contrainte d'unicité 1.\n  - Le champ _Adresse_ était déjà un simple attribut de l'entité _CLIENT_.\n  - Le champ _Mail_ était déjà un simple attribut de l'entité _CLIENT_. Il obéit à la contrainte d'unicité 2.\n\n- **FOO** (<u>foo</u>, bar <sup>u1</sup>, biz <sup>u1 u2</sup>, buz <sup>u2</sup>, qux <sup>u3</sup>, quux <sup>u1 u2 u3</sup>)\n  - Le champ _foo_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _FOO_.\n  - Le champ _bar_ était déjà un simple attribut de l'entité _FOO_. Il obéit à la contrainte d'unicité 1.\n  - Le champ _biz_ était déjà un simple attribut de l'entité _FOO_. Il obéit aux contraintes d'unicité 1 et 2.\n  - Le champ _buz_ était déjà un simple attribut de l'entité _FOO_. Il obéit à la contrainte d'unicité 2.\n  - Le champ _qux_ était déjà un simple attribut de l'entité _FOO_. Il obéit à la contrainte d'unicité 3.\n  - Le champ _quux_ était déjà un simple attribut de l'entité _FOO_. Il obéit aux contraintes d'unicité 1, 2 et 3.\n\n- **UTILISER** (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien <sup>u1 u2</sup>)\n  - Le champ _carnet_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _UTILISER_. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ _projet_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _UTILISER_. Il obéit en outre à la contrainte d'unicité 2.\n  - Le champ _technicien_ était déjà un simple attribut de l'entité _UTILISER_. Il obéit aux contraintes d'unicité 1 et 2.\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{alt}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CLIENT} (\\prim{Réf. client}, \\attr{Nom}$^{u\\_1}$, \\attr{Prénom}$^{u\\_1}$, \\attr{Adresse}, \\attr{Mail}$^{u\\_2}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. client} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CLIENT}.\n    \\item Les champs \\emph{Nom} et \\emph{Prénom} étaient déjà de simples attributs de l'entité \\emph{CLIENT}. Il obéit à la contrainte d'unicité 1.\n    \\item Le champ \\emph{Adresse} était déjà un simple attribut de l'entité \\emph{CLIENT}.\n    \\item Le champ \\emph{Mail} était déjà un simple attribut de l'entité \\emph{CLIENT}. Il obéit à la contrainte d'unicité 2.\n  \\end{itemize}\n\n  \\item \\relat{FOO} (\\prim{foo}, \\attr{bar}$^{u\\_1}$, \\attr{biz}$^{u\\_1 u\\_2}$, \\attr{buz}$^{u\\_2}$, \\attr{qux}$^{u\\_3}$, \\attr{quux}$^{u\\_1 u\\_2 u\\_3}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{foo} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{FOO}.\n    \\item Le champ \\emph{bar} était déjà un simple attribut de l'entité \\emph{FOO}. Il obéit à la contrainte d'unicité 1.\n    \\item Le champ \\emph{biz} était déjà un simple attribut de l'entité \\emph{FOO}. Il obéit aux contraintes d'unicité 1 et 2.\n    \\item Le champ \\emph{buz} était déjà un simple attribut de l'entité \\emph{FOO}. Il obéit à la contrainte d'unicité 2.\n    \\item Le champ \\emph{qux} était déjà un simple attribut de l'entité \\emph{FOO}. Il obéit à la contrainte d'unicité 3.\n    \\item Le champ \\emph{quux} était déjà un simple attribut de l'entité \\emph{FOO}. Il obéit aux contraintes d'unicité 1, 2 et 3.\n  \\end{itemize}\n\n  \\item \\relat{UTILISER} (\\prim{carnet}$^{u\\_1}$, \\prim{projet}$^{u\\_2}$, \\attr{technicien}$^{u\\_1 u\\_2}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{carnet} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{UTILISER}. Il obéit en outre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{UTILISER}. Il obéit en outre à la contrainte d'unicité 2.\n    \\item Le champ \\emph{technicien} était déjà un simple attribut de l'entité \\emph{UTILISER}. Il obéit aux contraintes d'unicité 1 et 2.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/alt/mld/alt_0_mld.txt",
    "content": "- CLIENT (_Réf. client_, Nom¹, Prénom¹, Adresse, Mail²)\n  - Le champ « Réf. client » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CLIENT ».\n  - Les champs « Nom » et « Prénom » étaient déjà de simples attributs de l'entité « CLIENT ». Il obéit à la contrainte d'unicité 1.\n  - Le champ « Adresse » était déjà un simple attribut de l'entité « CLIENT ».\n  - Le champ « Mail » était déjà un simple attribut de l'entité « CLIENT ». Il obéit à la contrainte d'unicité 2.\n\n- FOO (_foo_, bar¹, biz¹², buz², qux³, quux¹²³)\n  - Le champ « foo » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « FOO ».\n  - Le champ « bar » était déjà un simple attribut de l'entité « FOO ». Il obéit à la contrainte d'unicité 1.\n  - Le champ « biz » était déjà un simple attribut de l'entité « FOO ». Il obéit aux contraintes d'unicité 1 et 2.\n  - Le champ « buz » était déjà un simple attribut de l'entité « FOO ». Il obéit à la contrainte d'unicité 2.\n  - Le champ « qux » était déjà un simple attribut de l'entité « FOO ». Il obéit à la contrainte d'unicité 3.\n  - Le champ « quux » était déjà un simple attribut de l'entité « FOO ». Il obéit aux contraintes d'unicité 1, 2 et 3.\n\n- UTILISER (_carnet_¹, _projet_², technicien¹²)\n  - Le champ « carnet » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « UTILISER ». Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ « projet » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « UTILISER ». Il obéit en outre à la contrainte d'unicité 2.\n  - Le champ « technicien » était déjà un simple attribut de l'entité « UTILISER ». Il obéit aux contraintes d'unicité 1 et 2.\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, 1_at 1 2, 1_at 1 3, at 1 4, 2_at 1 5\nENTITÉ 2_: at 2 1, 1_at 2 2, 12_at 2 3, 2_at 2 4, 3_at 2 5, 123_at 2 6\nENTITÉ 3_: 1_at 3 1, 02_at 3 2, 12_at 3 3\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/alt/rewritten/alt_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/_basic_0.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\nDF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n"
  },
  {
    "path": "test/zoo/basic/_basic_1.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n\nDF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\n-Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n-Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\n\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n-Entity 11_: id 11 1, attr 11 2\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n"
  },
  {
    "path": "test/zoo/basic/_basic_2.mcd",
    "content": "CLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [INTEGER]\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_0_ddl.d2",
    "content": "\"CLIENT\": { shape: sql_table\n  \"Réf. client\": VARCHAR(42) {constraint: PK}\n  \"Nom\":         VARCHAR(42) \n  \"Prénom\":      VARCHAR(42) \n  \"Adresse\":     VARCHAR(42) \n}\n\n\"COMMANDE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(42) {constraint: PK}\n  \"Date\":          VARCHAR(42) \n  \"Montant\":       VARCHAR(42) \n  \"Réf. client\":   VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"INCLURE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(42) {constraint: [PK; FK]}\n  \"Réf. produit\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"Quantité\":      VARCHAR(42) \n}\n\n\"PRODUIT\": { shape: sql_table\n  \"Réf. produit\":  VARCHAR(42) {constraint: PK}\n  \"Libellé\":       VARCHAR(42) \n  \"Prix unitaire\": VARCHAR(42) \n}\n\n\"COMMANDE\".\"Réf. client\" -> \"CLIENT\".\"Réf. client\"\n\"INCLURE\".\"Num. commande\" -> \"COMMANDE\".\"Num. commande\"\n\"INCLURE\".\"Réf. produit\" -> \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_0_ddl.dbml",
    "content": "Table \"CLIENT\" {\n  \"Réf. client\" VARCHAR(42) [pk, NOT NULL]\n  \"Nom\"         VARCHAR(42)\n  \"Prénom\"      VARCHAR(42)\n  \"Adresse\"     VARCHAR(42)\n}\n\nTable \"COMMANDE\" {\n  \"Num. commande\" VARCHAR(42) [pk, NOT NULL]\n  \"Date\"          VARCHAR(42)\n  \"Montant\"       VARCHAR(42)\n  \"Réf. client\"   VARCHAR(42) [NOT NULL]\n}\n\nTable \"INCLURE\" {\n  \"Num. commande\" VARCHAR(42) [NOT NULL]\n  \"Réf. produit\"  VARCHAR(42) [NOT NULL]\n  \"Quantité\"      VARCHAR(42)\n  Indexes {\n    (\"Num. commande\", \"Réf. produit\") [pk]\n  }\n}\n\nTable \"PRODUIT\" {\n  \"Réf. produit\"  VARCHAR(42) [pk, NOT NULL]\n  \"Libellé\"       VARCHAR(42)\n  \"Prix unitaire\" VARCHAR(42)\n}\n\nRef:\"COMMANDE\".\"Réf. client\" > \"CLIENT\".\"Réf. client\"\nRef:\"INCLURE\".\"Num. commande\" > \"COMMANDE\".\"Num. commande\"\nRef:\"INCLURE\".\"Réf. produit\" > \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_0_ddl.sql",
    "content": "CREATE TABLE CLIENT (\n  PRIMARY KEY (ref_client),\n  ref_client VARCHAR(8) NOT NULL,\n  nom        VARCHAR(255),\n  prenom     VARCHAR(255),\n  adresse    VARCHAR(30)\n);\n\nCREATE TABLE COMMANDE (\n  PRIMARY KEY (num_commande),\n  num_commande VARCHAR(8) NOT NULL,\n  date         DATE,\n  montant      DECIMAL(10,2),\n  ref_client   VARCHAR(8) NOT NULL\n);\n\nCREATE TABLE INCLURE (\n  PRIMARY KEY (num_commande, ref_produit),\n  num_commande VARCHAR(8) NOT NULL,\n  ref_produit  VARCHAR(8) NOT NULL,\n  quantite     INTEGER\n);\n\nCREATE TABLE PRODUIT (\n  PRIMARY KEY (ref_produit),\n  ref_produit   VARCHAR(8) NOT NULL,\n  libelle       VARCHAR(50),\n  prix_unitaire DECIMAL(10,2)\n);\n\nALTER TABLE COMMANDE ADD FOREIGN KEY (ref_client) REFERENCES CLIENT (ref_client);\n\nALTER TABLE INCLURE ADD FOREIGN KEY (ref_produit) REFERENCES PRODUIT (ref_produit);\nALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_1_ddl.d2",
    "content": "\"CLIENT\": { shape: sql_table\n  \"Réf. client\": VARCHAR(42) {constraint: PK}\n  \"Nom\":         VARCHAR(42) \n  \"Prénom\":      VARCHAR(42) \n  \"Adresse\":     VARCHAR(42) \n}\n\n\"COMMANDE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(42) {constraint: PK}\n  \"Date\":          VARCHAR(42) \n  \"Montant\":       VARCHAR(42) \n  \"Réf. client\":   VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"INCLURE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(42) {constraint: [PK; FK]}\n  \"Réf. produit\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"Quantité\":      VARCHAR(42) \n}\n\n\"PRODUIT\": { shape: sql_table\n  \"Réf. produit\":  VARCHAR(42) {constraint: PK}\n  \"Libellé\":       VARCHAR(42) \n  \"Prix unitaire\": VARCHAR(42) \n}\n\n\"COMMANDE\".\"Réf. client\" -> \"CLIENT\".\"Réf. client\"\n\"INCLURE\".\"Num. commande\" -> \"COMMANDE\".\"Num. commande\"\n\"INCLURE\".\"Réf. produit\" -> \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_1_ddl.dbml",
    "content": "Table \"CLIENT\" {\n  \"Réf. client\" VARCHAR(42) [pk, NOT NULL]\n  \"Nom\"         VARCHAR(42)\n  \"Prénom\"      VARCHAR(42)\n  \"Adresse\"     VARCHAR(42)\n}\n\nTable \"COMMANDE\" {\n  \"Num. commande\" VARCHAR(42) [pk, NOT NULL]\n  \"Date\"          VARCHAR(42)\n  \"Montant\"       VARCHAR(42)\n  \"Réf. client\"   VARCHAR(42) [NOT NULL]\n}\n\nTable \"INCLURE\" {\n  \"Num. commande\" VARCHAR(42) [NOT NULL]\n  \"Réf. produit\"  VARCHAR(42) [NOT NULL]\n  \"Quantité\"      VARCHAR(42)\n  Indexes {\n    (\"Num. commande\", \"Réf. produit\") [pk]\n  }\n}\n\nTable \"PRODUIT\" {\n  \"Réf. produit\"  VARCHAR(42) [pk, NOT NULL]\n  \"Libellé\"       VARCHAR(42)\n  \"Prix unitaire\" VARCHAR(42)\n}\n\nRef:\"COMMANDE\".\"Réf. client\" > \"CLIENT\".\"Réf. client\"\nRef:\"INCLURE\".\"Num. commande\" > \"COMMANDE\".\"Num. commande\"\nRef:\"INCLURE\".\"Réf. produit\" > \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_1_ddl.sql",
    "content": "CREATE TABLE CLIENT (\n  PRIMARY KEY (ref_client),\n  ref_client VARCHAR(8) NOT NULL,\n  nom        VARCHAR(255),\n  prenom     VARCHAR(255),\n  adresse    VARCHAR(30)\n);\n\nCREATE TABLE COMMANDE (\n  PRIMARY KEY (num_commande),\n  num_commande VARCHAR(8) NOT NULL,\n  date         DATE,\n  montant      DECIMAL(10,2),\n  ref_client   VARCHAR(8) NOT NULL\n);\n\nCREATE TABLE INCLURE (\n  PRIMARY KEY (num_commande, ref_produit),\n  num_commande VARCHAR(8) NOT NULL,\n  ref_produit  VARCHAR(8) NOT NULL,\n  quantite     INTEGER\n);\n\nCREATE TABLE PRODUIT (\n  PRIMARY KEY (ref_produit),\n  ref_produit   VARCHAR(8) NOT NULL,\n  libelle       VARCHAR(50),\n  prix_unitaire DECIMAL(10,2)\n);\n\nALTER TABLE COMMANDE ADD FOREIGN KEY (ref_client) REFERENCES CLIENT (ref_client);\n\nALTER TABLE INCLURE ADD FOREIGN KEY (ref_produit) REFERENCES PRODUIT (ref_produit);\nALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_2_ddl.d2",
    "content": "\"CLIENT\": { shape: sql_table\n  \"Réf. client\": VARCHAR(8) {constraint: PK}\n  \"Nom\":         VARCHAR(255) \n  \"Prénom\":      VARCHAR(255) \n  \"Adresse\":     VARCHAR(255) \n}\n\n\"COMMANDE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(8) {constraint: PK}\n  \"Date\":          DATE \n  \"Montant\":       DECIMAL(10,2) \n  \"Réf. client\":   VARCHAR(8) {constraint: [FK; NOT NULL]}\n}\n\n\"INCLURE\": { shape: sql_table\n  \"Num. commande\": VARCHAR(8) {constraint: [PK; FK]}\n  \"Réf. produit\":  VARCHAR(8) {constraint: [PK; FK]}\n  \"Quantité\":      INTEGER \n}\n\n\"PRODUIT\": { shape: sql_table\n  \"Réf. produit\":  VARCHAR(8) {constraint: PK}\n  \"Libellé\":       VARCHAR(50) \n  \"Prix unitaire\": DECIMAL(10,2) \n}\n\n\"COMMANDE\".\"Réf. client\" -> \"CLIENT\".\"Réf. client\"\n\"INCLURE\".\"Num. commande\" -> \"COMMANDE\".\"Num. commande\"\n\"INCLURE\".\"Réf. produit\" -> \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_2_ddl.dbml",
    "content": "Table \"CLIENT\" {\n  \"Réf. client\" VARCHAR(8) [pk, NOT NULL]\n  \"Nom\"         VARCHAR(255)\n  \"Prénom\"      VARCHAR(255)\n  \"Adresse\"     VARCHAR(255)\n}\n\nTable \"COMMANDE\" {\n  \"Num. commande\" VARCHAR(8) [pk, NOT NULL]\n  \"Date\"          DATE\n  \"Montant\"       DECIMAL(10,2)\n  \"Réf. client\"   VARCHAR(8) [NOT NULL]\n}\n\nTable \"INCLURE\" {\n  \"Num. commande\" VARCHAR(8) [NOT NULL]\n  \"Réf. produit\"  VARCHAR(8) [NOT NULL]\n  \"Quantité\"      INTEGER\n  Indexes {\n    (\"Num. commande\", \"Réf. produit\") [pk]\n  }\n}\n\nTable \"PRODUIT\" {\n  \"Réf. produit\"  VARCHAR(8) [pk, NOT NULL]\n  \"Libellé\"       VARCHAR(50)\n  \"Prix unitaire\" DECIMAL(10,2)\n}\n\nRef:\"COMMANDE\".\"Réf. client\" > \"CLIENT\".\"Réf. client\"\nRef:\"INCLURE\".\"Num. commande\" > \"COMMANDE\".\"Num. commande\"\nRef:\"INCLURE\".\"Réf. produit\" > \"PRODUIT\".\"Réf. produit\"\n"
  },
  {
    "path": "test/zoo/basic/ddl/basic_2_ddl.sql",
    "content": "CREATE TABLE CLIENT (\n  PRIMARY KEY (ref_client),\n  ref_client VARCHAR(8) NOT NULL,\n  nom        VARCHAR(255),\n  prenom     VARCHAR(255),\n  adresse    VARCHAR(255)\n);\n\nCREATE TABLE COMMANDE (\n  PRIMARY KEY (num_commande),\n  num_commande VARCHAR(8) NOT NULL,\n  date         DATE,\n  montant      DECIMAL(10,2),\n  ref_client   VARCHAR(8) NOT NULL\n);\n\nCREATE TABLE INCLURE (\n  PRIMARY KEY (num_commande, ref_produit),\n  num_commande VARCHAR(8) NOT NULL,\n  ref_produit  VARCHAR(8) NOT NULL,\n  quantite     INTEGER\n);\n\nCREATE TABLE PRODUIT (\n  PRIMARY KEY (ref_produit),\n  ref_produit   VARCHAR(8) NOT NULL,\n  libelle       VARCHAR(50),\n  prix_unitaire DECIMAL(10,2)\n);\n\nALTER TABLE COMMANDE ADD FOREIGN KEY (ref_client) REFERENCES CLIENT (ref_client);\n\nALTER TABLE INCLURE ADD FOREIGN KEY (ref_produit) REFERENCES PRODUIT (ref_produit);\nALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"CLIENT\"]\n  7 [label=\"COMMANDE\"]\n  12 [label=\"PRODUIT\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Nom\"]\n  4 [label=\"Prénom\"]\n  5 [label=\"Adresse\"]\n  9 [label=\"Date\"]\n  10 [label=\"Montant\"]\n  15 [label=\"Libellé\"]\n  16 [label=\"Prix\\nunitaire\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>Réf.<br/>client</u>>]\n  8 [label=<<u>Num.<br/>commande</u>>]\n  14 [label=<<u>Réf.<br/>produit</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  13 [label=\"Quantité\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"DF\"]\n  11 [label=\"INCLURE\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  1 -- 5\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  12 -- 14\n  12 -- 15\n  12 -- 16\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  11 -- 13\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 6 [color=\"#000000\"]\n  edge [headlabel=M]\n  12 -- 11 [color=\"#000000\"]\n  edge [headlabel=N]\n  7 -- 6\n  7 -- 11\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_0_erd_chen.txt",
    "content": "[CLIENT] --1-- <DF>\n[COMMANDE] ==N== <DF>\n[COMMANDE] ==N== <INCLURE>\n[PRODUIT] --M-- <INCLURE>\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CLIENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. client</td></tr>\n        <tr><td> </td><td align=\"left\">Nom</td></tr>\n        <tr><td> </td><td align=\"left\">Prénom</td></tr>\n        <tr><td> </td><td align=\"left\">Adresse</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >COMMANDE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Num. commande</td></tr>\n        <tr><td> </td><td align=\"left\">Date</td></tr>\n        <tr><td> </td><td align=\"left\">Montant</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >INCLURE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Quantité</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PRODUIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. produit</td></tr>\n        <tr><td> </td><td align=\"left\">Libellé</td></tr>\n        <tr><td> </td><td align=\"left\">Prix unitaire</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"DF\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  3 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_0_erd_crow.mmd",
    "content": "erDiagram\n  CLIENT {\n    TYPE Ref_client PK\n    TYPE Nom\n    TYPE Prenom\n    TYPE Adresse\n  }\n  COMMANDE {\n    TYPE Num_commande PK\n    TYPE Date\n    TYPE Montant\n  }\n  INCLURE {\n    TYPE Quantite PK\n  }\n  PRODUIT {\n    TYPE Ref_produit PK\n    TYPE Libelle\n    TYPE Prix_unitaire\n  }\n  CLIENT ||--o{ COMMANDE: DF\n  INCLURE }|..|| COMMANDE: DF\n  INCLURE }o..|| PRODUIT: DF"
  },
  {
    "path": "test/zoo/basic/exported/basic_0_uml.puml",
    "content": "@startuml \"basic\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"CLIENT\") {\n    {field} + pk(Réf. client)\n    {field} + Nom\n    {field} + Prénom\n    {field} + Adresse\n}\n\n\"CLIENT\" \"1\" --- \"*\" \"COMMANDE\"\n\nTable(\"COMMANDE\") {\n    {field} + pk(Num. commande)\n    {field} + Date\n    {field} + Montant\n}\n\n\"COMMANDE\" \"*\" --- \"1..*\" \"PRODUIT\": \"INCLURE\"\n(\"COMMANDE\", \"PRODUIT\") .. \"INCLURE\"\nTable(\"INCLURE\") {\n    {field} + Quantité\n}\n\nTable(\"PRODUIT\") {\n    {field} + pk(Réf. produit)\n    {field} + Libellé\n    {field} + Prix unitaire\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"CLIENT\"]\n  10 [label=\"COMMANDE\"]\n  15 [label=\"PRODUIT\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Nom\"]\n  4 [label=\"Prénom\"]\n  5 [label=\"Adresse\"]\n  12 [label=\"Date\"]\n  13 [label=\"Montant\"]\n  17 [label=\"Libellé\"]\n  18 [label=\"Prix\\nunitaire\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>Réf.<br/>client</u>>]\n  11 [label=<<u>Num.<br/>commande</u>>]\n  16 [label=<<u>Réf.<br/>produit</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  22 [label=\"Quantité\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  9 [label=\"DF\"]\n  21 [label=\"INCLURE\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  1 -- 5\n  10 -- 11\n  10 -- 12\n  10 -- 13\n  15 -- 16\n  15 -- 17\n  15 -- 18\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  21 -- 22\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 9 [color=\"#000000\"]\n  edge [headlabel=M]\n  15 -- 21 [color=\"#000000\"]\n  edge [headlabel=N]\n  10 -- 9\n  10 -- 21\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_1_erd_chen.txt",
    "content": "[CLIENT] --1-- <DF>\n[COMMANDE] ==N== <DF>\n[COMMANDE] ==N== <INCLURE>\n[PRODUIT] --M-- <INCLURE>\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_1_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CLIENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. client</td></tr>\n        <tr><td> </td><td align=\"left\">Nom</td></tr>\n        <tr><td> </td><td align=\"left\">Prénom</td></tr>\n        <tr><td> </td><td align=\"left\">Adresse</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >COMMANDE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Num. commande</td></tr>\n        <tr><td> </td><td align=\"left\">Date</td></tr>\n        <tr><td> </td><td align=\"left\">Montant</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PRODUIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. produit</td></tr>\n        <tr><td> </td><td align=\"left\">Libellé</td></tr>\n        <tr><td> </td><td align=\"left\">Prix unitaire</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >INCLURE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Quantité</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"DF\"]\n  4 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  4 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_1_erd_crow.mmd",
    "content": "erDiagram\n  CLIENT {\n    TYPE Ref_client PK\n    TYPE Nom\n    TYPE Prenom\n    TYPE Adresse\n  }\n  COMMANDE {\n    TYPE Num_commande PK\n    TYPE Date\n    TYPE Montant\n  }\n  PRODUIT {\n    TYPE Ref_produit PK\n    TYPE Libelle\n    TYPE Prix_unitaire\n  }\n  INCLURE {\n    TYPE Quantite PK\n  }\n  CLIENT ||--o{ COMMANDE: DF\n  INCLURE }|..|| COMMANDE: DF\n  INCLURE }o..|| PRODUIT: DF"
  },
  {
    "path": "test/zoo/basic/exported/basic_1_uml.puml",
    "content": "@startuml \"basic\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"CLIENT\") {\n    {field} + pk(Réf. client)\n    {field} + Nom\n    {field} + Prénom\n    {field} + Adresse\n}\n\n\"CLIENT\" \"1\" --- \"*\" \"COMMANDE\"\n\nTable(\"COMMANDE\") {\n    {field} + pk(Num. commande)\n    {field} + Date\n    {field} + Montant\n}\n\nTable(\"PRODUIT\") {\n    {field} + pk(Réf. produit)\n    {field} + Libellé\n    {field} + Prix unitaire\n}\n\n\"COMMANDE\" \"*\" --- \"1..*\" \"PRODUIT\": \"INCLURE\"\n(\"COMMANDE\", \"PRODUIT\") .. \"INCLURE\"\nTable(\"INCLURE\") {\n    {field} + Quantité\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_2_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"CLIENT\"]\n  7 [label=\"COMMANDE\"]\n  12 [label=\"PRODUIT\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Nom\"]\n  4 [label=\"Prénom\"]\n  5 [label=\"Adresse\"]\n  9 [label=\"Date\"]\n  10 [label=\"Montant\"]\n  15 [label=\"Libellé\"]\n  16 [label=\"Prix\\nunitaire\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>Réf.<br/>client</u>>]\n  8 [label=<<u>Num.<br/>commande</u>>]\n  14 [label=<<u>Réf.<br/>produit</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  13 [label=\"Quantité\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"PASSER\"]\n  11 [label=\"INCLURE\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  1 -- 5\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  12 -- 14\n  12 -- 15\n  12 -- 16\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  11 -- 13\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 6 [color=\"#000000\"]\n  edge [headlabel=M]\n  12 -- 11 [color=\"#000000\"]\n  edge [headlabel=N]\n  7 -- 6\n  7 -- 11\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_2_erd_chen.txt",
    "content": "[CLIENT] --1-- <PASSER>\n[COMMANDE] ==N== <INCLURE>\n[COMMANDE] ==N== <PASSER>\n[PRODUIT] --M-- <INCLURE>\n"
  },
  {
    "path": "test/zoo/basic/exported/basic_2_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"3\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CLIENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\" sides=\"TBL\">Réf. client</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(8)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Nom</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(255)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Prénom</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(255)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Adresse</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(255)</font></td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"3\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >COMMANDE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\" sides=\"TBL\">Num. commande</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(8)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Date</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">DATE</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Montant</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">DECIMAL(10,2)</font></td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"3\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >INCLURE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\" sides=\"TBL\">Quantité</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">INTEGER</font></td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"3\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PRODUIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\" sides=\"TBL\">Réf. produit</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(8)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Libellé</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">VARCHAR(50)</font></td></tr>\n        <tr><td> </td><td align=\"left\" sides=\"TBL\">Prix unitaire</td><td align=\"right\" sides=\"TBR\"><font face=\"Courier\">DECIMAL(10,2)</font></td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"PASSER\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  3 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/basic/exported/basic_2_erd_crow.mmd",
    "content": "erDiagram\n  CLIENT {\n    VARCHAR(8) Ref_client PK\n    VARCHAR(255) Nom\n    VARCHAR(255) Prenom\n    VARCHAR(255) Adresse\n  }\n  COMMANDE {\n    VARCHAR(8) Num_commande PK\n    DATE Date\n    DECIMAL(10-2) Montant\n  }\n  INCLURE {\n    INTEGER Quantite PK\n  }\n  PRODUIT {\n    VARCHAR(8) Ref_produit PK\n    VARCHAR(50) Libelle\n    DECIMAL(10-2) Prix_unitaire\n  }\n  CLIENT ||--o{ COMMANDE: PASSER\n  INCLURE }|..|| COMMANDE: DF\n  INCLURE }o..|| PRODUIT: DF"
  },
  {
    "path": "test/zoo/basic/exported/basic_2_uml.puml",
    "content": "@startuml \"basic\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"CLIENT\") {\n    {field} + pk(Réf. client) VARCHAR(8)\n    {field} + Nom         VARCHAR(255)\n    {field} + Prénom      VARCHAR(255)\n    {field} + Adresse     VARCHAR(255)\n}\n\n\"CLIENT\" \"1\" --- \"*\" \"COMMANDE\": \"PASSER\"\n\nTable(\"COMMANDE\") {\n    {field} + pk(Num. commande) VARCHAR(8)\n    {field} + Date          DATE\n    {field} + Montant       DECIMAL(10,2)\n}\n\n\"COMMANDE\" \"*\" --- \"1..*\" \"PRODUIT\": \"INCLURE\"\n(\"COMMANDE\", \"PRODUIT\") .. \"INCLURE\"\nTable(\"INCLURE\") {\n    {field} + Quantité INTEGER\n}\n\nTable(\"PRODUIT\") {\n    {field} + pk(Réf. produit)  VARCHAR(8)\n    {field} + Libellé       VARCHAR(50)\n    {field} + Prix unitaire DECIMAL(10,2)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCLIENT\tRéf. client\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCLIENT\tNom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tPrénom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tAdresse\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tNum. commande\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCOMMANDE\tDate\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tMontant\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tRéf. client\t!\t\tforeign_key\tFalse\tCLIENT\tCLIENT\tDF\t\t\nINCLURE\tNum. commande\t!\t\tprimary_foreign_key\tTrue\tCOMMANDE\tCOMMANDE\tINCLURE\t\t\nINCLURE\tRéf. produit\t!\t\tprimary_foreign_key\tTrue\tPRODUIT\tPRODUIT\tINCLURE\t\t\nINCLURE\tQuantité\t\t\tassociation_attribute\tFalse\t\t\tINCLURE\t\t\nPRODUIT\tRéf. produit\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPRODUIT\tLibellé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPRODUIT\tPrix unitaire\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"CLIENT\" -> \"COMMANDE\"\n  \"PRODUIT\" -> \"INCLURE\"\n  \"COMMANDE\" -> \"INCLURE\"\n}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"basic_0_mld.svg\"/></center><figcaption>MCD <i>basic</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CLIENT</span> (\n    <span class='primary'>Réf. client</span>,\n    <span class='normal'>Nom</span>,\n    <span class='normal'>Prénom</span>,\n    <span class='normal'>Adresse</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. client</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CLIENT</i>.</li>\n    <li>Les champs <i>Nom</i>, <i>Prénom</i> et <i>Adresse</i> étaient déjà de simples attributs de l'entité <i>CLIENT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>COMMANDE</span> (\n    <span class='primary'>Num. commande</span>,\n    <span class='normal'>Date</span>,\n    <span class='normal'>Montant</span>,\n    <span class='foreign'>#Réf. client!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>COMMANDE</i>.</li>\n    <li>Les champs <i>Date</i> et <i>Montant</i> étaient déjà de simples attributs de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ à saisie obligatoire <i>Réf. client</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>DF</i> à partir de l'entité <i>CLIENT</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>INCLURE</span> (\n    <span class='foreign primary'>#Num. commande</span>,\n    <span class='foreign primary'>#Réf. produit</span>,\n    <span class='normal'>Quantité</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ <i>Réf. produit</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PRODUIT</i>.</li>\n    <li>Le champ <i>Quantité</i> était déjà un simple attribut de l'association <i>INCLURE</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PRODUIT</span> (\n    <span class='primary'>Réf. produit</span>,\n    <span class='normal'>Libellé</span>,\n    <span class='normal'>Prix unitaire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. produit</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PRODUIT</i>.</li>\n    <li>Les champs <i>Libellé</i> et <i>Prix unitaire</i> étaient déjà de simples attributs de l'entité <i>PRODUIT</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_mld.mcd",
    "content": "%%mocodo\n:\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nCOMMANDE: Num. commande, Date, Montant, #Réf. client > CLIENT > Réf. client\n:\nINCLURE: #Num. commande > COMMANDE > Num. commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n:\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_mld.md",
    "content": "- **CLIENT** (<u>Réf. client</u>, Nom, Prénom, Adresse)\n  - Le champ _Réf. client_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CLIENT_.\n  - Les champs _Nom_, _Prénom_ et _Adresse_ étaient déjà de simples attributs de l'entité _CLIENT_.\n\n- **COMMANDE** (<u>Num. commande</u>, Date, Montant, _#Réf. client!_)\n  - Le champ _Num. commande_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _COMMANDE_.\n  - Les champs _Date_ et _Montant_ étaient déjà de simples attributs de l'entité _COMMANDE_.\n  - Le champ à saisie obligatoire _Réf. client_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _DF_ à partir de l'entité _CLIENT_ en perdant son caractère identifiant.\n\n- **INCLURE** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\n  - Le champ _Num. commande_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _COMMANDE_.\n  - Le champ _Réf. produit_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PRODUIT_.\n  - Le champ _Quantité_ était déjà un simple attribut de l'association _INCLURE_.\n\n- **PRODUIT** (<u>Réf. produit</u>, Libellé, Prix unitaire)\n  - Le champ _Réf. produit_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PRODUIT_.\n  - Les champs _Libellé_ et _Prix unitaire_ étaient déjà de simples attributs de l'entité _PRODUIT_.\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{basic}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CLIENT} (\\prim{Réf. client}, \\attr{Nom}, \\attr{Prénom}, \\attr{Adresse})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. client} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CLIENT}.\n    \\item Les champs \\emph{Nom}, \\emph{Prénom} et \\emph{Adresse} étaient déjà de simples attributs de l'entité \\emph{CLIENT}.\n  \\end{itemize}\n\n  \\item \\relat{COMMANDE} (\\prim{Num. commande}, \\attr{Date}, \\attr{Montant}, \\foreign{Réf. client!})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{COMMANDE}.\n    \\item Les champs \\emph{Date} et \\emph{Montant} étaient déjà de simples attributs de l'entité \\emph{COMMANDE}.\n    \\item Le champ à saisie obligatoire \\emph{Réf. client} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{DF} à partir de l'entité \\emph{CLIENT} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{INCLURE} (\\foreign{\\prim{Num. commande}}, \\foreign{\\prim{Réf. produit}}, \\attr{Quantité})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{COMMANDE}.\n    \\item Le champ \\emph{Réf. produit} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PRODUIT}.\n    \\item Le champ \\emph{Quantité} était déjà un simple attribut de l'association \\emph{INCLURE}.\n  \\end{itemize}\n\n  \\item \\relat{PRODUIT} (\\prim{Réf. produit}, \\attr{Libellé}, \\attr{Prix unitaire})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. produit} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PRODUIT}.\n    \\item Les champs \\emph{Libellé} et \\emph{Prix unitaire} étaient déjà de simples attributs de l'entité \\emph{PRODUIT}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_0_mld.txt",
    "content": "- CLIENT (_Réf. client_, Nom, Prénom, Adresse)\n  - Le champ « Réf. client » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CLIENT ».\n  - Les champs « Nom », « Prénom » et « Adresse » étaient déjà de simples attributs de l'entité « CLIENT ».\n\n- COMMANDE (_Num. commande_, Date, Montant, #Réf. client!)\n  - Le champ « Num. commande » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « COMMANDE ».\n  - Les champs « Date » et « Montant » étaient déjà de simples attributs de l'entité « COMMANDE ».\n  - Le champ à saisie obligatoire « Réf. client » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « DF » à partir de l'entité « CLIENT » en perdant son caractère identifiant.\n\n- INCLURE (_#Num. commande_, _#Réf. produit_, Quantité)\n  - Le champ « Num. commande » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « COMMANDE ».\n  - Le champ « Réf. produit » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PRODUIT ».\n  - Le champ « Quantité » était déjà un simple attribut de l'association « INCLURE ».\n\n- PRODUIT (_Réf. produit_, Libellé, Prix unitaire)\n  - Le champ « Réf. produit » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PRODUIT ».\n  - Les champs « Libellé » et « Prix unitaire » étaient déjà de simples attributs de l'entité « PRODUIT ».\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCLIENT\tRéf. client\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCLIENT\tNom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tPrénom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCLIENT\tAdresse\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tNum. commande\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCOMMANDE\tDate\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tMontant\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMMANDE\tRéf. client\t!\t\tforeign_key\tFalse\tCLIENT\tCLIENT\tDF\t\t\nINCLURE\tNum. commande\t!\t\tprimary_foreign_key\tTrue\tCOMMANDE\tCOMMANDE\tINCLURE\t\t\nINCLURE\tRéf. produit\t!\t\tprimary_foreign_key\tTrue\tPRODUIT\tPRODUIT\tINCLURE\t\t\nINCLURE\tQuantité\t\t\tassociation_attribute\tFalse\t\t\tINCLURE\t\t\nPRODUIT\tRéf. produit\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPRODUIT\tLibellé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPRODUIT\tPrix unitaire\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"CLIENT\" -> \"COMMANDE\"\n  \"PRODUIT\" -> \"INCLURE\"\n  \"COMMANDE\" -> \"INCLURE\"\n}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"basic_1_mld.svg\"/></center><figcaption>MCD <i>basic</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CLIENT</span> (\n    <span class='primary'>Réf. client</span>,\n    <span class='normal'>Nom</span>,\n    <span class='normal'>Prénom</span>,\n    <span class='normal'>Adresse</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. client</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CLIENT</i>.</li>\n    <li>Les champs <i>Nom</i>, <i>Prénom</i> et <i>Adresse</i> étaient déjà de simples attributs de l'entité <i>CLIENT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>COMMANDE</span> (\n    <span class='primary'>Num. commande</span>,\n    <span class='normal'>Date</span>,\n    <span class='normal'>Montant</span>,\n    <span class='foreign'>#Réf. client!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>COMMANDE</i>.</li>\n    <li>Les champs <i>Date</i> et <i>Montant</i> étaient déjà de simples attributs de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ à saisie obligatoire <i>Réf. client</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>DF</i> à partir de l'entité <i>CLIENT</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>INCLURE</span> (\n    <span class='foreign primary'>#Num. commande</span>,\n    <span class='foreign primary'>#Réf. produit</span>,\n    <span class='normal'>Quantité</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ <i>Réf. produit</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PRODUIT</i>.</li>\n    <li>Le champ <i>Quantité</i> était déjà un simple attribut de l'association <i>INCLURE</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PRODUIT</span> (\n    <span class='primary'>Réf. produit</span>,\n    <span class='normal'>Libellé</span>,\n    <span class='normal'>Prix unitaire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. produit</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PRODUIT</i>.</li>\n    <li>Les champs <i>Libellé</i> et <i>Prix unitaire</i> étaient déjà de simples attributs de l'entité <i>PRODUIT</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_mld.mcd",
    "content": "%%mocodo\n:\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:::::::\n\n\n:::\nCOMMANDE: Num. commande, Date, Montant, #Réf. client > CLIENT > Réf. client\n:::\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n:\n\n\n:::::\nINCLURE: #Num. commande > COMMANDE > Num. commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\n:::\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_mld.md",
    "content": "- **CLIENT** (<u>Réf. client</u>, Nom, Prénom, Adresse)\n  - Le champ _Réf. client_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CLIENT_.\n  - Les champs _Nom_, _Prénom_ et _Adresse_ étaient déjà de simples attributs de l'entité _CLIENT_.\n\n- **COMMANDE** (<u>Num. commande</u>, Date, Montant, _#Réf. client!_)\n  - Le champ _Num. commande_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _COMMANDE_.\n  - Les champs _Date_ et _Montant_ étaient déjà de simples attributs de l'entité _COMMANDE_.\n  - Le champ à saisie obligatoire _Réf. client_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _DF_ à partir de l'entité _CLIENT_ en perdant son caractère identifiant.\n\n- **INCLURE** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\n  - Le champ _Num. commande_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _COMMANDE_.\n  - Le champ _Réf. produit_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PRODUIT_.\n  - Le champ _Quantité_ était déjà un simple attribut de l'association _INCLURE_.\n\n- **PRODUIT** (<u>Réf. produit</u>, Libellé, Prix unitaire)\n  - Le champ _Réf. produit_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PRODUIT_.\n  - Les champs _Libellé_ et _Prix unitaire_ étaient déjà de simples attributs de l'entité _PRODUIT_.\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{basic}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CLIENT} (\\prim{Réf. client}, \\attr{Nom}, \\attr{Prénom}, \\attr{Adresse})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. client} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CLIENT}.\n    \\item Les champs \\emph{Nom}, \\emph{Prénom} et \\emph{Adresse} étaient déjà de simples attributs de l'entité \\emph{CLIENT}.\n  \\end{itemize}\n\n  \\item \\relat{COMMANDE} (\\prim{Num. commande}, \\attr{Date}, \\attr{Montant}, \\foreign{Réf. client!})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{COMMANDE}.\n    \\item Les champs \\emph{Date} et \\emph{Montant} étaient déjà de simples attributs de l'entité \\emph{COMMANDE}.\n    \\item Le champ à saisie obligatoire \\emph{Réf. client} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{DF} à partir de l'entité \\emph{CLIENT} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{INCLURE} (\\foreign{\\prim{Num. commande}}, \\foreign{\\prim{Réf. produit}}, \\attr{Quantité})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{COMMANDE}.\n    \\item Le champ \\emph{Réf. produit} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PRODUIT}.\n    \\item Le champ \\emph{Quantité} était déjà un simple attribut de l'association \\emph{INCLURE}.\n  \\end{itemize}\n\n  \\item \\relat{PRODUIT} (\\prim{Réf. produit}, \\attr{Libellé}, \\attr{Prix unitaire})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. produit} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PRODUIT}.\n    \\item Les champs \\emph{Libellé} et \\emph{Prix unitaire} étaient déjà de simples attributs de l'entité \\emph{PRODUIT}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_1_mld.txt",
    "content": "- CLIENT (_Réf. client_, Nom, Prénom, Adresse)\n  - Le champ « Réf. client » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CLIENT ».\n  - Les champs « Nom », « Prénom » et « Adresse » étaient déjà de simples attributs de l'entité « CLIENT ».\n\n- COMMANDE (_Num. commande_, Date, Montant, #Réf. client!)\n  - Le champ « Num. commande » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « COMMANDE ».\n  - Les champs « Date » et « Montant » étaient déjà de simples attributs de l'entité « COMMANDE ».\n  - Le champ à saisie obligatoire « Réf. client » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « DF » à partir de l'entité « CLIENT » en perdant son caractère identifiant.\n\n- INCLURE (_#Num. commande_, _#Réf. produit_, Quantité)\n  - Le champ « Num. commande » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « COMMANDE ».\n  - Le champ « Réf. produit » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PRODUIT ».\n  - Le champ « Quantité » était déjà un simple attribut de l'association « INCLURE ».\n\n- PRODUIT (_Réf. produit_, Libellé, Prix unitaire)\n  - Le champ « Réf. produit » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PRODUIT ».\n  - Les champs « Libellé » et « Prix unitaire » étaient déjà de simples attributs de l'entité « PRODUIT ».\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCLIENT\tRéf. client\t!\t\tprimary_key\tTrue\t\t\t\tVARCHAR(8)\t\nCLIENT\tNom\t\t\tnormal_attribute\tFalse\t\t\t\tVARCHAR(255)\t\nCLIENT\tPrénom\t\t\tnormal_attribute\tFalse\t\t\t\tVARCHAR(255)\t\nCLIENT\tAdresse\t\t\tnormal_attribute\tFalse\t\t\t\tVARCHAR(255)\t\nCOMMANDE\tNum. commande\t!\t\tprimary_key\tTrue\t\t\t\tVARCHAR(8)\t\nCOMMANDE\tDate\t\t\tnormal_attribute\tFalse\t\t\t\tDATE\t\nCOMMANDE\tMontant\t\t\tnormal_attribute\tFalse\t\t\t\tDECIMAL(10,2)\t\nCOMMANDE\tRéf. client\t!\t\tforeign_key\tFalse\tCLIENT\tCLIENT\tPASSER\tVARCHAR(8)\t\nINCLURE\tNum. commande\t!\t\tprimary_foreign_key\tTrue\tCOMMANDE\tCOMMANDE\tINCLURE\tVARCHAR(8)\t\nINCLURE\tRéf. produit\t!\t\tprimary_foreign_key\tTrue\tPRODUIT\tPRODUIT\tINCLURE\tVARCHAR(8)\t\nINCLURE\tQuantité\t\t\tassociation_attribute\tFalse\t\t\tINCLURE\tINTEGER\t\nPRODUIT\tRéf. produit\t!\t\tprimary_key\tTrue\t\t\t\tVARCHAR(8)\t\nPRODUIT\tLibellé\t\t\tnormal_attribute\tFalse\t\t\t\tVARCHAR(50)\t\nPRODUIT\tPrix unitaire\t\t\tnormal_attribute\tFalse\t\t\t\tDECIMAL(10,2)\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"CLIENT\" -> \"COMMANDE\"\n  \"PRODUIT\" -> \"INCLURE\"\n  \"COMMANDE\" -> \"INCLURE\"\n}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"basic_2_mld.svg\"/></center><figcaption>MCD <i>basic</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CLIENT</span> (\n    <span class='primary'>Réf. client</span>,\n    <span class='normal'>Nom</span>,\n    <span class='normal'>Prénom</span>,\n    <span class='normal'>Adresse</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. client</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CLIENT</i>.</li>\n    <li>Les champs <i>Nom</i>, <i>Prénom</i> et <i>Adresse</i> étaient déjà de simples attributs de l'entité <i>CLIENT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>COMMANDE</span> (\n    <span class='primary'>Num. commande</span>,\n    <span class='normal'>Date</span>,\n    <span class='normal'>Montant</span>,\n    <span class='foreign'>#Réf. client!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>COMMANDE</i>.</li>\n    <li>Les champs <i>Date</i> et <i>Montant</i> étaient déjà de simples attributs de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ à saisie obligatoire <i>Réf. client</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>PASSER</i> à partir de l'entité <i>CLIENT</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>INCLURE</span> (\n    <span class='foreign primary'>#Num. commande</span>,\n    <span class='foreign primary'>#Réf. produit</span>,\n    <span class='normal'>Quantité</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. commande</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>COMMANDE</i>.</li>\n    <li>Le champ <i>Réf. produit</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PRODUIT</i>.</li>\n    <li>Le champ <i>Quantité</i> était déjà un simple attribut de l'association <i>INCLURE</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PRODUIT</span> (\n    <span class='primary'>Réf. produit</span>,\n    <span class='normal'>Libellé</span>,\n    <span class='normal'>Prix unitaire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Réf. produit</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PRODUIT</i>.</li>\n    <li>Les champs <i>Libellé</i> et <i>Prix unitaire</i> étaient déjà de simples attributs de l'entité <i>PRODUIT</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_mld.mcd",
    "content": "%%mocodo\n:\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nCOMMANDE: Num. commande, Date, Montant, #Réf. client > CLIENT > Réf. client\n:\nINCLURE: #Num. commande > COMMANDE > Num. commande, _#Réf. produit > PRODUIT > Réf. produit, Quantité\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n:\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_mld.md",
    "content": "- **CLIENT** (<u>Réf. client</u>, Nom, Prénom, Adresse)\n  - Le champ _Réf. client_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CLIENT_.\n  - Les champs _Nom_, _Prénom_ et _Adresse_ étaient déjà de simples attributs de l'entité _CLIENT_.\n\n- **COMMANDE** (<u>Num. commande</u>, Date, Montant, _#Réf. client!_)\n  - Le champ _Num. commande_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _COMMANDE_.\n  - Les champs _Date_ et _Montant_ étaient déjà de simples attributs de l'entité _COMMANDE_.\n  - Le champ à saisie obligatoire _Réf. client_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _PASSER_ à partir de l'entité _CLIENT_ en perdant son caractère identifiant.\n\n- **INCLURE** (<u>_#Num. commande_</u>, <u>_#Réf. produit_</u>, Quantité)\n  - Le champ _Num. commande_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _COMMANDE_.\n  - Le champ _Réf. produit_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PRODUIT_.\n  - Le champ _Quantité_ était déjà un simple attribut de l'association _INCLURE_.\n\n- **PRODUIT** (<u>Réf. produit</u>, Libellé, Prix unitaire)\n  - Le champ _Réf. produit_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PRODUIT_.\n  - Les champs _Libellé_ et _Prix unitaire_ étaient déjà de simples attributs de l'entité _PRODUIT_.\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{basic}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CLIENT} (\\prim{Réf. client}, \\attr{Nom}, \\attr{Prénom}, \\attr{Adresse})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. client} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CLIENT}.\n    \\item Les champs \\emph{Nom}, \\emph{Prénom} et \\emph{Adresse} étaient déjà de simples attributs de l'entité \\emph{CLIENT}.\n  \\end{itemize}\n\n  \\item \\relat{COMMANDE} (\\prim{Num. commande}, \\attr{Date}, \\attr{Montant}, \\foreign{Réf. client!})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{COMMANDE}.\n    \\item Les champs \\emph{Date} et \\emph{Montant} étaient déjà de simples attributs de l'entité \\emph{COMMANDE}.\n    \\item Le champ à saisie obligatoire \\emph{Réf. client} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{PASSER} à partir de l'entité \\emph{CLIENT} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{INCLURE} (\\foreign{\\prim{Num. commande}}, \\foreign{\\prim{Réf. produit}}, \\attr{Quantité})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. commande} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{COMMANDE}.\n    \\item Le champ \\emph{Réf. produit} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PRODUIT}.\n    \\item Le champ \\emph{Quantité} était déjà un simple attribut de l'association \\emph{INCLURE}.\n  \\end{itemize}\n\n  \\item \\relat{PRODUIT} (\\prim{Réf. produit}, \\attr{Libellé}, \\attr{Prix unitaire})\n  \\begin{itemize}\n    \\item Le champ \\emph{Réf. produit} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PRODUIT}.\n    \\item Les champs \\emph{Libellé} et \\emph{Prix unitaire} étaient déjà de simples attributs de l'entité \\emph{PRODUIT}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/basic/mld/basic_2_mld.txt",
    "content": "- CLIENT (_Réf. client_, Nom, Prénom, Adresse)\n  - Le champ « Réf. client » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CLIENT ».\n  - Les champs « Nom », « Prénom » et « Adresse » étaient déjà de simples attributs de l'entité « CLIENT ».\n\n- COMMANDE (_Num. commande_, Date, Montant, #Réf. client!)\n  - Le champ « Num. commande » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « COMMANDE ».\n  - Les champs « Date » et « Montant » étaient déjà de simples attributs de l'entité « COMMANDE ».\n  - Le champ à saisie obligatoire « Réf. client » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « PASSER » à partir de l'entité « CLIENT » en perdant son caractère identifiant.\n\n- INCLURE (_#Num. commande_, _#Réf. produit_, Quantité)\n  - Le champ « Num. commande » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « COMMANDE ».\n  - Le champ « Réf. produit » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PRODUIT ».\n  - Le champ « Quantité » était déjà un simple attribut de l'association « INCLURE ».\n\n- PRODUIT (_Réf. produit_, Libellé, Prix unitaire)\n  - Le champ « Réf. produit » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PRODUIT ».\n  - Les champs « Libellé » et « Prix unitaire » étaient déjà de simples attributs de l'entité « PRODUIT ».\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2, at 1 3, at 1 4\nDF, 0N> ENTITÉ 1_, 11 ENTITÉ 2_\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\nASSOC 5_, 1N ENTITÉ 2_, 0N ENTITÉ 3_: at 5 1\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=2,weak.mcd",
    "content": "DF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, _11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nINCLURE: _Quantité\nDF, _11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=2.5,weak.mcd",
    "content": "DF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, _11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nINCLURE: _Quantité\nDF, _11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=2.5.mcd",
    "content": "DF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, 11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nINCLURE: id. inclure, Quantité\nDF, 11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=2.mcd",
    "content": "DF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, 11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\nINCLURE: id. inclure, Quantité\nDF, 11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_create_df_arrows=across.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\n-Reflexive 6_, 11 COMMANDE, 01> COMMANDE\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n-Reflexive 13_, 11 PRODUIT, 1N> PRODUIT\n\nDF, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\n-Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n-Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\n\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n-Entity 11_: id 11 1, attr 11 2\n-Binary 12_, 0N> Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_drain.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n\nDF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\n-Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\n-Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\n\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n-Entity 11_: id 11 1, attr 11 2\n-Binary 12_, 0N Entity 11_, 11 Entity 9_\n-Entity 9_: id 9 1, attr 9 2, attr 9 3, attr 12 1\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_drown.mcd",
    "content": "ENTITÉ 01_: at 01 1, at 01 2, at 01 3, at 01 4\n-ASSOC 08_, 11 ENTITÉ 03_, 01 ENTITÉ 03_\n-ENTITÉ 02_: at 02 1, _at 02 2, at 02 3, at 02 4\n-ASSOC 09_, 11 ENTITÉ 04_, 1N ENTITÉ 04_\n\nDF, 0N ENTITÉ 01_, 11 ENTITÉ 03_\nENTITÉ 03_: at 03 1, at 03 2, at 03 3\n-ASSOC 11_, 0N ENTITÉ 02_, 0N ENTITÉ 03_, 1N ENTITÉ 04_\nENTITÉ 04_: at 04 1, at 04 2, at 04 3\n\n-ENTITÉ 05_: at 05 1, at 05 2, at 05 3, at 05 4\n-ASSOC 12_, 0N ENTITÉ 05_, 01 ENTITÉ 06_\nASSOC 13_, 1N ENTITÉ 03_, 0N ENTITÉ 04_: at 13 1\n-ASSOC 14_, 1N ENTITÉ 07_, 1N ENTITÉ 04_: at 14 1\n\n-ASSOC 15_, 0N ENTITÉ 05_, 1N ENTITÉ 06_\n-ENTITÉ 06_: at 06 1, at 06 2\n-ASSOC 16_, 0N ENTITÉ 06_, 11 ENTITÉ 07_: at 16 1\n-ENTITÉ 07_: at 07 1, at 07 2, at 07 3\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=2,weak.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n:\n:\n:\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 11_: id 11 1, attr 11 2\n-DF, _11 Binary 16_, 1N Entity 11_\n\nDF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, _11 INCLURE, 1N COMMANDE\nINCLURE: _Quantité\n:\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n-Binary 16_:\n\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n-DF, _11 Ternary 8_, 0N COMMANDE\n:\nDF, _11 INCLURE, 0N PRODUIT\n:\n-DF, _11 Binary 10_, 1N Entity 9_\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-DF, _11 Binary 16_, 0N Entity 14_\n\n-DF, _11 Ternary 8_, 0N Entity 7_\n-Ternary 8_:\n-DF, _11 Ternary 8_, 1N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n-DF, _11 Binary 10_, 1N PRODUIT\n-Binary 10_: _attr 10 1\n:\n:\n\n:\n:\n:\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=2.5,weak.mcd",
    "content": ":\nDF, 0N CLIENT, 11 COMMANDE\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\n:\n:\n:\n\nDF, _11 INCLURE, 1N COMMANDE\nCOMMANDE: Num. commande, Date, Montant\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n:\n:\n:\n:\n\nINCLURE: _Quantité\n-Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n:\n:\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n\nDF, _11 INCLURE, 0N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 11_: id 11 1, attr 11 2\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n\n:\n-DF, _11 Binary 10_, 1N PRODUIT\n-Binary 10_: _attr 10 1\n-DF, _11 Binary 10_, 1N Entity 9_\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=2.5.mcd",
    "content": ":\nDF, 0N CLIENT, 11 COMMANDE\nCLIENT: Réf. client, Nom, Prénom, Adresse\n:\n:\n:\n:\n\nDF, 11 INCLURE, 1N COMMANDE\nCOMMANDE: Num. commande, Date, Montant\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n:\n:\n:\n:\n\nINCLURE: id. inclure, Quantité\n-Ternary 8_, 0N Entity 7_, 0N COMMANDE, 1N PRODUIT\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n:\n:\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n\nDF, 11 INCLURE, 0N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 11_: id 11 1, attr 11 2\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n\n:\n-DF, 11 Binary 10_, 1N PRODUIT\n-Binary 10_: id. binary 10_, attr 10 1\n-DF, 11 Binary 10_, 1N Entity 9_\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=2.mcd",
    "content": "CLIENT: Réf. client, Nom, Prénom, Adresse\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n:\n:\n:\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 11_: id 11 1, attr 11 2\n-DF, 11 Binary 16_, 1N Entity 11_\n\nDF, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande, Date, Montant\nDF, 11 INCLURE, 1N COMMANDE\nINCLURE: id. inclure, Quantité\n:\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n-Binary 16_: id. binary 16_\n\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n-DF, 11 Ternary 8_, 0N COMMANDE\n:\nDF, 11 INCLURE, 0N PRODUIT\n:\n-DF, 11 Binary 10_, 1N Entity 9_\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-DF, 11 Binary 16_, 0N Entity 14_\n\n-DF, 11 Ternary 8_, 0N Entity 7_\n-Ternary 8_: id. ternary 8_\n-DF, 11 Ternary 8_, 1N PRODUIT\nPRODUIT: Réf. produit, Libellé, Prix unitaire\n-DF, 11 Binary 10_, 1N PRODUIT\n-Binary 10_: id. binary 10_, attr 10 1\n:\n:\n\n:\n:\n:\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=3,weak.mcd",
    "content": ":\n:\n:\n:\n:\n-DF, _11 Ternary 8_, 0N Entity 7_\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n:\n\n:\n:\n:\n:\n-DF, _11 Ternary 8_, 1N PRODUIT\n-Ternary 8_:\n-DF, _11 Ternary 8_, 0N COMMANDE\n:\n\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n:\n-Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\nPRODUIT: Réf. produit, Libellé, Prix unitaire\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nCOMMANDE: Num. commande, Date, Montant\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n-Entity 11_: id 11 1, attr 11 2\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n:\nDF, 0N CLIENT, 11 COMMANDE\nCLIENT: Réf. client, Nom, Prénom, Adresse\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_explode_arity=3.mcd",
    "content": ":\n:\n:\n:\n:\n-DF, 11 Ternary 8_, 0N Entity 7_\n-Entity 7_: id 7 1, _id 7 2, attr 7 3, attr 7 4\n:\n\n:\n:\n:\n:\n-DF, 11 Ternary 8_, 1N PRODUIT\n-Ternary 8_: id. ternary 8_\n-DF, 11 Ternary 8_, 0N COMMANDE\n:\n\n-Entity 14_: id 14 1, attr 14 2, attr 14 3, attr 14 4\n-Binary 15_, 0N Entity 14_, 01 Entity 11_\n:\n-Binary 10_, 1N Entity 9_, 1N PRODUIT: attr 10 1\nPRODUIT: Réf. produit, Libellé, Prix unitaire\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité\nCOMMANDE: Num. commande, Date, Montant\n-Reflexive 6_, 11 COMMANDE, 01 COMMANDE\n\n-Binary 16_, 0N Entity 14_, 1N Entity 11_\n-Entity 11_: id 11 1, attr 11 2\n-Binary 12_, 0N Entity 11_, 11 Entity 9_: attr 12 1\n-Entity 9_: id 9 1, attr 9 2, attr 9 3\n-Reflexive 13_, 11 PRODUIT, 1N PRODUIT\n:\nDF, 0N CLIENT, 11 COMMANDE\nCLIENT: Réf. client, Nom, Prénom, Adresse\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_create_df_arrows=across.mcd",
    "content": "CLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\nPASSER, 0N> CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nINCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [INTEGER]\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1 [VARCHAR(8)], at 1 2 [VARCHAR(255)], at 1 3 [VARCHAR(255)], at 1 4 [VARCHAR(255)]\nASSOC 4_, 0N ENTITÉ 1_, 11 ENTITÉ 2_\nENTITÉ 2_: at 2 1 [VARCHAR(8)], at 2 2 [DATE], at 2 3 [DECIMAL(10,2)]\nASSOC 5_, 1N ENTITÉ 2_, 0N ENTITÉ 3_: at 5 1 [INTEGER]\nENTITÉ 3_: at 3 1 [VARCHAR(8)], at 3 2 [VARCHAR(50)], at 3 3 [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=2,weak.mcd",
    "content": "PASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nDF, _11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\n:\nINCLURE: _Quantité [INTEGER]\nDF, _11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=2.5,weak.mcd",
    "content": "PASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nDF, _11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\n:\nINCLURE: _Quantité [INTEGER]\nDF, _11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=2.5.mcd",
    "content": "PASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nDF, 11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\n:\nINCLURE: id. inclure, Quantité [INTEGER]\nDF, 11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=2.mcd",
    "content": "PASSER, 0N CLIENT, 11 COMMANDE\nCOMMANDE: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]\nDF, 11 INCLURE, 1N COMMANDE\n:\n\nCLIENT: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]\n:\nINCLURE: id. inclure, Quantité [INTEGER]\nDF, 11 INCLURE, 0N PRODUIT\n\n:\n:\n:\nPRODUIT: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/basic/rewritten/basic_2_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/_cluster_NN1_0.mcd",
    "content": "Voilier: num voilier, longueur\nOffrir, 0N Voilier, 0N Semaine, /11 Réservation: tarif\nSemaine: num semaine, 1_date début\n\nRéservation: num résa, arrhes, date résa\n"
  },
  {
    "path": "test/zoo/cluster_NN1/ddl/cluster_NN1_0_ddl.d2",
    "content": "\"Réservation\": { shape: sql_table\n  \"num résa\":    VARCHAR(42) {constraint: PK}\n  \"arrhes\":      VARCHAR(42) \n  \"date résa\":   VARCHAR(42) \n  \"num voilier\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"num semaine\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"tarif\":       VARCHAR(42) \n}\n\n\"Semaine\": { shape: sql_table\n  \"num semaine\": VARCHAR(42) {constraint: PK}\n  \"date début\":  VARCHAR(42) {constraint: UNQ1}\n}\n\n\"Voilier\": { shape: sql_table\n  \"num voilier\": VARCHAR(42) {constraint: PK}\n  \"longueur\":    VARCHAR(42) \n}\n\n\"Réservation\".\"num voilier\" -> \"Voilier\".\"num voilier\"\n\"Réservation\".\"num semaine\" -> \"Semaine\".\"num semaine\"\n"
  },
  {
    "path": "test/zoo/cluster_NN1/ddl/cluster_NN1_0_ddl.dbml",
    "content": "Table \"Réservation\" {\n  \"num résa\"    VARCHAR(42) [pk, NOT NULL]\n  \"arrhes\"      VARCHAR(42)\n  \"date résa\"   VARCHAR(42)\n  \"num voilier\" VARCHAR(42) [NOT NULL]\n  \"num semaine\" VARCHAR(42) [NOT NULL]\n  \"tarif\"       VARCHAR(42)\n  Indexes {\n    (\"num voilier\", \"num semaine\") [unique]\n  }\n}\n\nTable \"Semaine\" {\n  \"num semaine\" VARCHAR(42) [pk, NOT NULL]\n  \"date début\"  VARCHAR(42)\n  Indexes {\n    \"date début\" [unique]\n  }\n}\n\nTable \"Voilier\" {\n  \"num voilier\" VARCHAR(42) [pk, NOT NULL]\n  \"longueur\"    VARCHAR(42)\n}\n\nRef:\"Réservation\".\"num voilier\" > \"Voilier\".\"num voilier\"\nRef:\"Réservation\".\"num semaine\" > \"Semaine\".\"num semaine\"\n"
  },
  {
    "path": "test/zoo/cluster_NN1/ddl/cluster_NN1_0_ddl.sql",
    "content": "CREATE TABLE RESERVATION (\n  PRIMARY KEY (num_resa),\n  num_resa    VARCHAR(8) NOT NULL,\n  arrhes      VARCHAR(42),\n  date_resa   DATE,\n  num_voilier VARCHAR(8) NOT NULL,\n  num_semaine VARCHAR(8) NOT NULL,\n  tarif       VARCHAR(42),\n  UNIQUE (num_voilier, num_semaine)\n);\n\nCREATE TABLE SEMAINE (\n  PRIMARY KEY (num_semaine),\n  num_semaine VARCHAR(8) NOT NULL,\n  date_debut  DATE,\n  UNIQUE (date_debut)\n);\n\nCREATE TABLE VOILIER (\n  PRIMARY KEY (num_voilier),\n  num_voilier VARCHAR(8) NOT NULL,\n  longueur    DECIMAL(10,2)\n);\n\nALTER TABLE RESERVATION ADD FOREIGN KEY (num_semaine) REFERENCES SEMAINE (num_semaine);\nALTER TABLE RESERVATION ADD FOREIGN KEY (num_voilier) REFERENCES VOILIER (num_voilier);\n"
  },
  {
    "path": "test/zoo/cluster_NN1/exported/cluster_NN1_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Voilier\"]\n  5 [label=\"Semaine\"]\n  6 [label=\"Réservation\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"longueur\"]\n  9 [label=\"date\\ndébut\"]\n  11 [label=\"arrhes\"]\n  12 [label=\"date résa\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>num<br/>voilier</u>>]\n  8 [label=<<u>num<br/>semaine</u>>]\n  10 [label=<<u>num résa</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  7 [label=\"tarif\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Offrir\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 8\n  5 -- 9\n  6 -- 10\n  6 -- 11\n  6 -- 12\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  4 -- 7\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  6 -- 4\n  edge [headlabel=N]\n  1 -- 4 [color=\"#000000\"]\n  5 -- 4 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/cluster_NN1/exported/cluster_NN1_0_erd_chen.txt",
    "content": "[Réservation] ==1== <Offrir>\n[Semaine] --N-- <Offrir>\n[Voilier] --N-- <Offrir>\n"
  },
  {
    "path": "test/zoo/cluster_NN1/exported/cluster_NN1_0_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/cluster_NN1/exported/cluster_NN1_0_uml.puml",
    "content": "@startuml \"cluster_NN1\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Voilier\") {\n    {field} + pk(num voilier)\n    {field} + longueur\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"*\" \"Voilier\"\nN_ARY_0 -- \"*\" \"Semaine\"\nN_ARY_0 -- \"1\" \"Réservation\"\n\nTable(\"Semaine\") {\n    {field} + pk(num semaine)\n    {field} + date début\n}\n\nTable(\"Réservation\") {\n    {field} + pk(num résa)\n    {field} + arrhes\n    {field} + date résa\n    {field} + tarif\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nRéservation\tnum résa\t!\t\tprimary_key\tTrue\t\t\t\t\t\nRéservation\tarrhes\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nRéservation\tdate résa\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nRéservation\tnum voilier\t!\t1\tforeign_key\tFalse\tVoilier\tVoilier\tOffrir\t\t\nRéservation\tnum semaine\t!\t1\tforeign_key\tFalse\tSemaine\tSemaine\tOffrir\t\t\nRéservation\ttarif\t\t\touter_attribute\tFalse\t\t\tOffrir\t\t\nSemaine\tnum semaine\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSemaine\tdate début\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nVoilier\tnum voilier\t!\t\tprimary_key\tTrue\t\t\t\t\t\nVoilier\tlongueur\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Semaine\" -> \"Réservation\"\n  \"Voilier\" -> \"Réservation\"\n}\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"cluster_NN1_0_mld.svg\"/></center><figcaption>MCD <i>cluster_NN1</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Réservation</span> (\n    <span class='primary'>num résa</span>,\n    <span class='normal'>arrhes</span>,\n    <span class='normal'>date résa</span>,\n    <span class='foreign'>#num voilier</span> <sup>u1</sup>,\n    <span class='foreign'>#num semaine</span> <sup>u1</sup>,\n    <span class='normal'>tarif</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num résa</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Réservation</i>.</li>\n    <li>Les champs <i>arrhes</i> et <i>date résa</i> étaient déjà de simples attributs de l'entité <i>Réservation</i>.</li>\n    <li>Le champ <i>num voilier</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Offrir</i> à partir de l'entité <i>Voilier</i> en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>num semaine</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Offrir</i> à partir de l'entité <i>Semaine</i> en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>tarif</i> a migré à partir de l'association de dépendance fonctionnelle <i>Offrir</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Semaine</span> (\n    <span class='primary'>num semaine</span>,\n    <span class='normal'>date début</span> <sup>u1</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num semaine</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Semaine</i>.</li>\n    <li>Le champ <i>date début</i> était déjà un simple attribut de l'entité <i>Semaine</i>. Il obéit à la contrainte d'unicité 1.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Voilier</span> (\n    <span class='primary'>num voilier</span>,\n    <span class='normal'>longueur</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num voilier</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Voilier</i>.</li>\n    <li>Le champ <i>longueur</i> était déjà un simple attribut de l'entité <i>Voilier</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_mld.mcd",
    "content": "%%mocodo\n:\nVoilier: num voilier, longueur\n:::\nSemaine: num semaine, date début\n:\n\n\n:::\nRéservation: num résa, arrhes, date résa, #num voilier > Voilier > num voilier, #num semaine > Semaine > num semaine, tarif\n:::\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_mld.md",
    "content": "- **Réservation** (<u>num résa</u>, arrhes, date résa, _#num voilier_ <sup>u1</sup>, _#num semaine_ <sup>u1</sup>, tarif)\n  - Le champ _num résa_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Réservation_.\n  - Les champs _arrhes_ et _date résa_ étaient déjà de simples attributs de l'entité _Réservation_.\n  - Le champ _num voilier_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Offrir_ à partir de l'entité _Voilier_ en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ _num semaine_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Offrir_ à partir de l'entité _Semaine_ en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ _tarif_ a migré à partir de l'association de dépendance fonctionnelle _Offrir_.\n\n- **Semaine** (<u>num semaine</u>, date début <sup>u1</sup>)\n  - Le champ _num semaine_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Semaine_.\n  - Le champ _date début_ était déjà un simple attribut de l'entité _Semaine_. Il obéit à la contrainte d'unicité 1.\n\n- **Voilier** (<u>num voilier</u>, longueur)\n  - Le champ _num voilier_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Voilier_.\n  - Le champ _longueur_ était déjà un simple attribut de l'entité _Voilier_.\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{cluster\\_NN1}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Réservation} (\\prim{num résa}, \\attr{arrhes}, \\attr{date résa}, \\foreign{num voilier}$^{u\\_1}$, \\foreign{num semaine}$^{u\\_1}$, \\attr{tarif})\n  \\begin{itemize}\n    \\item Le champ \\emph{num résa} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Réservation}.\n    \\item Les champs \\emph{arrhes} et \\emph{date résa} étaient déjà de simples attributs de l'entité \\emph{Réservation}.\n    \\item Le champ \\emph{num voilier} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Offrir} à partir de l'entité \\emph{Voilier} en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{num semaine} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Offrir} à partir de l'entité \\emph{Semaine} en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{tarif} a migré à partir de l'association de dépendance fonctionnelle \\emph{Offrir}.\n  \\end{itemize}\n\n  \\item \\relat{Semaine} (\\prim{num semaine}, \\attr{date début}$^{u\\_1}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{num semaine} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Semaine}.\n    \\item Le champ \\emph{date début} était déjà un simple attribut de l'entité \\emph{Semaine}. Il obéit à la contrainte d'unicité 1.\n  \\end{itemize}\n\n  \\item \\relat{Voilier} (\\prim{num voilier}, \\attr{longueur})\n  \\begin{itemize}\n    \\item Le champ \\emph{num voilier} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Voilier}.\n    \\item Le champ \\emph{longueur} était déjà un simple attribut de l'entité \\emph{Voilier}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/cluster_NN1/mld/cluster_NN1_0_mld.txt",
    "content": "- Réservation (_num résa_, arrhes, date résa, #num voilier¹, #num semaine¹, tarif)\n  - Le champ « num résa » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Réservation ».\n  - Les champs « arrhes » et « date résa » étaient déjà de simples attributs de l'entité « Réservation ».\n  - Le champ « num voilier » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Offrir » à partir de l'entité « Voilier » en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ « num semaine » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Offrir » à partir de l'entité « Semaine » en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ « tarif » a migré à partir de l'association de dépendance fonctionnelle « Offrir ».\n\n- Semaine (_num semaine_, date début¹)\n  - Le champ « num semaine » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Semaine ».\n  - Le champ « date début » était déjà un simple attribut de l'entité « Semaine ». Il obéit à la contrainte d'unicité 1.\n\n- Voilier (_num voilier_, longueur)\n  - Le champ « num voilier » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Voilier ».\n  - Le champ « longueur » était déjà un simple attribut de l'entité « Voilier ».\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_create_df_arrows=across.mcd",
    "content": "Voilier: num voilier, longueur\nOffrir, 0N> Voilier, 0N> Semaine, /11 Réservation: tarif\nSemaine: num semaine, 1_date début\n\nRéservation: num résa, arrhes, date résa\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_drain.mcd",
    "content": "Voilier: num voilier, longueur\nOffrir, 0N Voilier, 0N Semaine, /11 Réservation\nSemaine: num semaine, 1_date début\n\nRéservation: num résa, arrhes, date résa, tarif\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 4_, 0N ENTITÉ 1_, 0N ENTITÉ 2_, /11 ENTITÉ 3_: at 4 1\nENTITÉ 2_: at 2 1, 1_at 2 2\n\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/cluster_NN1/rewritten/cluster_NN1_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/complex/_complex.mcd",
    "content": ":\n      PÉRIODE: date début, _date fin\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n:\n:\n\nENCLOS: num. enclos\n      OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\n  ANIMAL: nom, sexe, _date naissance, date décès\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  CARNIVORE: quantité viande\n\nPEUT VIVRE DANS, 1N ESPÈCE, 1N ENCLOS: nb. max. congénères\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n  DF, 0N ESPÈCE, _11 ANIMAL\n  HERBIVORE: plante préférée\n:\n\n:\n    PEUT COHABITER AVEC, 0N ESPÈCE, 0N [commensale] ESPÈCE: nb. max. commensaux\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/ddl/complex_ddl.d2",
    "content": "\"ANIMAL\": { shape: sql_table\n  \"code espèce\":         VARCHAR(42) {constraint: [PK; FK]}\n  \"nom\":                 VARCHAR(42) {constraint: PK}\n  \"date naissance\":      VARCHAR(42) {constraint: PK}\n  \"sexe\":                VARCHAR(42) \n  \"date décès\":          VARCHAR(42) \n  \"code espèce mère\":    VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"nom mère\":            VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"date naissance mère\": VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"type alimentation\":   UNSIGNED INT {constraint: \"NULL\"}\n  \"est carnivore\":       BOOLEAN {constraint: NOT NULL}\n  \"quantité viande\":     VARCHAR(42) {constraint: \"NULL\"}\n  \"est herbivore\":       BOOLEAN {constraint: NOT NULL}\n  \"plante préférée\":     VARCHAR(42) {constraint: \"NULL\"}\n}\n\n\"ESPÈCE\": { shape: sql_table\n  \"code espèce\":      VARCHAR(42) {constraint: PK}\n  \"nom latin\":        VARCHAR(42) {constraint: UNQ1}\n  \"nom vernaculaire\": VARCHAR(42) \n}\n\n\"OCCUPE\": { shape: sql_table\n  \"code espèce\":    VARCHAR(42) {constraint: [PK; FK]}\n  \"nom\":            VARCHAR(42) {constraint: [PK; FK]}\n  \"date naissance\": VARCHAR(42) {constraint: [PK; FK]}\n  \"num. enclos\":    VARCHAR(42) {constraint: PK}\n  \"date début\":     VARCHAR(42) {constraint: NOT NULL}\n  \"date fin\":       VARCHAR(42) {constraint: NOT NULL}\n}\n\n\"PEUT COHABITER AVEC\": { shape: sql_table\n  \"code espèce\":            VARCHAR(42) {constraint: [PK; FK]}\n  \"code espèce commensale\": VARCHAR(42) {constraint: [PK; FK]}\n  \"nb. max. commensaux\":    VARCHAR(42) \n}\n\n\"PEUT VIVRE DANS\": { shape: sql_table\n  \"code espèce\":         VARCHAR(42) {constraint: [PK; FK]}\n  \"num. enclos\":         VARCHAR(42) {constraint: PK}\n  \"nb. max. congénères\": VARCHAR(42) \n}\n\n\"ANIMAL\".\"code espèce\" -> \"ESPÈCE\".\"code espèce\"\n\"ANIMAL\".\"code espèce mère\" -> \"ANIMAL\".\"code espèce\"\n\"ANIMAL\".\"nom mère\" -> \"ANIMAL\".\"nom\"\n\"ANIMAL\".\"date naissance mère\" -> \"ANIMAL\".\"date naissance\"\n\"OCCUPE\".\"code espèce\" -> \"ANIMAL\".\"code espèce\"\n\"OCCUPE\".\"nom\" -> \"ANIMAL\".\"nom\"\n\"OCCUPE\".\"date naissance\" -> \"ANIMAL\".\"date naissance\"\n\"PEUT COHABITER AVEC\".\"code espèce\" -> \"ESPÈCE\".\"code espèce\"\n\"PEUT COHABITER AVEC\".\"code espèce commensale\" -> \"ESPÈCE\".\"code espèce\"\n\"PEUT VIVRE DANS\".\"code espèce\" -> \"ESPÈCE\".\"code espèce\"\n"
  },
  {
    "path": "test/zoo/complex/ddl/complex_ddl.dbml",
    "content": "Table \"ANIMAL\" {\n  \"code espèce\"         VARCHAR(42) [NOT NULL]\n  \"nom\"                 VARCHAR(42) [NOT NULL]\n  \"date naissance\"      VARCHAR(42) [NOT NULL]\n  \"sexe\"                VARCHAR(42)\n  \"date décès\"          VARCHAR(42)\n  \"code espèce mère\"    VARCHAR(42) [\"NULL\"]\n  \"nom mère\"            VARCHAR(42) [\"NULL\"]\n  \"date naissance mère\" VARCHAR(42) [\"NULL\"]\n  \"type alimentation\"   UNSIGNED_INT [\"NULL\"]\n  \"est carnivore\"       BOOLEAN [NOT NULL]\n  \"quantité viande\"     VARCHAR(42) [\"NULL\"]\n  \"est herbivore\"       BOOLEAN [NOT NULL]\n  \"plante préférée\"     VARCHAR(42) [\"NULL\"]\n  Indexes {\n    (\"code espèce\", \"nom\", \"date naissance\") [pk]\n  }\n}\n\nTable \"ESPÈCE\" {\n  \"code espèce\"      VARCHAR(42) [pk, NOT NULL]\n  \"nom latin\"        VARCHAR(42)\n  \"nom vernaculaire\" VARCHAR(42)\n  Indexes {\n    \"nom latin\" [unique]\n  }\n}\n\nTable \"OCCUPE\" {\n  \"code espèce\"    VARCHAR(42) [NOT NULL]\n  \"nom\"            VARCHAR(42) [NOT NULL]\n  \"date naissance\" VARCHAR(42) [NOT NULL]\n  \"num. enclos\"    VARCHAR(42) [NOT NULL]\n  \"date début\"     VARCHAR(42) [NOT NULL]\n  \"date fin\"       VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"code espèce\", \"nom\", \"date naissance\", \"num. enclos\") [pk]\n  }\n}\n\nTable \"PEUT COHABITER AVEC\" {\n  \"code espèce\"            VARCHAR(42) [NOT NULL]\n  \"code espèce commensale\" VARCHAR(42) [NOT NULL]\n  \"nb. max. commensaux\"    VARCHAR(42)\n  Indexes {\n    (\"code espèce\", \"code espèce commensale\") [pk]\n  }\n}\n\nTable \"PEUT VIVRE DANS\" {\n  \"code espèce\"         VARCHAR(42) [NOT NULL]\n  \"num. enclos\"         VARCHAR(42) [NOT NULL]\n  \"nb. max. congénères\" VARCHAR(42)\n  Indexes {\n    (\"code espèce\", \"num. enclos\") [pk]\n  }\n}\n\nRef:\"ANIMAL\".\"code espèce\" > \"ESPÈCE\".\"code espèce\"\nRef:\"ANIMAL\".(\"code espèce mère\", \"date naissance mère\", \"nom mère\") > \"ANIMAL\".(\"code espèce\", \"date naissance\", \"nom\")\nRef:\"OCCUPE\".(\"code espèce\", \"date naissance\", \"nom\") > \"ANIMAL\".(\"code espèce\", \"date naissance\", \"nom\")\nRef:\"PEUT COHABITER AVEC\".(\"code espèce\", \"code espèce commensale\") > \"ESPÈCE\".(\"code espèce\", \"code espèce\")\nRef:\"PEUT VIVRE DANS\".\"code espèce\" > \"ESPÈCE\".\"code espèce\"\n"
  },
  {
    "path": "test/zoo/complex/ddl/complex_ddl.sql",
    "content": "CREATE TABLE ANIMAL (\n  PRIMARY KEY (code_espece, nom, date_naissance),\n  code_espece         VARCHAR(8) NOT NULL,\n  nom                 VARCHAR(255) NOT NULL,\n  date_naissance      DATE NOT NULL,\n  sexe                CHAR(1),\n  date_deces          DATE,\n  code_espece_mere    VARCHAR(8) NULL,\n  nom_mere            VARCHAR(255) NULL,\n  date_naissance_mere DATE NULL,\n  type_alimentation   UNSIGNED INT NULL,\n  est_carnivore       BOOLEAN NOT NULL,\n  quantite_viande     INTEGER NULL,\n  est_herbivore       BOOLEAN NOT NULL,\n  plante_preferee     VARCHAR(42) NULL\n);\n\nCREATE TABLE ESPECE (\n  PRIMARY KEY (code_espece),\n  code_espece      VARCHAR(8) NOT NULL,\n  nom_latin        VARCHAR(255),\n  nom_vernaculaire VARCHAR(255),\n  UNIQUE (nom_latin)\n);\n\nCREATE TABLE OCCUPE (\n  PRIMARY KEY (code_espece, nom, date_naissance, num_enclos),\n  code_espece    VARCHAR(8) NOT NULL,\n  nom            VARCHAR(255) NOT NULL,\n  date_naissance DATE NOT NULL,\n  num_enclos     VARCHAR(8) NOT NULL,\n  date_debut     DATE NOT NULL,\n  date_fin       DATE NOT NULL\n);\n\nCREATE TABLE PEUT_COHABITER_AVEC (\n  PRIMARY KEY (code_espece, code_espece_commensale),\n  code_espece            VARCHAR(8) NOT NULL,\n  code_espece_commensale VARCHAR(8) NOT NULL,\n  nb_max_commensaux      INTEGER\n);\n\nCREATE TABLE PEUT_VIVRE_DANS (\n  PRIMARY KEY (code_espece, num_enclos),\n  code_espece       VARCHAR(8) NOT NULL,\n  num_enclos        VARCHAR(8) NOT NULL,\n  nb_max_congeneres INTEGER\n);\n\nALTER TABLE ANIMAL ADD FOREIGN KEY (code_espece_mere, nom_mere, date_naissance_mere) REFERENCES ANIMAL (code_espece, nom, date_naissance);\nALTER TABLE ANIMAL ADD FOREIGN KEY (code_espece) REFERENCES ESPECE (code_espece);\n\nALTER TABLE OCCUPE ADD FOREIGN KEY (code_espece, nom, date_naissance) REFERENCES ANIMAL (code_espece, nom, date_naissance);\n\nALTER TABLE PEUT_COHABITER_AVEC ADD FOREIGN KEY (code_espece_commensale) REFERENCES ESPECE (code_espece);\nALTER TABLE PEUT_COHABITER_AVEC ADD FOREIGN KEY (code_espece) REFERENCES ESPECE (code_espece);\n\nALTER TABLE PEUT_VIVRE_DANS ADD FOREIGN KEY (code_espece) REFERENCES ESPECE (code_espece);\n"
  },
  {
    "path": "test/zoo/complex/exported/complex_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"PÉRIODE\"]\n  6 [label=\"ENCLOS\"]\n  5 [label=\"ANIMAL\",peripheries=2]\n  16 [label=\"ESPÈCE\"]\n\n  // Associative entities\n  13 [label=\"CARNIVORE\",shape=Mdiamond]\n  22 [label=\"HERBIVORE\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  10 [label=\"sexe\"]\n  12 [label=\"date\\ndécès\"]\n  19 [label=\"nom\\nlatin\"]\n  20 [label=\"nom\\nvernaculaire\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>date<br/>début</u>>]\n  3 [label=<<u>date fin</u>>]\n  7 [label=<<u>num.<br/>enclos</u>>]\n  9 [label=<<u>nom</u>> style=\"dashed,filled\"]\n  11 [label=<<u>date<br/>naissance</u>> style=\"dashed,filled\"]\n  14 [label=<<u>quantité<br/>viande</u>>]\n  18 [label=<<u>code<br/>espèce</u>>]\n  23 [label=<<u>plante<br/>préférée</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  17 [label=\"nb. max.\\ncongénères\"]\n  25 [label=\"nb. max.\\ncommensaux\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"A MÈRE\"]\n  8 [label=\"OCCUPE\"]\n  15 [label=\"PEUT VIVRE\\nDANS\"]\n  21 [label=\"DF\",peripheries=2]\n  24 [label=\"PEUT\\nCOHABITER\\nAVEC\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 9\n  5 -- 10\n  5 -- 11\n  5 -- 12\n  6 -- 7\n  13 -- 14\n  16 -- 18\n  16 -- 19\n  16 -- 20\n  22 -- 23\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  15 -- 17\n  24 -- 25\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 8\n  5 -- 4 [color=\"#000000\"]\n  16 -- 21 [color=\"#000000\"]\n  edge [headlabel=M]\n  6 -- 15\n  16 -- 24 [color=\"#000000\"]\n  edge [headlabel=N]\n  5 -- 8\n  5 -- 21\n  6 -- 8\n  16 -- 15\n  4 -- 5 [color=\"#000000\"]\n  24 -- 16 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/complex/exported/complex_erd_chen.txt",
    "content": "[ENCLOS] ==M== <PEUT VIVRE DANS>\n[ENCLOS] ==N== <OCCUPE>\n[ESPÈCE] --1-- <<DF>>\n[ESPÈCE] --M-- <PEUT COHABITER AVEC>\n[ESPÈCE] --N-- <PEUT COHABITER AVEC>\n[ESPÈCE] ==N== <PEUT VIVRE DANS>\n[PÉRIODE] ==1== <OCCUPE>\n[[ANIMAL]] --1-- <A MÈRE>\n[[ANIMAL]] --N-- <A MÈRE>\n[[ANIMAL]] ==N== <<DF>>\n[[ANIMAL]] ==N== <OCCUPE>\n"
  },
  {
    "path": "test/zoo/complex/exported/complex_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/complex/exported/complex_uml.puml",
    "content": "@startuml \"complex\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"PÉRIODE\") {\n    {field} + pk(date début)\n    {field} + pk(date fin)\n}\n\n\"ANIMAL\" \"*\" --- \"1..*\" \"ANIMAL\": \"A MÈRE\"\n\nTable(\"ENCLOS\") {\n    {field} + pk(num. enclos)\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1..*\" \"ANIMAL\"\nN_ARY_0 -- \"1\" \"PÉRIODE\"\nN_ARY_0 -- \"1..*\" \"ENCLOS\"\n\nTable(\"ANIMAL\") {\n    {field} + pk(nom)\n    {field} + sexe\n    {field} + pk(date naissance)\n    {field} + date décès\n}\n\nnote \"{incomplete, overlapping}\" as GENERALIZATION_1\nGENERALIZATION_1 -[dotted]- HERBIVORE\nGENERALIZATION_1 -[dotted]- CARNIVORE\nANIMAL <|-- HERBIVORE\nANIMAL <|-- CARNIVORE\n\nTable(\"CARNIVORE\") {\n    {field} + pk(quantité viande)\n}\n\n\"ESPÈCE\" \"1..*\" --- \"1..*\" \"ENCLOS\": \"PEUT VIVRE DANS\"\n(\"ESPÈCE\", \"ENCLOS\") .. \"PEUT VIVRE DANS\"\nTable(\"PEUT VIVRE DANS\") {\n    {field} + nb. max. congénères\n}\n\nTable(\"ESPÈCE\") {\n    {field} + pk(code espèce)\n    {field} + nom latin\n    {field} + nom vernaculaire\n}\n\n\"ESPÈCE\" \"1\" *-- \"*\" \"ANIMAL\"\n\nTable(\"HERBIVORE\") {\n    {field} + pk(plante préférée)\n}\n\n\"ESPÈCE\" \"*\" --- \"*\" \"ESPÈCE\": \"PEUT COHABITER AVEC\"\n(\"ESPÈCE\", \"ESPÈCE\") .. \"PEUT COHABITER AVEC\"\nTable(\"PEUT COHABITER AVEC\") {\n    {field} + nb. max. commensaux\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nANIMAL\tcode espèce\t!\t\tstrengthening_primary_foreign_key\tTrue\tESPÈCE\tESPÈCE\tDF\t\t\nANIMAL\tnom\t!\t\tprimary_key\tTrue\t\t\t\t\t\nANIMAL\tdate naissance\t!\t\tprimary_key\tTrue\t\t\t\t\t\nANIMAL\tsexe\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nANIMAL\tdate décès\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nANIMAL\tcode espèce\t?\t\tforeign_key\tFalse\tANIMAL\tANIMAL\tA MÈRE\t\tmère\nANIMAL\tnom\t?\t\tforeign_key\tFalse\tANIMAL\tANIMAL\tA MÈRE\t\tmère\nANIMAL\tdate naissance\t?\t\tforeign_key\tFalse\tANIMAL\tANIMAL\tA MÈRE\t\tmère\nANIMAL\ttype alimentation\t?\t\tdeleted_child_discriminator_\tFalse\t\t\t\tUNSIGNED_INT_PLACEHOLDER\t\nANIMAL\test carnivore\t!\t\tdeleted_child_entity_name\tFalse\tCARNIVORE\tCARNIVORE\t\tBOOLEAN_PLACEHOLDER\t\nANIMAL\tquantité viande\t?\t\tdeleted_child_attribute\tFalse\tCARNIVORE\t\t\t\t\nANIMAL\test herbivore\t!\t\tdeleted_child_entity_name\tFalse\tHERBIVORE\tHERBIVORE\t\tBOOLEAN_PLACEHOLDER\t\nANIMAL\tplante préférée\t?\t\tdeleted_child_attribute\tFalse\tHERBIVORE\t\t\t\t\nESPÈCE\tcode espèce\t!\t\tprimary_key\tTrue\t\t\t\t\t\nESPÈCE\tnom latin\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nESPÈCE\tnom vernaculaire\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nOCCUPE\tcode espèce\t!\t\tprimary_foreign_key\tTrue\tANIMAL\tANIMAL\tOCCUPE\t\t\nOCCUPE\tnom\t!\t\tprimary_foreign_key\tTrue\tANIMAL\tANIMAL\tOCCUPE\t\t\nOCCUPE\tdate naissance\t!\t\tprimary_foreign_key\tTrue\tANIMAL\tANIMAL\tOCCUPE\t\t\nOCCUPE\tnum. enclos\t!\t\tprimary_ex_foreign_key\tTrue\tENCLOS\tENCLOS\tOCCUPE\t\t\nOCCUPE\tdate début\t!\t\tstopped_ex_foreign_key\tFalse\tPÉRIODE\tPÉRIODE\tOCCUPE\t\t\nOCCUPE\tdate fin\t!\t\tstopped_ex_foreign_key\tFalse\tPÉRIODE\tPÉRIODE\tOCCUPE\t\t\nPEUT COHABITER AVEC\tcode espèce\t!\t\tprimary_foreign_key\tTrue\tESPÈCE\tESPÈCE\tPEUT COHABITER AVEC\t\t\nPEUT COHABITER AVEC\tcode espèce\t!\t\tprimary_foreign_key\tTrue\tESPÈCE\tESPÈCE\tPEUT COHABITER AVEC\t\tcommensale\nPEUT COHABITER AVEC\tnb. max. commensaux\t\t\tassociation_attribute\tFalse\t\t\tPEUT COHABITER AVEC\t\t\nPEUT VIVRE DANS\tcode espèce\t!\t\tprimary_foreign_key\tTrue\tESPÈCE\tESPÈCE\tPEUT VIVRE DANS\t\t\nPEUT VIVRE DANS\tnum. enclos\t!\t\tprimary_ex_foreign_key\tTrue\tENCLOS\tENCLOS\tPEUT VIVRE DANS\t\t\nPEUT VIVRE DANS\tnb. max. congénères\t\t\tassociation_attribute\tFalse\t\t\tPEUT VIVRE DANS\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"ANIMAL\" -> \"ANIMAL\"\n  \"ESPÈCE\" -> \"ANIMAL\"\n  \"ANIMAL\" -> \"OCCUPE\"\n  \"ESPÈCE\" -> \"PEUT COHABITER AVEC\"\n  \"ESPÈCE\" -> \"PEUT VIVRE DANS\"\n}\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"complex_mld.svg\"/></center><figcaption>MCD <i>complex</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>ANIMAL</span> (\n    <span class='foreign primary'>#code espèce</span>,\n    <span class='primary'>nom</span>,\n    <span class='primary'>date naissance</span>,\n    <span class='normal'>sexe</span>,\n    <span class='normal'>date décès</span>,\n    <span class='foreign'>#code espèce mère?</span>,\n    <span class='foreign'>#nom mère?</span>,\n    <span class='foreign'>#date naissance mère?</span>,\n    <span class='normal'>type alimentation?</span>,\n    <span class='normal'>est carnivore!</span>,\n    <span class='normal'>quantité viande?</span>,\n    <span class='normal'>est herbivore!</span>,\n    <span class='normal'>plante préférée?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code espèce</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>ESPÈCE</i> pour renforcer l'identifiant.</li>\n    <li>Les champs <i>nom</i> et <i>date naissance</i> font partie de la clé primaire de la table. C'étaient déjà des identifiants de l'entité <i>ANIMAL</i>.</li>\n    <li>Les champs <i>sexe</i> et <i>date décès</i> étaient déjà de simples attributs de l'entité <i>ANIMAL</i>.</li>\n    <li>Les champs à saisie facultative <i>code espèce mère</i>, <i>nom mère</i> et <i>date naissance mère</i> sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle <i>A MÈRE</i> à partir de l'entité <i>ANIMAL</i> en perdant leur caractère identifiant.</li>\n    <li>Un discriminateur à saisie facultative <i>type alimentation</i> est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l'absence de contrainte de totalité.</li>\n    <li>Un champ booléen à saisie obligatoire <i>est carnivore</i> est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.</li>\n    <li>Le champ à saisie facultative <i>quantité viande</i> a migré à partir de l'entité-fille <i>CARNIVORE</i> (supprimée).</li>\n    <li>Un champ booléen à saisie obligatoire <i>est herbivore</i> est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.</li>\n    <li>Le champ à saisie facultative <i>plante préférée</i> a migré à partir de l'entité-fille <i>HERBIVORE</i> (supprimée).</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ESPÈCE</span> (\n    <span class='primary'>code espèce</span>,\n    <span class='normal'>nom latin</span> <sup>u1</sup>,\n    <span class='normal'>nom vernaculaire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code espèce</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>ESPÈCE</i>.</li>\n    <li>Le champ <i>nom latin</i> était déjà un simple attribut de l'entité <i>ESPÈCE</i>. Il obéit à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>nom vernaculaire</i> était déjà un simple attribut de l'entité <i>ESPÈCE</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>OCCUPE</span> (\n    <span class='foreign primary'>#code espèce</span>,\n    <span class='foreign primary'>#nom</span>,\n    <span class='foreign primary'>#date naissance</span>,\n    <span class='primary'>num. enclos</span>,\n    <span class='normal'>date début!</span>,\n    <span class='normal'>date fin!</span>\n  )</summary>\n  <ul>\n    <li>Les champs <i>code espèce</i>, <i>nom</i> et <i>date naissance</i> font partie de la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité <i>ANIMAL</i>.</li>\n    <li>Le champ <i>num. enclos</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>ENCLOS</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Les champs à saisie obligatoire <i>date début</i> et <i>date fin</i> sont de simples attributs. Ils ont migré directement à partir de l'entité <i>PÉRIODE</i> en perdant leur caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, ils ne sont pas considérés comme clés étrangères.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PEUT COHABITER AVEC</span> (\n    <span class='foreign primary'>#code espèce</span>,\n    <span class='foreign primary'>#code espèce commensale</span>,\n    <span class='normal'>nb. max. commensaux</span>\n  )</summary>\n  <ul>\n    <li>Les champs <i>code espèce</i> et <i>code espèce commensale</i> constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité <i>ESPÈCE</i>.</li>\n    <li>Le champ <i>nb. max. commensaux</i> était déjà un simple attribut de l'association <i>PEUT COHABITER AVEC</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PEUT VIVRE DANS</span> (\n    <span class='foreign primary'>#code espèce</span>,\n    <span class='primary'>num. enclos</span>,\n    <span class='normal'>nb. max. congénères</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code espèce</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>ESPÈCE</i>.</li>\n    <li>Le champ <i>num. enclos</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>ENCLOS</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>nb. max. congénères</i> était déjà un simple attribut de l'association <i>PEUT VIVRE DANS</i>.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>ENCLOS</i> et <i>PÉRIODE</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_mld.mcd",
    "content": ":::\nOCCUPE: #code espèce > ANIMAL > code espèce, _#nom > ANIMAL > nom, _#date naissance > ANIMAL > date naissance, _num. enclos, date début, date fin\n:\nANIMAL: #code espèce > ESPÈCE > code espèce, _nom, _date naissance, sexe, date décès, #code espèce mère > ANIMAL > code espèce, #nom mère > ANIMAL > nom, #date naissance mère > ANIMAL > date naissance, type alimentation, est carnivore, quantité viande, est herbivore, plante préférée\n:\n\n\n:\nPEUT VIVRE DANS: #code espèce > ESPÈCE > code espèce, _num. enclos, nb. max. congénères\n:\nESPÈCE: code espèce, nom latin, nom vernaculaire\n:::\n\n\n:::\nPEUT COHABITER AVEC: #code espèce > ESPÈCE > code espèce, _#code espèce commensale > ESPÈCE > code espèce, nb. max. commensaux\n:::\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_mld.md",
    "content": "- **ANIMAL** (<u>_#code espèce_</u>, <u>nom</u>, <u>date naissance</u>, sexe, date décès, _#code espèce mère?_, _#nom mère?_, _#date naissance mère?_, type alimentation?, est carnivore!, quantité viande?, est herbivore!, plante préférée?)\n  - Le champ _code espèce_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _ESPÈCE_ pour renforcer l'identifiant.\n  - Les champs _nom_ et _date naissance_ font partie de la clé primaire de la table. C'étaient déjà des identifiants de l'entité _ANIMAL_.\n  - Les champs _sexe_ et _date décès_ étaient déjà de simples attributs de l'entité _ANIMAL_.\n  - Les champs à saisie facultative _code espèce mère_, _nom mère_ et _date naissance mère_ sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle _A MÈRE_ à partir de l'entité _ANIMAL_ en perdant leur caractère identifiant.\n  - Un discriminateur à saisie facultative _type alimentation_ est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l'absence de contrainte de totalité.\n  - Un champ booléen à saisie obligatoire _est carnivore_ est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n  - Le champ à saisie facultative _quantité viande_ a migré à partir de l'entité-fille _CARNIVORE_ (supprimée).\n  - Un champ booléen à saisie obligatoire _est herbivore_ est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n  - Le champ à saisie facultative _plante préférée_ a migré à partir de l'entité-fille _HERBIVORE_ (supprimée).\n\n- **ESPÈCE** (<u>code espèce</u>, nom latin <sup>u1</sup>, nom vernaculaire)\n  - Le champ _code espèce_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _ESPÈCE_.\n  - Le champ _nom latin_ était déjà un simple attribut de l'entité _ESPÈCE_. Il obéit à la contrainte d'unicité 1.\n  - Le champ _nom vernaculaire_ était déjà un simple attribut de l'entité _ESPÈCE_.\n\n- **OCCUPE** (<u>_#code espèce_</u>, <u>_#nom_</u>, <u>_#date naissance_</u>, <u>num. enclos</u>, date début!, date fin!)\n  - Les champs _code espèce_, _nom_ et _date naissance_ font partie de la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité _ANIMAL_.\n  - Le champ _num. enclos_ fait partie de la clé primaire de la table. Sa table d'origine (_ENCLOS_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Les champs à saisie obligatoire _date début_ et _date fin_ sont de simples attributs. Ils ont migré directement à partir de l'entité _PÉRIODE_ en perdant leur caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, ils ne sont pas considérés comme clés étrangères.\n\n- **PEUT COHABITER AVEC** (<u>_#code espèce_</u>, <u>_#code espèce commensale_</u>, nb. max. commensaux)\n  - Les champs _code espèce_ et _code espèce commensale_ constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité _ESPÈCE_.\n  - Le champ _nb. max. commensaux_ était déjà un simple attribut de l'association _PEUT COHABITER AVEC_.\n\n- **PEUT VIVRE DANS** (<u>_#code espèce_</u>, <u>num. enclos</u>, nb. max. congénères)\n  - Le champ _code espèce_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _ESPÈCE_.\n  - Le champ _num. enclos_ fait partie de la clé primaire de la table. Sa table d'origine (_ENCLOS_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _nb. max. congénères_ était déjà un simple attribut de l'association _PEUT VIVRE DANS_.\n<br>\n----\n\n\n**NB.** Les tables _ENCLOS_ et _PÉRIODE_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{complex}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{ANIMAL} (\\foreign{\\prim{code espèce}}, \\prim{nom}, \\prim{date naissance}, \\attr{sexe}, \\attr{date décès}, \\foreign{code espèce mère?}, \\foreign{nom mère?}, \\foreign{date naissance mère?}, \\attr{type alimentation?}, \\attr{est carnivore!}, \\attr{quantité viande?}, \\attr{est herbivore!}, \\attr{plante préférée?})\n  \\begin{itemize}\n    \\item Le champ \\emph{code espèce} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{ESPÈCE} pour renforcer l'identifiant.\n    \\item Les champs \\emph{nom} et \\emph{date naissance} font partie de la clé primaire de la table. C'étaient déjà des identifiants de l'entité \\emph{ANIMAL}.\n    \\item Les champs \\emph{sexe} et \\emph{date décès} étaient déjà de simples attributs de l'entité \\emph{ANIMAL}.\n    \\item Les champs à saisie facultative \\emph{code espèce mère}, \\emph{nom mère} et \\emph{date naissance mère} sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle \\emph{A MÈRE} à partir de l'entité \\emph{ANIMAL} en perdant leur caractère identifiant.\n    \\item Un discriminateur à saisie facultative \\emph{type alimentation} est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l'absence de contrainte de totalité.\n    \\item Un champ booléen à saisie obligatoire \\emph{est carnivore} est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n    \\item Le champ à saisie facultative \\emph{quantité viande} a migré à partir de l'entité-fille \\emph{CARNIVORE} (supprimée).\n    \\item Un champ booléen à saisie obligatoire \\emph{est herbivore} est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n    \\item Le champ à saisie facultative \\emph{plante préférée} a migré à partir de l'entité-fille \\emph{HERBIVORE} (supprimée).\n  \\end{itemize}\n\n  \\item \\relat{ESPÈCE} (\\prim{code espèce}, \\attr{nom latin}$^{u\\_1}$, \\attr{nom vernaculaire})\n  \\begin{itemize}\n    \\item Le champ \\emph{code espèce} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{ESPÈCE}.\n    \\item Le champ \\emph{nom latin} était déjà un simple attribut de l'entité \\emph{ESPÈCE}. Il obéit à la contrainte d'unicité 1.\n    \\item Le champ \\emph{nom vernaculaire} était déjà un simple attribut de l'entité \\emph{ESPÈCE}.\n  \\end{itemize}\n\n  \\item \\relat{OCCUPE} (\\foreign{\\prim{code espèce}}, \\foreign{\\prim{nom}}, \\foreign{\\prim{date naissance}}, \\prim{num. enclos}, \\attr{date début!}, \\attr{date fin!})\n  \\begin{itemize}\n    \\item Les champs \\emph{code espèce}, \\emph{nom} et \\emph{date naissance} font partie de la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité \\emph{ANIMAL}.\n    \\item Le champ \\emph{num. enclos} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{ENCLOS}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Les champs à saisie obligatoire \\emph{date début} et \\emph{date fin} sont de simples attributs. Ils ont migré directement à partir de l'entité \\emph{PÉRIODE} en perdant leur caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, ils ne sont pas considérés comme clés étrangères.\n  \\end{itemize}\n\n  \\item \\relat{PEUT COHABITER AVEC} (\\foreign{\\prim{code espèce}}, \\foreign{\\prim{code espèce commensale}}, \\attr{nb. max. commensaux})\n  \\begin{itemize}\n    \\item Les champs \\emph{code espèce} et \\emph{code espèce commensale} constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité \\emph{ESPÈCE}.\n    \\item Le champ \\emph{nb. max. commensaux} était déjà un simple attribut de l'association \\emph{PEUT COHABITER AVEC}.\n  \\end{itemize}\n\n  \\item \\relat{PEUT VIVRE DANS} (\\foreign{\\prim{code espèce}}, \\prim{num. enclos}, \\attr{nb. max. congénères})\n  \\begin{itemize}\n    \\item Le champ \\emph{code espèce} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{ESPÈCE}.\n    \\item Le champ \\emph{num. enclos} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{ENCLOS}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{nb. max. congénères} était déjà un simple attribut de l'association \\emph{PEUT VIVRE DANS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/complex/mld/complex_mld.txt",
    "content": "- ANIMAL (_#code espèce_, _nom_, _date naissance_, sexe, date décès, #code espèce mère?, #nom mère?, #date naissance mère?, type alimentation?, est carnivore!, quantité viande?, est herbivore!, plante préférée?)\n  - Le champ « code espèce » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « ESPÈCE » pour renforcer l'identifiant.\n  - Les champs « nom » et « date naissance » font partie de la clé primaire de la table. C'étaient déjà des identifiants de l'entité « ANIMAL ».\n  - Les champs « sexe » et « date décès » étaient déjà de simples attributs de l'entité « ANIMAL ».\n  - Les champs à saisie facultative « code espèce mère », « nom mère » et « date naissance mère » sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle « A MÈRE » à partir de l'entité « ANIMAL » en perdant leur caractère identifiant.\n  - Un discriminateur à saisie facultative « type alimentation » est ajouté pour indiquer la nature de la spécialisation. Peut être vide, du fait de l'absence de contrainte de totalité.\n  - Un champ booléen à saisie obligatoire « est carnivore » est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n  - Le champ à saisie facultative « quantité viande » a migré à partir de l'entité-fille « CARNIVORE » (supprimée).\n  - Un champ booléen à saisie obligatoire « est herbivore » est ajouté pour indiquer si on a affaire ou pas à la spécialisation de même nom.\n  - Le champ à saisie facultative « plante préférée » a migré à partir de l'entité-fille « HERBIVORE » (supprimée).\n\n- ESPÈCE (_code espèce_, nom latin¹, nom vernaculaire)\n  - Le champ « code espèce » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « ESPÈCE ».\n  - Le champ « nom latin » était déjà un simple attribut de l'entité « ESPÈCE ». Il obéit à la contrainte d'unicité 1.\n  - Le champ « nom vernaculaire » était déjà un simple attribut de l'entité « ESPÈCE ».\n\n- OCCUPE (_#code espèce_, _#nom_, _#date naissance_, _num. enclos_, date début!, date fin!)\n  - Les champs « code espèce », « nom » et « date naissance » font partie de la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité « ANIMAL ».\n  - Le champ « num. enclos » fait partie de la clé primaire de la table. Sa table d'origine (« ENCLOS ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Les champs à saisie obligatoire « date début » et « date fin » sont de simples attributs. Ils ont migré directement à partir de l'entité « PÉRIODE » en perdant leur caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, ils ne sont pas considérés comme clés étrangères.\n\n- PEUT COHABITER AVEC (_#code espèce_, _#code espèce commensale_, nb. max. commensaux)\n  - Les champs « code espèce » et « code espèce commensale » constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité « ESPÈCE ».\n  - Le champ « nb. max. commensaux » était déjà un simple attribut de l'association « PEUT COHABITER AVEC ».\n\n- PEUT VIVRE DANS (_#code espèce_, _num. enclos_, nb. max. congénères)\n  - Le champ « code espèce » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « ESPÈCE ».\n  - Le champ « num. enclos » fait partie de la clé primaire de la table. Sa table d'origine (« ENCLOS ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « nb. max. congénères » était déjà un simple attribut de l'association « PEUT VIVRE DANS ».\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « ENCLOS » et « PÉRIODE » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_create_df_arrows=across.mcd",
    "content": ":\n      PÉRIODE: date début, _date fin\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n:\n:\n\nENCLOS: num. enclos\n      OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\n  ANIMAL: nom, sexe, _date naissance, date décès\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  CARNIVORE: quantité viande\n\nPEUT VIVRE DANS, 1N ESPÈCE, 1N ENCLOS: nb. max. congénères\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n  DF, 0N> ESPÈCE, _11 ANIMAL\n  HERBIVORE: plante préférée\n:\n\n:\n    PEUT COHABITER AVEC, 0N ESPÈCE, 0N [commensale] ESPÈCE: nb. max. commensaux\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_drown.mcd",
    "content": ":\n      ENTITÉ 01_: at 01 1, _at 01 2\n    ASSOC 07_, 01 ENTITÉ 03_, 0N> [rôle 1] ENTITÉ 03_\n:\n:\n\nENTITÉ 02_: at 02 1\n      ASSOC 08_, 1N ENTITÉ 03_, /1N ENTITÉ 01_, 1N ENTITÉ 02_\n  ENTITÉ 03_: at 03 1, at 03 2, _at 03 3, at 03 4\n  /\\\\ ENTITÉ 03_ <= ENTITÉ 04_, ENTITÉ 06_: type alimentation\n  ENTITÉ 04_: at 04 1\n\nASSOC 09_, 1N ENTITÉ 05_, 1N ENTITÉ 02_: at 09 1\nENTITÉ 05_: at 05 1, 1_at 05 2, at 05 3\n  DF, 0N ENTITÉ 05_, _11 ENTITÉ 03_\n  ENTITÉ 06_: at 06 1\n:\n\n:\n    ASSOC 11_, 0N ENTITÉ 05_, 0N [rôle 1] ENTITÉ 05_: at 11 1\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=2,weak.mcd",
    "content": ":\n:\n:\n    DF, _11 PEUT COHABITER AVEC, 0N [commensale] ESPÈCE\n    PEUT COHABITER AVEC: _nb. max. commensaux\n\n:\n:\nDF, _11 PEUT VIVRE DANS, 1N ESPÈCE\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n    DF, _11 PEUT COHABITER AVEC, 0N ESPÈCE\n\nENCLOS: num. enclos\nDF, _11 PEUT VIVRE DANS, 1N ENCLOS\nPEUT VIVRE DANS: _nb. max. congénères\n  DF, 0N ESPÈCE, _11 ANIMAL\n:\n\n      DF, _11 OCCUPE, 1N ENCLOS\n      OCCUPE:\n      DF, _11 OCCUPE, 1N ANIMAL\n  ANIMAL: nom, sexe, _date naissance, date décès\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n\n      PÉRIODE: date début, _date fin\n      DF, 11 OCCUPE, 1N PÉRIODE\n  CARNIVORE: quantité viande\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  HERBIVORE: plante préférée\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=2.5,weak.mcd",
    "content": "  HERBIVORE: plante préférée\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  CARNIVORE: quantité viande\n    DF, _11 PEUT COHABITER AVEC, 0N [commensale] ESPÈCE\n    PEUT COHABITER AVEC: _nb. max. commensaux\n\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n  ANIMAL: nom, sexe, _date naissance, date décès\n  DF, 0N ESPÈCE, _11 ANIMAL\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n    DF, _11 PEUT COHABITER AVEC, 0N ESPÈCE\n\n      PÉRIODE: date début, _date fin\n      OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\nPEUT VIVRE DANS: _nb. max. congénères\nDF, _11 PEUT VIVRE DANS, 1N ESPÈCE\n:\n\n:\nENCLOS: num. enclos\nDF, _11 PEUT VIVRE DANS, 1N ENCLOS\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=2.5.mcd",
    "content": "  HERBIVORE: plante préférée\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  CARNIVORE: quantité viande\n    DF, 11 PEUT COHABITER AVEC, 0N [commensale] ESPÈCE\n    PEUT COHABITER AVEC: id. peut cohabiter avec, nb. max. commensaux\n\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n  ANIMAL: nom, sexe, _date naissance, date décès\n  DF, 0N ESPÈCE, _11 ANIMAL\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n    DF, 11 PEUT COHABITER AVEC, 0N ESPÈCE\n\n      PÉRIODE: date début, _date fin\n      OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\nPEUT VIVRE DANS: id. peut vivre dans, nb. max. congénères\nDF, 11 PEUT VIVRE DANS, 1N ESPÈCE\n:\n\n:\nENCLOS: num. enclos\nDF, 11 PEUT VIVRE DANS, 1N ENCLOS\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=2.mcd",
    "content": "  HERBIVORE: plante préférée\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  CARNIVORE: quantité viande\n    DF, 11 PEUT COHABITER AVEC, 0N [commensale] ESPÈCE\n    PEUT COHABITER AVEC: id. peut cohabiter avec, nb. max. commensaux\n\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n  ANIMAL: nom, sexe, _date naissance, date décès\n  DF, 0N ESPÈCE, _11 ANIMAL\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n    DF, 11 PEUT COHABITER AVEC, 0N ESPÈCE\n\n      PÉRIODE: date début, _date fin\n      OCCUPE, 1N ANIMAL, /1N PÉRIODE, 1N ENCLOS\nPEUT VIVRE DANS: id. peut vivre dans, nb. max. congénères\nDF, 11 PEUT VIVRE DANS, 1N ESPÈCE\n:\n\n:\nENCLOS: num. enclos\nDF, 11 PEUT VIVRE DANS, 1N ENCLOS\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=3,weak.mcd",
    "content": ":\n:\n:\n:\n    A MÈRE, 01 ANIMAL, 0N> [mère] ANIMAL\n:\n:\n\n      PÉRIODE: date début, _date fin\n      DF, 11 OCCUPE, 1N PÉRIODE\n      OCCUPE:\n      DF, _11 OCCUPE, 1N ANIMAL\n  ANIMAL: nom, sexe, _date naissance, date décès\n  /\\\\ ANIMAL <= CARNIVORE, HERBIVORE: type alimentation\n  HERBIVORE: plante préférée\n\n:\n:\n      DF, _11 OCCUPE, 1N ENCLOS\n:\n  DF, 0N ESPÈCE, _11 ANIMAL\n  CARNIVORE: quantité viande\n:\n\n:\n:\nENCLOS: num. enclos\nPEUT VIVRE DANS, 1N ESPÈCE, 1N ENCLOS: nb. max. congénères\nESPÈCE: code espèce, 1_nom latin, nom vernaculaire\n:\n:\n\n:\n:\n:\n:\n    PEUT COHABITER AVEC, 0N ESPÈCE, 0N [commensale] ESPÈCE: nb. max. commensaux\n:\n:\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/complex/rewritten/complex_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/_drain.mcd",
    "content": "Entreprise: nom entreprise, adresse, téléphone\nProposer, 0N Entreprise, 11 Stage: date proposition\nStage: num. stage, sujet\nAttribuer, 11 Étudiant, 01 Stage: date signature\nÉtudiant: num étudiant, nom\nSoutenir, 01 Étudiant, 0N Date: note stage\nDate: date\n"
  },
  {
    "path": "test/zoo/drain/ddl/drain_ddl.d2",
    "content": "\"Entreprise\": { shape: sql_table\n  \"nom entreprise\": VARCHAR(42) {constraint: PK}\n  \"adresse\":        VARCHAR(42) \n  \"téléphone\":      VARCHAR(42) \n}\n\n\"Étudiant\": { shape: sql_table\n  \"num étudiant\":   VARCHAR(42) {constraint: PK}\n  \"nom\":            VARCHAR(42) \n  \"num. stage\":     VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"date signature\": VARCHAR(42) \n  \"date\":           VARCHAR(42) {constraint: \"NULL\"}\n  \"note stage\":     VARCHAR(42) \n}\n\n\"Stage\": { shape: sql_table\n  \"num. stage\":       VARCHAR(42) {constraint: PK}\n  \"sujet\":            VARCHAR(42) \n  \"nom entreprise\":   VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"date proposition\": VARCHAR(42) \n}\n\n\"Étudiant\".\"num. stage\" -> \"Stage\".\"num. stage\"\n\"Stage\".\"nom entreprise\" -> \"Entreprise\".\"nom entreprise\"\n"
  },
  {
    "path": "test/zoo/drain/ddl/drain_ddl.dbml",
    "content": "Table \"Entreprise\" {\n  \"nom entreprise\" VARCHAR(42) [pk, NOT NULL]\n  \"adresse\"        VARCHAR(42)\n  \"téléphone\"      VARCHAR(42)\n}\n\nTable \"Étudiant\" {\n  \"num étudiant\"   VARCHAR(42) [pk, NOT NULL]\n  \"nom\"            VARCHAR(42)\n  \"num. stage\"     VARCHAR(42) [NOT NULL]\n  \"date signature\" VARCHAR(42)\n  \"date\"           VARCHAR(42) [\"NULL\"]\n  \"note stage\"     VARCHAR(42)\n  Indexes {\n    \"num. stage\" [unique]\n  }\n}\n\nTable \"Stage\" {\n  \"num. stage\"       VARCHAR(42) [pk, NOT NULL]\n  \"sujet\"            VARCHAR(42)\n  \"nom entreprise\"   VARCHAR(42) [NOT NULL]\n  \"date proposition\" VARCHAR(42)\n}\n\nRef:\"Étudiant\".\"num. stage\" > \"Stage\".\"num. stage\"\nRef:\"Stage\".\"nom entreprise\" > \"Entreprise\".\"nom entreprise\"\n"
  },
  {
    "path": "test/zoo/drain/ddl/drain_ddl.sql",
    "content": "CREATE TABLE ENTREPRISE (\n  PRIMARY KEY (nom_entreprise),\n  nom_entreprise VARCHAR(255) NOT NULL,\n  adresse        VARCHAR(30),\n  telephone      VARCHAR(20)\n);\n\nCREATE TABLE ETUDIANT (\n  PRIMARY KEY (num_etudiant),\n  num_etudiant   VARCHAR(8) NOT NULL,\n  nom            VARCHAR(255),\n  num_stage      VARCHAR(8) NOT NULL,\n  date_signature BINARY(64),\n  date           DATE NULL,\n  note_stage     TEXT,\n  UNIQUE (num_stage)\n);\n\nCREATE TABLE STAGE (\n  PRIMARY KEY (num_stage),\n  num_stage        VARCHAR(8) NOT NULL,\n  sujet            VARCHAR(42),\n  nom_entreprise   VARCHAR(255) NOT NULL,\n  date_proposition DATE\n);\n\nALTER TABLE ETUDIANT ADD FOREIGN KEY (num_stage) REFERENCES STAGE (num_stage);\n\nALTER TABLE STAGE ADD FOREIGN KEY (nom_entreprise) REFERENCES ENTREPRISE (nom_entreprise);\n"
  },
  {
    "path": "test/zoo/drain/exported/drain_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Entreprise\"]\n  6 [label=\"Stage\"]\n  11 [label=\"Étudiant\"]\n  16 [label=\"Date\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"adresse\"]\n  4 [label=\"téléphone\"]\n  9 [label=\"sujet\"]\n  14 [label=\"nom\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>nom<br/>entreprise</u>>]\n  8 [label=<<u>num.<br/>stage</u>>]\n  13 [label=<<u>num<br/>étudiant</u>>]\n  18 [label=<<u>date</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  7 [label=\"date\\nproposition\"]\n  12 [label=\"date\\nsignature\"]\n  17 [label=\"note\\nstage\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"Proposer\"]\n  10 [label=\"Attribuer\"]\n  15 [label=\"Soutenir\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  6 -- 8\n  6 -- 9\n  11 -- 13\n  11 -- 14\n  16 -- 18\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  5 -- 7\n  10 -- 12\n  15 -- 17\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  11 -- 10\n  1 -- 5 [color=\"#000000\"]\n  6 -- 10 [color=\"#000000\"]\n  16 -- 15 [color=\"#000000\"]\n  edge [headlabel=N]\n  6 -- 5\n  11 -- 15 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/drain/exported/drain_erd_chen.txt",
    "content": "[Date] --1-- <Soutenir>\n[Entreprise] --1-- <Proposer>\n[Stage] --1-- <Attribuer>\n[Stage] ==N== <Proposer>\n[Étudiant] --N-- <Soutenir>\n[Étudiant] ==1== <Attribuer>\n"
  },
  {
    "path": "test/zoo/drain/exported/drain_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Entreprise</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">nom entreprise</td></tr>\n        <tr><td> </td><td align=\"left\">adresse</td></tr>\n        <tr><td> </td><td align=\"left\">téléphone</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Stage</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num. stage</td></tr>\n        <tr><td> </td><td align=\"left\">sujet</td></tr>\n        <tr><td> </td><td align=\"left\">date proposition</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Étudiant</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num étudiant</td></tr>\n        <tr><td> </td><td align=\"left\">nom</td></tr>\n        <tr><td> </td><td align=\"left\">date signature</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Date</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"Proposer\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"teeodot\" label=\"Attribuer\"]\n  3 -> 4 [arrowhead=\"teeodot\" arrowtail=\"crowodot\" label=\"Soutenir\"]\n}"
  },
  {
    "path": "test/zoo/drain/exported/drain_erd_crow.mmd",
    "content": "erDiagram\n  Entreprise {\n    TYPE nom_entreprise PK\n    TYPE adresse\n    TYPE telephone\n  }\n  Stage {\n    TYPE num_stage PK\n    TYPE sujet\n    TYPE date_proposition\n  }\n  Etudiant {\n    TYPE num_etudiant PK\n    TYPE nom\n    TYPE date_signature\n  }\n  Date {\n    TYPE date PK\n  }\n  Entreprise ||--o{ Stage: Proposer\n  Etudiant |o--|| Stage: Attribuer\n  Etudiant }o--o| Date: Soutenir"
  },
  {
    "path": "test/zoo/drain/exported/drain_uml.puml",
    "content": "@startuml \"drain\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Entreprise\") {\n    {field} + pk(nom entreprise)\n    {field} + adresse\n    {field} + téléphone\n}\n\n\"Entreprise\" \"1\" --- \"*\" \"Stage\": \"Proposer\"\n\nTable(\"Stage\") {\n    {field} + pk(num. stage)\n    {field} + sujet\n    {field} + date proposition\n}\n\n\"Étudiant\" \"1..*\" --- \"1\" \"Stage\": \"Attribuer\"\n\nTable(\"Étudiant\") {\n    {field} + pk(num étudiant)\n    {field} + nom\n    {field} + date signature\n}\n\n\"Étudiant\" \"*\" --- \"1..*\" \"Date\": \"Soutenir\"\n(\"Étudiant\", \"Date\") .. \"Soutenir\"\nTable(\"Soutenir\") {\n    {field} + note stage\n}\n\nTable(\"Date\") {\n    {field} + pk(date)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nEntreprise\tnom entreprise\t!\t\tprimary_key\tTrue\t\t\t\t\t\nEntreprise\tadresse\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nEntreprise\ttéléphone\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nÉtudiant\tnum étudiant\t!\t\tprimary_key\tTrue\t\t\t\t\t\nÉtudiant\tnom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nÉtudiant\tnum. stage\t!\t1\tforeign_key\tFalse\tStage\tStage\tAttribuer\t\t\nÉtudiant\tdate signature\t\t\touter_attribute\tFalse\t\t\tAttribuer\t\t\nÉtudiant\tdate\t?\t\tex_foreign_key\tFalse\tDate\tDate\tSoutenir\t\t\nÉtudiant\tnote stage\t\t\touter_attribute\tFalse\t\t\tSoutenir\t\t\nStage\tnum. stage\t!\t\tprimary_key\tTrue\t\t\t\t\t\nStage\tsujet\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nStage\tnom entreprise\t!\t\tforeign_key\tFalse\tEntreprise\tEntreprise\tProposer\t\t\nStage\tdate proposition\t\t\touter_attribute\tFalse\t\t\tProposer\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Stage\" -> \"Étudiant\"\n  \"Entreprise\" -> \"Stage\"\n}\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"drain_mld.svg\"/></center><figcaption>MCD <i>drain</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Entreprise</span> (\n    <span class='primary'>nom entreprise</span>,\n    <span class='normal'>adresse</span>,\n    <span class='normal'>téléphone</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>nom entreprise</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Entreprise</i>.</li>\n    <li>Les champs <i>adresse</i> et <i>téléphone</i> étaient déjà de simples attributs de l'entité <i>Entreprise</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Étudiant</span> (\n    <span class='primary'>num étudiant</span>,\n    <span class='normal'>nom</span>,\n    <span class='foreign'>#num. stage</span> <sup>u1</sup>,\n    <span class='normal'>date signature</span>,\n    <span class='normal'>date?</span>,\n    <span class='normal'>note stage</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num étudiant</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Étudiant</i>.</li>\n    <li>Le champ <i>nom</i> était déjà un simple attribut de l'entité <i>Étudiant</i>.</li>\n    <li>Le champ <i>num. stage</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Attribuer</i> à partir de l'entité <i>Stage</i> en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>date signature</i> a migré à partir de l'association de dépendance fonctionnelle <i>Attribuer</i>.</li>\n    <li>Le champ à saisie facultative <i>date</i> est un simple attribut. Il a migré par l'association de dépendance fonctionnelle <i>Soutenir</i> à partir de l'entité <i>Date</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>note stage</i> a migré à partir de l'association de dépendance fonctionnelle <i>Soutenir</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Stage</span> (\n    <span class='primary'>num. stage</span>,\n    <span class='normal'>sujet</span>,\n    <span class='foreign'>#nom entreprise!</span>,\n    <span class='normal'>date proposition</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. stage</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Stage</i>.</li>\n    <li>Le champ <i>sujet</i> était déjà un simple attribut de l'entité <i>Stage</i>.</li>\n    <li>Le champ à saisie obligatoire <i>nom entreprise</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Proposer</i> à partir de l'entité <i>Entreprise</i> en perdant son caractère identifiant.</li>\n    <li>Le champ <i>date proposition</i> a migré à partir de l'association de dépendance fonctionnelle <i>Proposer</i>.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>Date</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_mld.mcd",
    "content": "%%mocodo\n:\nEntreprise: nom entreprise, adresse, téléphone\n:\nStage: num. stage, sujet, #nom entreprise > Entreprise > nom entreprise, date proposition\n:\nÉtudiant: num étudiant, nom, #num. stage > Stage > num. stage, date signature, date, note stage\n:\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_mld.md",
    "content": "- **Entreprise** (<u>nom entreprise</u>, adresse, téléphone)\n  - Le champ _nom entreprise_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Entreprise_.\n  - Les champs _adresse_ et _téléphone_ étaient déjà de simples attributs de l'entité _Entreprise_.\n\n- **Étudiant** (<u>num étudiant</u>, nom, _#num. stage_ <sup>u1</sup>, date signature, date?, note stage)\n  - Le champ _num étudiant_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Étudiant_.\n  - Le champ _nom_ était déjà un simple attribut de l'entité _Étudiant_.\n  - Le champ _num. stage_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Attribuer_ à partir de l'entité _Stage_ en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ _date signature_ a migré à partir de l'association de dépendance fonctionnelle _Attribuer_.\n  - Le champ à saisie facultative _date_ est un simple attribut. Il a migré par l'association de dépendance fonctionnelle _Soutenir_ à partir de l'entité _Date_ en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _note stage_ a migré à partir de l'association de dépendance fonctionnelle _Soutenir_.\n\n- **Stage** (<u>num. stage</u>, sujet, _#nom entreprise!_, date proposition)\n  - Le champ _num. stage_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Stage_.\n  - Le champ _sujet_ était déjà un simple attribut de l'entité _Stage_.\n  - Le champ à saisie obligatoire _nom entreprise_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Proposer_ à partir de l'entité _Entreprise_ en perdant son caractère identifiant.\n  - Le champ _date proposition_ a migré à partir de l'association de dépendance fonctionnelle _Proposer_.\n<br>\n----\n\n\n**NB.** La table _Date_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{drain}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Entreprise} (\\prim{nom entreprise}, \\attr{adresse}, \\attr{téléphone})\n  \\begin{itemize}\n    \\item Le champ \\emph{nom entreprise} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Entreprise}.\n    \\item Les champs \\emph{adresse} et \\emph{téléphone} étaient déjà de simples attributs de l'entité \\emph{Entreprise}.\n  \\end{itemize}\n\n  \\item \\relat{Étudiant} (\\prim{num étudiant}, \\attr{nom}, \\foreign{num. stage}$^{u\\_1}$, \\attr{date signature}, \\attr{date?}, \\attr{note stage})\n  \\begin{itemize}\n    \\item Le champ \\emph{num étudiant} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Étudiant}.\n    \\item Le champ \\emph{nom} était déjà un simple attribut de l'entité \\emph{Étudiant}.\n    \\item Le champ \\emph{num. stage} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Attribuer} à partir de l'entité \\emph{Stage} en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{date signature} a migré à partir de l'association de dépendance fonctionnelle \\emph{Attribuer}.\n    \\item Le champ à saisie facultative \\emph{date} est un simple attribut. Il a migré par l'association de dépendance fonctionnelle \\emph{Soutenir} à partir de l'entité \\emph{Date} en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{note stage} a migré à partir de l'association de dépendance fonctionnelle \\emph{Soutenir}.\n  \\end{itemize}\n\n  \\item \\relat{Stage} (\\prim{num. stage}, \\attr{sujet}, \\foreign{nom entreprise!}, \\attr{date proposition})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. stage} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Stage}.\n    \\item Le champ \\emph{sujet} était déjà un simple attribut de l'entité \\emph{Stage}.\n    \\item Le champ à saisie obligatoire \\emph{nom entreprise} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Proposer} à partir de l'entité \\emph{Entreprise} en perdant son caractère identifiant.\n    \\item Le champ \\emph{date proposition} a migré à partir de l'association de dépendance fonctionnelle \\emph{Proposer}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/drain/mld/drain_mld.txt",
    "content": "- Entreprise (_nom entreprise_, adresse, téléphone)\n  - Le champ « nom entreprise » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Entreprise ».\n  - Les champs « adresse » et « téléphone » étaient déjà de simples attributs de l'entité « Entreprise ».\n\n- Étudiant (_num étudiant_, nom, #num. stage¹, date signature, date?, note stage)\n  - Le champ « num étudiant » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Étudiant ».\n  - Le champ « nom » était déjà un simple attribut de l'entité « Étudiant ».\n  - Le champ « num. stage » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Attribuer » à partir de l'entité « Stage » en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ « date signature » a migré à partir de l'association de dépendance fonctionnelle « Attribuer ».\n  - Le champ à saisie facultative « date » est un simple attribut. Il a migré par l'association de dépendance fonctionnelle « Soutenir » à partir de l'entité « Date » en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « note stage » a migré à partir de l'association de dépendance fonctionnelle « Soutenir ».\n\n- Stage (_num. stage_, sujet, #nom entreprise!, date proposition)\n  - Le champ « num. stage » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Stage ».\n  - Le champ « sujet » était déjà un simple attribut de l'entité « Stage ».\n  - Le champ à saisie obligatoire « nom entreprise » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Proposer » à partir de l'entité « Entreprise » en perdant son caractère identifiant.\n  - Le champ « date proposition » a migré à partir de l'association de dépendance fonctionnelle « Proposer ».\n<br>\n--------------------------------------------------------------------------------\n\nNB. La table « Date » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_create_df_arrows=across.mcd",
    "content": "Entreprise: nom entreprise, adresse, téléphone\nProposer, 0N> Entreprise, 11 Stage: date proposition\nStage: num. stage, sujet\nAttribuer, 11 Étudiant, 01> Stage: date signature\nÉtudiant: num étudiant, nom\nSoutenir, 01 Étudiant, 0N Date: note stage\nDate: date\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_drain.mcd",
    "content": "Entreprise: nom entreprise, adresse, téléphone\nProposer, 0N Entreprise, 11 Stage\nStage: num. stage, sujet, date proposition\nAttribuer, 11 Étudiant, 01 Stage\nÉtudiant: num étudiant, nom, date signature\nSoutenir, 01 Étudiant, 0N Date: note stage\nDate: date\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2, at 1 3\nASSOC 5_, 0N ENTITÉ 1_, 11 ENTITÉ 2_: at 5 1\nENTITÉ 2_: at 2 1, at 2 2\nASSOC 6_, 11 ENTITÉ 3_, 01 ENTITÉ 2_: at 6 1\nENTITÉ 3_: at 3 1, at 3 2\nASSOC 7_, 01 ENTITÉ 3_, 0N ENTITÉ 4_: at 7 1\nENTITÉ 4_: at 4 1\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/drain/rewritten/drain_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/_empty_attrs_0.mcd",
    "content": "CLIENT: Réf. client, , , \n"
  },
  {
    "path": "test/zoo/empty_attrs/ddl/empty_attrs_0_ddl.d2",
    "content": "\n"
  },
  {
    "path": "test/zoo/empty_attrs/ddl/empty_attrs_0_ddl.dbml",
    "content": "\n"
  },
  {
    "path": "test/zoo/empty_attrs/ddl/empty_attrs_0_ddl.sql",
    "content": ""
  },
  {
    "path": "test/zoo/empty_attrs/exported/empty_attrs_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Associative entities\n  1 [label=\"CLIENT\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>Réf.<br/>client</u>>]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n}"
  },
  {
    "path": "test/zoo/empty_attrs/exported/empty_attrs_0_erd_chen.txt",
    "content": "\n"
  },
  {
    "path": "test/zoo/empty_attrs/exported/empty_attrs_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CLIENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Réf. client</td></tr>\n        <tr><td> </td><td align=\"left\"></td></tr>\n        <tr><td> </td><td align=\"left\"></td></tr>\n        <tr><td> </td><td align=\"left\"></td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n}"
  },
  {
    "path": "test/zoo/empty_attrs/exported/empty_attrs_0_erd_crow.mmd",
    "content": "erDiagram\n  CLIENT {\n    TYPE Ref_client PK\n    TYPE \n    TYPE \n    TYPE \n  }"
  },
  {
    "path": "test/zoo/empty_attrs/exported/empty_attrs_0_uml.puml",
    "content": "@startuml \"empty_attrs\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"CLIENT\") {\n    {field} + pk(Réf. client)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"empty_attrs_0_rw_drown.svg\"/></center><figcaption>MCD <i>empty_attrs</i></figcaption></figure>\n<div class=\"mld\">\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>CLIENT</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_mld.mcd",
    "content": "%%mocodo\n:\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_mld.md",
    "content": "<br>\n----\n\n\n**NB.** La table _CLIENT_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{empty\\_attrs}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/empty_attrs/mld/empty_attrs_0_mld.txt",
    "content": "<br>\n--------------------------------------------------------------------------------\n\nNB. La table « CLIENT » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, , ,\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/empty_attrs/rewritten/empty_attrs_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/_gerund_0.mcd",
    "content": "Produit: produit\nDF, _11 Ligne de commande, 0N Produit\nLigne de commande: _quantité\nDF, _11 Ligne de commande, 1N Commande\nCommande: commande\n"
  },
  {
    "path": "test/zoo/gerund/_gerund_1.mcd",
    "content": "Produit: produit, libellé\nDF, _11 Ligne de commande, 0N Produit\nLigne de commande: _quantité\nDF, _11 Ligne de commande, 1N Commande\nCommande: commande, date\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_0_ddl.d2",
    "content": "\"Ligne de commande\": { shape: sql_table\n  \"commande\": VARCHAR(42) {constraint: PK}\n  \"produit\":  VARCHAR(42) {constraint: PK}\n  \"quantité\": VARCHAR(42) \n}\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_0_ddl.dbml",
    "content": "Table \"Ligne de commande\" {\n  \"commande\" VARCHAR(42) [NOT NULL]\n  \"produit\"  VARCHAR(42) [NOT NULL]\n  \"quantité\" VARCHAR(42)\n  Indexes {\n    (\"commande\", \"produit\") [pk]\n  }\n}\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_0_ddl.sql",
    "content": "CREATE TABLE LIGNE_DE_COMMANDE (\n  PRIMARY KEY (commande, produit),\n  commande VARCHAR(42) NOT NULL,\n  produit  VARCHAR(42) NOT NULL,\n  quantite INTEGER\n);\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_1_ddl.d2",
    "content": "\"Commande\": { shape: sql_table\n  \"commande\": VARCHAR(42) {constraint: PK}\n  \"date\":     VARCHAR(42) \n}\n\n\"Ligne de commande\": { shape: sql_table\n  \"commande\": VARCHAR(42) {constraint: [PK; FK]}\n  \"produit\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"quantité\": VARCHAR(42) \n}\n\n\"Produit\": { shape: sql_table\n  \"produit\": VARCHAR(42) {constraint: PK}\n  \"libellé\": VARCHAR(42) \n}\n\n\"Ligne de commande\".\"commande\" -> \"Commande\".\"commande\"\n\"Ligne de commande\".\"produit\" -> \"Produit\".\"produit\"\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_1_ddl.dbml",
    "content": "Table \"Commande\" {\n  \"commande\" VARCHAR(42) [pk, NOT NULL]\n  \"date\"     VARCHAR(42)\n}\n\nTable \"Ligne de commande\" {\n  \"commande\" VARCHAR(42) [NOT NULL]\n  \"produit\"  VARCHAR(42) [NOT NULL]\n  \"quantité\" VARCHAR(42)\n  Indexes {\n    (\"commande\", \"produit\") [pk]\n  }\n}\n\nTable \"Produit\" {\n  \"produit\" VARCHAR(42) [pk, NOT NULL]\n  \"libellé\" VARCHAR(42)\n}\n\nRef:\"Ligne de commande\".\"commande\" > \"Commande\".\"commande\"\nRef:\"Ligne de commande\".\"produit\" > \"Produit\".\"produit\"\n"
  },
  {
    "path": "test/zoo/gerund/ddl/gerund_1_ddl.sql",
    "content": "CREATE TABLE COMMANDE (\n  PRIMARY KEY (commande),\n  commande VARCHAR(42) NOT NULL,\n  date     DATE\n);\n\nCREATE TABLE LIGNE_DE_COMMANDE (\n  PRIMARY KEY (commande, produit),\n  commande VARCHAR(42) NOT NULL,\n  produit  VARCHAR(42) NOT NULL,\n  quantite INTEGER\n);\n\nCREATE TABLE PRODUIT (\n  PRIMARY KEY (produit),\n  produit VARCHAR(42) NOT NULL,\n  libelle VARCHAR(50)\n);\n\nALTER TABLE LIGNE_DE_COMMANDE ADD FOREIGN KEY (produit) REFERENCES PRODUIT (produit);\nALTER TABLE LIGNE_DE_COMMANDE ADD FOREIGN KEY (commande) REFERENCES COMMANDE (commande);\n"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Produit\"]\n  7 [label=\"Commande\"]\n\n  // Associative entities\n  4 [label=\"Ligne de\\ncommande\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>produit</u>>]\n  5 [label=<<u>quantité</u>> style=\"dashed,filled\"]\n  8 [label=<<u>commande</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"DF\",peripheries=2]\n  6 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 5\n  7 -- 8\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  7 -- 6\n  1 -- 3 [color=\"#000000\"]\n  edge [headlabel=N]\n  4 -- 3\n  4 -- 6\n}"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_0_erd_chen.txt",
    "content": "[<Ligne de commande>] ==N== <<DF>>\n[<Ligne de commande>] ==N== <<DF>>\n[Commande] ==1== <<DF>>\n[Produit] --1-- <<DF>>\n"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Produit</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">produit</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Ligne de commande</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">quantité</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Commande</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">commande</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  2 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_0_erd_crow.mmd",
    "content": "erDiagram\n  Produit {\n    TYPE produit PK\n  }\n  Ligne_de_commande {\n    TYPE quantite PK\n  }\n  Commande {\n    TYPE commande PK\n  }\n  Ligne_de_commande }o..|| Produit: DF\n  Ligne_de_commande }|..|| Commande: DF"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_0_uml.puml",
    "content": "@startuml \"gerund\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Produit\") {\n    {field} + pk(produit)\n}\n\n\"Ligne de commande\" \"*\" --* \"1\" \"Produit\"\n\nTable(\"Ligne de commande\") {\n    {field} + pk(quantité)\n}\n\n\"Ligne de commande\" \"1..*\" --* \"1\" \"Commande\"\n\nTable(\"Commande\") {\n    {field} + pk(commande)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Produit\"]\n  8 [label=\"Commande\"]\n\n  // Associative entities\n  5 [label=\"Ligne de\\ncommande\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"libellé\"]\n  10 [label=\"date\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>produit</u>>]\n  6 [label=<<u>quantité</u>> style=\"dashed,filled\"]\n  9 [label=<<u>commande</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"DF\",peripheries=2]\n  7 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 6\n  8 -- 9\n  8 -- 10\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  8 -- 7\n  1 -- 4 [color=\"#000000\"]\n  edge [headlabel=N]\n  5 -- 4\n  5 -- 7\n}"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_1_erd_chen.txt",
    "content": "[<Ligne de commande>] ==N== <<DF>>\n[<Ligne de commande>] ==N== <<DF>>\n[Commande] ==1== <<DF>>\n[Produit] --1-- <<DF>>\n"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_1_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Produit</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">produit</td></tr>\n        <tr><td> </td><td align=\"left\">libellé</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Ligne de commande</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">quantité</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Commande</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">commande</td></tr>\n        <tr><td> </td><td align=\"left\">date</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  2 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_1_erd_crow.mmd",
    "content": "erDiagram\n  Produit {\n    TYPE produit PK\n    TYPE libelle\n  }\n  Ligne_de_commande {\n    TYPE quantite PK\n  }\n  Commande {\n    TYPE commande PK\n    TYPE date\n  }\n  Ligne_de_commande }o..|| Produit: DF\n  Ligne_de_commande }|..|| Commande: DF"
  },
  {
    "path": "test/zoo/gerund/exported/gerund_1_uml.puml",
    "content": "@startuml \"gerund\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Produit\") {\n    {field} + pk(produit)\n    {field} + libellé\n}\n\n\"Ligne de commande\" \"*\" --* \"1\" \"Produit\"\n\nTable(\"Ligne de commande\") {\n    {field} + pk(quantité)\n}\n\n\"Ligne de commande\" \"1..*\" --* \"1\" \"Commande\"\n\nTable(\"Commande\") {\n    {field} + pk(commande)\n    {field} + date\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nLigne de commande\tcommande\t!\t\tstrengthening_primary_ex_foreign_key\tTrue\tCommande\tCommande\tDF\t\t\nLigne de commande\tproduit\t!\t\tstrengthening_primary_ex_foreign_key\tTrue\tProduit\tProduit\tDF\t\t\nLigne de commande\tquantité\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"gerund_0_mld.svg\"/></center><figcaption>MCD <i>gerund</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Ligne de commande</span> (\n    <span class='primary'>commande</span>,\n    <span class='primary'>produit</span>,\n    <span class='normal'>quantité</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>commande</i> fait partie de la clé primaire de la table. Il a migré à partir de l'entité <i>Commande</i> pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>produit</i> fait partie de la clé primaire de la table. Il a migré à partir de l'entité <i>Produit</i> pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>quantité</i> était déjà un simple attribut de l'entité <i>Ligne de commande</i>.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>Commande</i> et <i>Produit</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_mld.mcd",
    "content": "%%mocodo\n:\nLigne de commande: commande, _produit, quantité\n:\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_mld.md",
    "content": "- **Ligne de commande** (<u>commande</u>, <u>produit</u>, quantité)\n  - Le champ _commande_ fait partie de la clé primaire de la table. Il a migré à partir de l'entité _Commande_ pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _produit_ fait partie de la clé primaire de la table. Il a migré à partir de l'entité _Produit_ pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _quantité_ était déjà un simple attribut de l'entité _Ligne de commande_.\n<br>\n----\n\n\n**NB.** Les tables _Commande_ et _Produit_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{gerund}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Ligne de commande} (\\prim{commande}, \\prim{produit}, \\attr{quantité})\n  \\begin{itemize}\n    \\item Le champ \\emph{commande} fait partie de la clé primaire de la table. Il a migré à partir de l'entité \\emph{Commande} pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{produit} fait partie de la clé primaire de la table. Il a migré à partir de l'entité \\emph{Produit} pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{quantité} était déjà un simple attribut de l'entité \\emph{Ligne de commande}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_0_mld.txt",
    "content": "- Ligne de commande (_commande_, _produit_, quantité)\n  - Le champ « commande » fait partie de la clé primaire de la table. Il a migré à partir de l'entité « Commande » pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « produit » fait partie de la clé primaire de la table. Il a migré à partir de l'entité « Produit » pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « quantité » était déjà un simple attribut de l'entité « Ligne de commande ».\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « Commande » et « Produit » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCommande\tcommande\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCommande\tdate\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLigne de commande\tcommande\t!\t\tstrengthening_primary_foreign_key\tTrue\tCommande\tCommande\tDF\t\t\nLigne de commande\tproduit\t!\t\tstrengthening_primary_foreign_key\tTrue\tProduit\tProduit\tDF\t\t\nLigne de commande\tquantité\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nProduit\tproduit\t!\t\tprimary_key\tTrue\t\t\t\t\t\nProduit\tlibellé\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Produit\" -> \"Ligne de commande\"\n  \"Commande\" -> \"Ligne de commande\"\n}\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"gerund_1_mld.svg\"/></center><figcaption>MCD <i>gerund</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Commande</span> (\n    <span class='primary'>commande</span>,\n    <span class='normal'>date</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>commande</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Commande</i>.</li>\n    <li>Le champ <i>date</i> était déjà un simple attribut de l'entité <i>Commande</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Ligne de commande</span> (\n    <span class='foreign primary'>#commande</span>,\n    <span class='foreign primary'>#produit</span>,\n    <span class='normal'>quantité</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>commande</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Commande</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>produit</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Produit</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>quantité</i> était déjà un simple attribut de l'entité <i>Ligne de commande</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Produit</span> (\n    <span class='primary'>produit</span>,\n    <span class='normal'>libellé</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>produit</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Produit</i>.</li>\n    <li>Le champ <i>libellé</i> était déjà un simple attribut de l'entité <i>Produit</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_mld.mcd",
    "content": "%%mocodo\n:\nProduit: produit, libellé\n:\nLigne de commande: #commande > Commande > commande, _#produit > Produit > produit, quantité\n:\nCommande: commande, date\n:\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_mld.md",
    "content": "- **Commande** (<u>commande</u>, date)\n  - Le champ _commande_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Commande_.\n  - Le champ _date_ était déjà un simple attribut de l'entité _Commande_.\n\n- **Ligne de commande** (<u>_#commande_</u>, <u>_#produit_</u>, quantité)\n  - Le champ _commande_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Commande_ pour renforcer l'identifiant.\n  - Le champ _produit_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Produit_ pour renforcer l'identifiant.\n  - Le champ _quantité_ était déjà un simple attribut de l'entité _Ligne de commande_.\n\n- **Produit** (<u>produit</u>, libellé)\n  - Le champ _produit_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Produit_.\n  - Le champ _libellé_ était déjà un simple attribut de l'entité _Produit_.\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{gerund}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Commande} (\\prim{commande}, \\attr{date})\n  \\begin{itemize}\n    \\item Le champ \\emph{commande} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Commande}.\n    \\item Le champ \\emph{date} était déjà un simple attribut de l'entité \\emph{Commande}.\n  \\end{itemize}\n\n  \\item \\relat{Ligne de commande} (\\foreign{\\prim{commande}}, \\foreign{\\prim{produit}}, \\attr{quantité})\n  \\begin{itemize}\n    \\item Le champ \\emph{commande} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Commande} pour renforcer l'identifiant.\n    \\item Le champ \\emph{produit} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Produit} pour renforcer l'identifiant.\n    \\item Le champ \\emph{quantité} était déjà un simple attribut de l'entité \\emph{Ligne de commande}.\n  \\end{itemize}\n\n  \\item \\relat{Produit} (\\prim{produit}, \\attr{libellé})\n  \\begin{itemize}\n    \\item Le champ \\emph{produit} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Produit}.\n    \\item Le champ \\emph{libellé} était déjà un simple attribut de l'entité \\emph{Produit}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/gerund/mld/gerund_1_mld.txt",
    "content": "- Commande (_commande_, date)\n  - Le champ « commande » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Commande ».\n  - Le champ « date » était déjà un simple attribut de l'entité « Commande ».\n\n- Ligne de commande (_#commande_, _#produit_, quantité)\n  - Le champ « commande » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Commande » pour renforcer l'identifiant.\n  - Le champ « produit » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Produit » pour renforcer l'identifiant.\n  - Le champ « quantité » était déjà un simple attribut de l'entité « Ligne de commande ».\n\n- Produit (_produit_, libellé)\n  - Le champ « produit » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Produit ».\n  - Le champ « libellé » était déjà un simple attribut de l'entité « Produit ».\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_create_df_arrows=across.mcd",
    "content": "Produit: produit\nDF, _11 Ligne de commande, 0N> Produit\nLigne de commande: _quantité\nDF, _11 Ligne de commande, 1N> Commande\nCommande: commande\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nDF, _11 ENTITÉ 2_, 0N ENTITÉ 1_\nENTITÉ 2_: _at 2 1\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 3_\nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_create_df_arrows=across.mcd",
    "content": "Produit: produit, libellé\nDF, _11 Ligne de commande, 0N> Produit\nLigne de commande: _quantité\nDF, _11 Ligne de commande, 1N> Commande\nCommande: commande, date\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nDF, _11 ENTITÉ 2_, 0N ENTITÉ 1_\nENTITÉ 2_: _at 2 1\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 3_\nENTITÉ 3_: at 3 1, at 3 2\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/gerund/rewritten/gerund_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_0.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_1.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_2.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_3.mcd",
    "content": ":\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_4.mcd",
    "content": ":\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/_inheritance_5.mcd",
    "content": ":\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_0_ddl.d2",
    "content": "\"ALIQUET\": { shape: sql_table\n  \"magna\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"tellus\": VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"CONSEQUAT\": { shape: sql_table\n  \"fermentum\": VARCHAR(42) {constraint: PK}\n  \"dederit\":   VARCHAR(42) \n}\n\n\"CURABITUR\": { shape: sql_table\n  \"gravida\": VARCHAR(42) {constraint: PK}\n  \"amor\":    VARCHAR(42) \n}\n\n\"DIGNISSIM\": { shape: sql_table\n  \"tellus\": VARCHAR(42) {constraint: PK}\n  \"terra\":  VARCHAR(42) \n}\n\n\"LIBERO\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: PK}\n  \"lacrima\": VARCHAR(42) \n}\n\n\"QUAM\": { shape: sql_table\n  \"cras\":  VARCHAR(42) {constraint: PK}\n  \"sed\":   VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"SUSCIPIT\": { shape: sql_table\n  \"orci\":  VARCHAR(42) {constraint: PK}\n  \"lorem\": VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"TRISTIS\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"fermentum\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"type\":       UNSIGNED INT {constraint: NOT NULL}\n  \"convallis\":  VARCHAR(42) {constraint: \"NULL\"}\n  \"ipsum\":      VARCHAR(42) {constraint: \"NULL\"}\n  \"pulvinar\":   VARCHAR(42) {constraint: \"NULL\"}\n  \"audis\":      VARCHAR(42) {constraint: \"NULL\"}\n  \"gravida\":    VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"tempor\":     VARCHAR(42) {constraint: \"NULL\"}\n  \"fugit\":      VARCHAR(42) {constraint: \"NULL\"}\n}\n\n\"ULTRICES\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"ALIQUET\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"ALIQUET\".\"tellus\" -> \"DIGNISSIM\".\"tellus\"\n\"QUAM\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"SUSCIPIT\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"TRISTIS\".\"fermentum\" -> \"CONSEQUAT\".\"fermentum\"\n\"TRISTIS\".\"gravida\" -> \"CURABITUR\".\"gravida\"\n\"ULTRICES\".\"posuere\" -> \"LIBERO\".\"posuere\"\n\"ULTRICES\".\"magna\" -> \"TRISTIS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_0_ddl.dbml",
    "content": "Table \"ALIQUET\" {\n  \"magna\"  VARCHAR(42) [NOT NULL]\n  \"tellus\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"magna\", \"tellus\") [pk]\n  }\n}\n\nTable \"CONSEQUAT\" {\n  \"fermentum\" VARCHAR(42) [pk, NOT NULL]\n  \"dederit\"   VARCHAR(42)\n}\n\nTable \"CURABITUR\" {\n  \"gravida\" VARCHAR(42) [pk, NOT NULL]\n  \"amor\"    VARCHAR(42)\n}\n\nTable \"DIGNISSIM\" {\n  \"tellus\" VARCHAR(42) [pk, NOT NULL]\n  \"terra\"  VARCHAR(42)\n}\n\nTable \"LIBERO\" {\n  \"posuere\" VARCHAR(42) [pk, NOT NULL]\n  \"lacrima\" VARCHAR(42)\n}\n\nTable \"QUAM\" {\n  \"cras\"  VARCHAR(42) [pk, NOT NULL]\n  \"sed\"   VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"SUSCIPIT\" {\n  \"orci\"  VARCHAR(42) [pk, NOT NULL]\n  \"lorem\" VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"TRISTIS\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"fermentum\"  VARCHAR(42) [NOT NULL]\n  \"type\"       UNSIGNED_INT [NOT NULL]\n  \"convallis\"  VARCHAR(42) [\"NULL\"]\n  \"ipsum\"      VARCHAR(42) [\"NULL\"]\n  \"pulvinar\"   VARCHAR(42) [\"NULL\"]\n  \"audis\"      VARCHAR(42) [\"NULL\"]\n  \"gravida\"    VARCHAR(42) [\"NULL\"]\n  \"tempor\"     VARCHAR(42) [\"NULL\"]\n  \"fugit\"      VARCHAR(42) [\"NULL\"]\n}\n\nTable \"ULTRICES\" {\n  \"posuere\" VARCHAR(42) [NOT NULL]\n  \"magna\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"posuere\", \"magna\") [pk]\n  }\n}\n\nRef:\"ALIQUET\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"ALIQUET\".\"tellus\" > \"DIGNISSIM\".\"tellus\"\nRef:\"QUAM\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"SUSCIPIT\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"TRISTIS\".\"fermentum\" > \"CONSEQUAT\".\"fermentum\"\nRef:\"TRISTIS\".\"gravida\" > \"CURABITUR\".\"gravida\"\nRef:\"ULTRICES\".\"posuere\" > \"LIBERO\".\"posuere\"\nRef:\"ULTRICES\".\"magna\" > \"TRISTIS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_0_ddl.sql",
    "content": "CREATE TABLE ALIQUET (\n  PRIMARY KEY (magna, tellus),\n  magna  VARCHAR(42) NOT NULL,\n  tellus VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE CONSEQUAT (\n  PRIMARY KEY (fermentum),\n  fermentum VARCHAR(42) NOT NULL,\n  dederit   VARCHAR(42)\n);\n\nCREATE TABLE CURABITUR (\n  PRIMARY KEY (gravida),\n  gravida VARCHAR(42) NOT NULL,\n  amor    VARCHAR(42)\n);\n\nCREATE TABLE DIGNISSIM (\n  PRIMARY KEY (tellus),\n  tellus VARCHAR(42) NOT NULL,\n  terra  VARCHAR(42)\n);\n\nCREATE TABLE LIBERO (\n  PRIMARY KEY (posuere),\n  posuere VARCHAR(42) NOT NULL,\n  lacrima VARCHAR(42)\n);\n\nCREATE TABLE QUAM (\n  PRIMARY KEY (cras),\n  cras  VARCHAR(42) NOT NULL,\n  sed   VARCHAR(42),\n  magna VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE SUSCIPIT (\n  PRIMARY KEY (orci),\n  orci  VARCHAR(42) NOT NULL,\n  lorem VARCHAR(42),\n  magna VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE TRISTIS (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  fermentum  VARCHAR(42) NOT NULL,\n  type       UNSIGNED INT NOT NULL,\n  convallis  VARCHAR(42) NULL,\n  ipsum      VARCHAR(42) NULL,\n  pulvinar   VARCHAR(42) NULL,\n  audis      VARCHAR(42) NULL,\n  gravida    VARCHAR(42) NULL,\n  tempor     VARCHAR(42) NULL,\n  fugit      VARCHAR(42) NULL\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (posuere, magna),\n  posuere VARCHAR(42) NOT NULL,\n  magna   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE ALIQUET ADD FOREIGN KEY (tellus) REFERENCES DIGNISSIM (tellus);\nALTER TABLE ALIQUET ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE QUAM ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE SUSCIPIT ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE TRISTIS ADD FOREIGN KEY (gravida) REFERENCES CURABITUR (gravida);\nALTER TABLE TRISTIS ADD FOREIGN KEY (fermentum) REFERENCES CONSEQUAT (fermentum);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (posuere) REFERENCES LIBERO (posuere);\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_1_ddl.d2",
    "content": "\"ALIQUET\": { shape: sql_table\n  \"magna\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"tellus\": VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"CONSEQUAT\": { shape: sql_table\n  \"fermentum\": VARCHAR(42) {constraint: PK}\n  \"dederit\":   VARCHAR(42) \n}\n\n\"CURABITUR\": { shape: sql_table\n  \"gravida\": VARCHAR(42) {constraint: PK}\n  \"amor\":    VARCHAR(42) \n}\n\n\"DIGNISSIM\": { shape: sql_table\n  \"tellus\": VARCHAR(42) {constraint: PK}\n  \"terra\":  VARCHAR(42) \n}\n\n\"LACUS\": { shape: sql_table\n  \"magna\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"tempor\": VARCHAR(42) \n  \"fugit\":  VARCHAR(42) \n}\n\n\"LIBERO\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: PK}\n  \"lacrima\": VARCHAR(42) \n}\n\n\"NEC\": { shape: sql_table\n  \"magna\":    VARCHAR(42) {constraint: [PK; FK]}\n  \"pulvinar\": VARCHAR(42) \n  \"audis\":    VARCHAR(42) \n  \"gravida\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"QUAM\": { shape: sql_table\n  \"cras\":  VARCHAR(42) {constraint: PK}\n  \"sed\":   VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"SODALES\": { shape: sql_table\n  \"magna\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"convallis\": VARCHAR(42) \n  \"ipsum\":     VARCHAR(42) \n}\n\n\"SUSCIPIT\": { shape: sql_table\n  \"orci\":  VARCHAR(42) {constraint: PK}\n  \"lorem\": VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"TRISTIS\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"fermentum\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"type\":       UNSIGNED INT {constraint: NOT NULL}\n}\n\n\"ULTRICES\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"ALIQUET\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"ALIQUET\".\"tellus\" -> \"DIGNISSIM\".\"tellus\"\n\"LACUS\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"NEC\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"NEC\".\"gravida\" -> \"CURABITUR\".\"gravida\"\n\"QUAM\".\"magna\" -> \"SODALES\".\"magna\"\n\"SODALES\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"SUSCIPIT\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"TRISTIS\".\"fermentum\" -> \"CONSEQUAT\".\"fermentum\"\n\"ULTRICES\".\"posuere\" -> \"LIBERO\".\"posuere\"\n\"ULTRICES\".\"magna\" -> \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_1_ddl.dbml",
    "content": "Table \"ALIQUET\" {\n  \"magna\"  VARCHAR(42) [NOT NULL]\n  \"tellus\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"magna\", \"tellus\") [pk]\n  }\n}\n\nTable \"CONSEQUAT\" {\n  \"fermentum\" VARCHAR(42) [pk, NOT NULL]\n  \"dederit\"   VARCHAR(42)\n}\n\nTable \"CURABITUR\" {\n  \"gravida\" VARCHAR(42) [pk, NOT NULL]\n  \"amor\"    VARCHAR(42)\n}\n\nTable \"DIGNISSIM\" {\n  \"tellus\" VARCHAR(42) [pk, NOT NULL]\n  \"terra\"  VARCHAR(42)\n}\n\nTable \"LACUS\" {\n  \"magna\"  VARCHAR(42) [pk, NOT NULL]\n  \"tempor\" VARCHAR(42)\n  \"fugit\"  VARCHAR(42)\n}\n\nTable \"LIBERO\" {\n  \"posuere\" VARCHAR(42) [pk, NOT NULL]\n  \"lacrima\" VARCHAR(42)\n}\n\nTable \"NEC\" {\n  \"magna\"    VARCHAR(42) [pk, NOT NULL]\n  \"pulvinar\" VARCHAR(42)\n  \"audis\"    VARCHAR(42)\n  \"gravida\"  VARCHAR(42) [NOT NULL]\n}\n\nTable \"QUAM\" {\n  \"cras\"  VARCHAR(42) [pk, NOT NULL]\n  \"sed\"   VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"SODALES\" {\n  \"magna\"     VARCHAR(42) [pk, NOT NULL]\n  \"convallis\" VARCHAR(42)\n  \"ipsum\"     VARCHAR(42)\n}\n\nTable \"SUSCIPIT\" {\n  \"orci\"  VARCHAR(42) [pk, NOT NULL]\n  \"lorem\" VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"TRISTIS\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"fermentum\"  VARCHAR(42) [NOT NULL]\n  \"type\"       UNSIGNED_INT [NOT NULL]\n}\n\nTable \"ULTRICES\" {\n  \"posuere\" VARCHAR(42) [NOT NULL]\n  \"magna\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"posuere\", \"magna\") [pk]\n  }\n}\n\nRef:\"ALIQUET\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"ALIQUET\".\"tellus\" > \"DIGNISSIM\".\"tellus\"\nRef:\"LACUS\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"NEC\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"NEC\".\"gravida\" > \"CURABITUR\".\"gravida\"\nRef:\"QUAM\".\"magna\" > \"SODALES\".\"magna\"\nRef:\"SODALES\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"SUSCIPIT\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"TRISTIS\".\"fermentum\" > \"CONSEQUAT\".\"fermentum\"\nRef:\"ULTRICES\".\"posuere\" > \"LIBERO\".\"posuere\"\nRef:\"ULTRICES\".\"magna\" > \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_1_ddl.sql",
    "content": "CREATE TABLE ALIQUET (\n  PRIMARY KEY (magna, tellus),\n  magna  VARCHAR(42) NOT NULL,\n  tellus VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE CONSEQUAT (\n  PRIMARY KEY (fermentum),\n  fermentum VARCHAR(42) NOT NULL,\n  dederit   VARCHAR(42)\n);\n\nCREATE TABLE CURABITUR (\n  PRIMARY KEY (gravida),\n  gravida VARCHAR(42) NOT NULL,\n  amor    VARCHAR(42)\n);\n\nCREATE TABLE DIGNISSIM (\n  PRIMARY KEY (tellus),\n  tellus VARCHAR(42) NOT NULL,\n  terra  VARCHAR(42)\n);\n\nCREATE TABLE LACUS (\n  PRIMARY KEY (magna),\n  magna  VARCHAR(42) NOT NULL,\n  tempor VARCHAR(42),\n  fugit  VARCHAR(42)\n);\n\nCREATE TABLE LIBERO (\n  PRIMARY KEY (posuere),\n  posuere VARCHAR(42) NOT NULL,\n  lacrima VARCHAR(42)\n);\n\nCREATE TABLE NEC (\n  PRIMARY KEY (magna),\n  magna    VARCHAR(42) NOT NULL,\n  pulvinar VARCHAR(42),\n  audis    VARCHAR(42),\n  gravida  VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE QUAM (\n  PRIMARY KEY (cras),\n  cras  VARCHAR(42) NOT NULL,\n  sed   VARCHAR(42),\n  magna VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE SODALES (\n  PRIMARY KEY (magna),\n  magna     VARCHAR(42) NOT NULL,\n  convallis VARCHAR(42),\n  ipsum     VARCHAR(42)\n);\n\nCREATE TABLE SUSCIPIT (\n  PRIMARY KEY (orci),\n  orci  VARCHAR(42) NOT NULL,\n  lorem VARCHAR(42),\n  magna VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE TRISTIS (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  fermentum  VARCHAR(42) NOT NULL,\n  type       UNSIGNED INT NOT NULL\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (posuere, magna),\n  posuere VARCHAR(42) NOT NULL,\n  magna   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE ALIQUET ADD FOREIGN KEY (tellus) REFERENCES DIGNISSIM (tellus);\nALTER TABLE ALIQUET ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE LACUS ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE NEC ADD FOREIGN KEY (gravida) REFERENCES CURABITUR (gravida);\nALTER TABLE NEC ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE QUAM ADD FOREIGN KEY (magna) REFERENCES SODALES (magna);\n\nALTER TABLE SODALES ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE SUSCIPIT ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE TRISTIS ADD FOREIGN KEY (fermentum) REFERENCES CONSEQUAT (fermentum);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna) REFERENCES LACUS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (posuere) REFERENCES LIBERO (posuere);\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_2_ddl.d2",
    "content": "\"ALIQUET\": { shape: sql_table\n  \"magna\":  VARCHAR(42) {constraint: PK}\n  \"tellus\": VARCHAR(42) {constraint: [PK; FK]}\n  \"type\":   UNSIGNED INT {constraint: NOT NULL}\n}\n\n\"CONSEQUAT\": { shape: sql_table\n  \"fermentum\": VARCHAR(42) {constraint: PK}\n  \"dederit\":   VARCHAR(42) \n}\n\n\"CURABITUR\": { shape: sql_table\n  \"gravida\": VARCHAR(42) {constraint: PK}\n  \"amor\":    VARCHAR(42) \n}\n\n\"DIGNISSIM\": { shape: sql_table\n  \"tellus\": VARCHAR(42) {constraint: PK}\n  \"terra\":  VARCHAR(42) \n}\n\n\"LACUS\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"fermentum\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"tempor\":     VARCHAR(42) \n  \"fugit\":      VARCHAR(42) \n}\n\n\"LIBERO\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: PK}\n  \"lacrima\": VARCHAR(42) \n}\n\n\"NEC\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"fermentum\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"pulvinar\":   VARCHAR(42) \n  \"audis\":      VARCHAR(42) \n  \"gravida\":    VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"QUAM\": { shape: sql_table\n  \"cras\":  VARCHAR(42) {constraint: PK}\n  \"sed\":   VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"SODALES\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"fermentum\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"convallis\":  VARCHAR(42) \n  \"ipsum\":      VARCHAR(42) \n}\n\n\"SUSCIPIT\": { shape: sql_table\n  \"orci\":  VARCHAR(42) {constraint: PK}\n  \"lorem\": VARCHAR(42) \n  \"magna\": VARCHAR(42) {constraint: NOT NULL}\n  \"type\":  UNSIGNED INT {constraint: NOT NULL}\n}\n\n\"ULTRICES\": { shape: sql_table\n  \"posuere\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"ALIQUET\".\"tellus\" -> \"DIGNISSIM\".\"tellus\"\n\"LACUS\".\"fermentum\" -> \"CONSEQUAT\".\"fermentum\"\n\"NEC\".\"fermentum\" -> \"CONSEQUAT\".\"fermentum\"\n\"NEC\".\"gravida\" -> \"CURABITUR\".\"gravida\"\n\"QUAM\".\"magna\" -> \"SODALES\".\"magna\"\n\"SODALES\".\"fermentum\" -> \"CONSEQUAT\".\"fermentum\"\n\"ULTRICES\".\"posuere\" -> \"LIBERO\".\"posuere\"\n\"ULTRICES\".\"magna\" -> \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_2_ddl.dbml",
    "content": "Table \"ALIQUET\" {\n  \"magna\"  VARCHAR(42) [NOT NULL]\n  \"tellus\" VARCHAR(42) [NOT NULL]\n  \"type\"   UNSIGNED_INT [NOT NULL]\n  Indexes {\n    (\"magna\", \"tellus\") [pk]\n  }\n}\n\nTable \"CONSEQUAT\" {\n  \"fermentum\" VARCHAR(42) [pk, NOT NULL]\n  \"dederit\"   VARCHAR(42)\n}\n\nTable \"CURABITUR\" {\n  \"gravida\" VARCHAR(42) [pk, NOT NULL]\n  \"amor\"    VARCHAR(42)\n}\n\nTable \"DIGNISSIM\" {\n  \"tellus\" VARCHAR(42) [pk, NOT NULL]\n  \"terra\"  VARCHAR(42)\n}\n\nTable \"LACUS\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"fermentum\"  VARCHAR(42) [NOT NULL]\n  \"tempor\"     VARCHAR(42)\n  \"fugit\"      VARCHAR(42)\n}\n\nTable \"LIBERO\" {\n  \"posuere\" VARCHAR(42) [pk, NOT NULL]\n  \"lacrima\" VARCHAR(42)\n}\n\nTable \"NEC\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"fermentum\"  VARCHAR(42) [NOT NULL]\n  \"pulvinar\"   VARCHAR(42)\n  \"audis\"      VARCHAR(42)\n  \"gravida\"    VARCHAR(42) [NOT NULL]\n}\n\nTable \"QUAM\" {\n  \"cras\"  VARCHAR(42) [pk, NOT NULL]\n  \"sed\"   VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"SODALES\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"fermentum\"  VARCHAR(42) [NOT NULL]\n  \"convallis\"  VARCHAR(42)\n  \"ipsum\"      VARCHAR(42)\n}\n\nTable \"SUSCIPIT\" {\n  \"orci\"  VARCHAR(42) [pk, NOT NULL]\n  \"lorem\" VARCHAR(42)\n  \"magna\" VARCHAR(42) [NOT NULL]\n  \"type\"  UNSIGNED_INT [NOT NULL]\n}\n\nTable \"ULTRICES\" {\n  \"posuere\" VARCHAR(42) [NOT NULL]\n  \"magna\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"posuere\", \"magna\") [pk]\n  }\n}\n\nRef:\"ALIQUET\".\"tellus\" > \"DIGNISSIM\".\"tellus\"\nRef:\"LACUS\".\"fermentum\" > \"CONSEQUAT\".\"fermentum\"\nRef:\"NEC\".\"fermentum\" > \"CONSEQUAT\".\"fermentum\"\nRef:\"NEC\".\"gravida\" > \"CURABITUR\".\"gravida\"\nRef:\"QUAM\".\"magna\" > \"SODALES\".\"magna\"\nRef:\"SODALES\".\"fermentum\" > \"CONSEQUAT\".\"fermentum\"\nRef:\"ULTRICES\".\"posuere\" > \"LIBERO\".\"posuere\"\nRef:\"ULTRICES\".\"magna\" > \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_2_ddl.sql",
    "content": "CREATE TABLE ALIQUET (\n  PRIMARY KEY (magna, tellus),\n  magna  VARCHAR(42) NOT NULL,\n  tellus VARCHAR(42) NOT NULL,\n  type   UNSIGNED INT NOT NULL\n);\n\nCREATE TABLE CONSEQUAT (\n  PRIMARY KEY (fermentum),\n  fermentum VARCHAR(42) NOT NULL,\n  dederit   VARCHAR(42)\n);\n\nCREATE TABLE CURABITUR (\n  PRIMARY KEY (gravida),\n  gravida VARCHAR(42) NOT NULL,\n  amor    VARCHAR(42)\n);\n\nCREATE TABLE DIGNISSIM (\n  PRIMARY KEY (tellus),\n  tellus VARCHAR(42) NOT NULL,\n  terra  VARCHAR(42)\n);\n\nCREATE TABLE LACUS (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  fermentum  VARCHAR(42) NOT NULL,\n  tempor     VARCHAR(42),\n  fugit      VARCHAR(42)\n);\n\nCREATE TABLE LIBERO (\n  PRIMARY KEY (posuere),\n  posuere VARCHAR(42) NOT NULL,\n  lacrima VARCHAR(42)\n);\n\nCREATE TABLE NEC (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  fermentum  VARCHAR(42) NOT NULL,\n  pulvinar   VARCHAR(42),\n  audis      VARCHAR(42),\n  gravida    VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE QUAM (\n  PRIMARY KEY (cras),\n  cras  VARCHAR(42) NOT NULL,\n  sed   VARCHAR(42),\n  magna VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE SODALES (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  fermentum  VARCHAR(42) NOT NULL,\n  convallis  VARCHAR(42),\n  ipsum      VARCHAR(42)\n);\n\nCREATE TABLE SUSCIPIT (\n  PRIMARY KEY (orci),\n  orci  VARCHAR(42) NOT NULL,\n  lorem VARCHAR(42),\n  magna VARCHAR(42) NOT NULL,\n  type  UNSIGNED INT NOT NULL\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (posuere, magna),\n  posuere VARCHAR(42) NOT NULL,\n  magna   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE ALIQUET ADD FOREIGN KEY (tellus) REFERENCES DIGNISSIM (tellus);\n\nALTER TABLE LACUS ADD FOREIGN KEY (fermentum) REFERENCES CONSEQUAT (fermentum);\n\nALTER TABLE NEC ADD FOREIGN KEY (gravida) REFERENCES CURABITUR (gravida);\nALTER TABLE NEC ADD FOREIGN KEY (fermentum) REFERENCES CONSEQUAT (fermentum);\n\nALTER TABLE QUAM ADD FOREIGN KEY (magna) REFERENCES SODALES (magna);\n\nALTER TABLE SODALES ADD FOREIGN KEY (fermentum) REFERENCES CONSEQUAT (fermentum);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna) REFERENCES LACUS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (posuere) REFERENCES LIBERO (posuere);\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_3_ddl.d2",
    "content": "\"TRISTIS\": { shape: sql_table\n  \"magna\":            VARCHAR(42) {constraint: PK}\n  \"vestibulum\":       VARCHAR(42) \n  \"type\":             UNSIGNED INT {constraint: NOT NULL}\n  \"convallis\":        VARCHAR(42) {constraint: \"NULL\"}\n  \"ipsum\":            VARCHAR(42) {constraint: \"NULL\"}\n  \"pulvinar\":         VARCHAR(42) {constraint: \"NULL\"}\n  \"audis\":            VARCHAR(42) {constraint: \"NULL\"}\n  \"magna via_mollis\": VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"magna via_vitae\":  VARCHAR(42) {constraint: [FK; \"NULL\"]}\n  \"tempor\":           VARCHAR(42) {constraint: \"NULL\"}\n  \"fugit\":            VARCHAR(42) {constraint: \"NULL\"}\n}\n\n\"ULTRICES\": { shape: sql_table\n  \"magna sodales\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna lacus\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"TRISTIS\".\"magna via_mollis\" -> \"TRISTIS\".\"magna\"\n\"TRISTIS\".\"magna via_vitae\" -> \"TRISTIS\".\"magna\"\n\"ULTRICES\".\"magna sodales\" -> \"TRISTIS\".\"magna\"\n\"ULTRICES\".\"magna lacus\" -> \"TRISTIS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_3_ddl.dbml",
    "content": "Table \"TRISTIS\" {\n  \"magna\"            VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\"       VARCHAR(42)\n  \"type\"             UNSIGNED_INT [NOT NULL]\n  \"convallis\"        VARCHAR(42) [\"NULL\"]\n  \"ipsum\"            VARCHAR(42) [\"NULL\"]\n  \"pulvinar\"         VARCHAR(42) [\"NULL\"]\n  \"audis\"            VARCHAR(42) [\"NULL\"]\n  \"magna via_mollis\" VARCHAR(42) [\"NULL\"]\n  \"magna via_vitae\"  VARCHAR(42) [\"NULL\"]\n  \"tempor\"           VARCHAR(42) [\"NULL\"]\n  \"fugit\"            VARCHAR(42) [\"NULL\"]\n}\n\nTable \"ULTRICES\" {\n  \"magna sodales\" VARCHAR(42) [NOT NULL]\n  \"magna lacus\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"magna sodales\", \"magna lacus\") [pk]\n  }\n}\n\nRef:\"TRISTIS\".(\"magna via_mollis\", \"magna via_vitae\") > \"TRISTIS\".(\"magna\", \"magna\")\nRef:\"ULTRICES\".(\"magna sodales\", \"magna lacus\") > \"TRISTIS\".(\"magna\", \"magna\")\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_3_ddl.sql",
    "content": "CREATE TABLE TRISTIS (\n  PRIMARY KEY (magna),\n  magna            VARCHAR(42) NOT NULL,\n  vestibulum       VARCHAR(42),\n  type             UNSIGNED INT NOT NULL,\n  convallis        VARCHAR(42) NULL,\n  ipsum            VARCHAR(42) NULL,\n  pulvinar         VARCHAR(42) NULL,\n  audis            VARCHAR(42) NULL,\n  magna_via_mollis VARCHAR(42) NULL,\n  magna_via_vitae  VARCHAR(42) NULL,\n  tempor           VARCHAR(42) NULL,\n  fugit            VARCHAR(42) NULL\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (magna_sodales, magna_lacus),\n  magna_sodales VARCHAR(42) NOT NULL,\n  magna_lacus   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE TRISTIS ADD FOREIGN KEY (magna_via_vitae) REFERENCES TRISTIS (magna);\nALTER TABLE TRISTIS ADD FOREIGN KEY (magna_via_mollis) REFERENCES TRISTIS (magna);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_lacus) REFERENCES TRISTIS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_sodales) REFERENCES TRISTIS (magna);\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_4_ddl.d2",
    "content": "\"LACUS\": { shape: sql_table\n  \"magna\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"tempor\": VARCHAR(42) \n  \"fugit\":  VARCHAR(42) \n}\n\n\"NEC\": { shape: sql_table\n  \"magna\":            VARCHAR(42) {constraint: [PK; FK]}\n  \"pulvinar\":         VARCHAR(42) \n  \"audis\":            VARCHAR(42) \n  \"magna via_mollis\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"magna via_vitae\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"SODALES\": { shape: sql_table\n  \"magna\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"convallis\": VARCHAR(42) \n  \"ipsum\":     VARCHAR(42) \n}\n\n\"TRISTIS\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"type\":       UNSIGNED INT {constraint: NOT NULL}\n}\n\n\"ULTRICES\": { shape: sql_table\n  \"magna sodales\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna lacus\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"LACUS\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"NEC\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"NEC\".\"magna via_mollis\" -> \"LACUS\".\"magna\"\n\"NEC\".\"magna via_vitae\" -> \"SODALES\".\"magna\"\n\"SODALES\".\"magna\" -> \"TRISTIS\".\"magna\"\n\"ULTRICES\".\"magna sodales\" -> \"SODALES\".\"magna\"\n\"ULTRICES\".\"magna lacus\" -> \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_4_ddl.dbml",
    "content": "Table \"LACUS\" {\n  \"magna\"  VARCHAR(42) [pk, NOT NULL]\n  \"tempor\" VARCHAR(42)\n  \"fugit\"  VARCHAR(42)\n}\n\nTable \"NEC\" {\n  \"magna\"            VARCHAR(42) [pk, NOT NULL]\n  \"pulvinar\"         VARCHAR(42)\n  \"audis\"            VARCHAR(42)\n  \"magna via_mollis\" VARCHAR(42) [NOT NULL]\n  \"magna via_vitae\"  VARCHAR(42) [NOT NULL]\n}\n\nTable \"SODALES\" {\n  \"magna\"     VARCHAR(42) [pk, NOT NULL]\n  \"convallis\" VARCHAR(42)\n  \"ipsum\"     VARCHAR(42)\n}\n\nTable \"TRISTIS\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"type\"       UNSIGNED_INT [NOT NULL]\n}\n\nTable \"ULTRICES\" {\n  \"magna sodales\" VARCHAR(42) [NOT NULL]\n  \"magna lacus\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"magna sodales\", \"magna lacus\") [pk]\n  }\n}\n\nRef:\"LACUS\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"NEC\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"NEC\".\"magna via_mollis\" > \"LACUS\".\"magna\"\nRef:\"NEC\".\"magna via_vitae\" > \"SODALES\".\"magna\"\nRef:\"SODALES\".\"magna\" > \"TRISTIS\".\"magna\"\nRef:\"ULTRICES\".\"magna sodales\" > \"SODALES\".\"magna\"\nRef:\"ULTRICES\".\"magna lacus\" > \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_4_ddl.sql",
    "content": "CREATE TABLE LACUS (\n  PRIMARY KEY (magna),\n  magna  VARCHAR(42) NOT NULL,\n  tempor VARCHAR(42),\n  fugit  VARCHAR(42)\n);\n\nCREATE TABLE NEC (\n  PRIMARY KEY (magna),\n  magna            VARCHAR(42) NOT NULL,\n  pulvinar         VARCHAR(42),\n  audis            VARCHAR(42),\n  magna_via_mollis VARCHAR(42) NOT NULL,\n  magna_via_vitae  VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE SODALES (\n  PRIMARY KEY (magna),\n  magna     VARCHAR(42) NOT NULL,\n  convallis VARCHAR(42),\n  ipsum     VARCHAR(42)\n);\n\nCREATE TABLE TRISTIS (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  type       UNSIGNED INT NOT NULL\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (magna_sodales, magna_lacus),\n  magna_sodales VARCHAR(42) NOT NULL,\n  magna_lacus   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE LACUS ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE NEC ADD FOREIGN KEY (magna_via_vitae) REFERENCES SODALES (magna);\nALTER TABLE NEC ADD FOREIGN KEY (magna_via_mollis) REFERENCES LACUS (magna);\nALTER TABLE NEC ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE SODALES ADD FOREIGN KEY (magna) REFERENCES TRISTIS (magna);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_lacus) REFERENCES LACUS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_sodales) REFERENCES SODALES (magna);\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_5_ddl.d2",
    "content": "\"LACUS\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"tempor\":     VARCHAR(42) \n  \"fugit\":      VARCHAR(42) \n}\n\n\"NEC\": { shape: sql_table\n  \"magna\":            VARCHAR(42) {constraint: PK}\n  \"vestibulum\":       VARCHAR(42) \n  \"pulvinar\":         VARCHAR(42) \n  \"audis\":            VARCHAR(42) \n  \"magna via_mollis\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"magna via_vitae\":  VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"SODALES\": { shape: sql_table\n  \"magna\":      VARCHAR(42) {constraint: PK}\n  \"vestibulum\": VARCHAR(42) \n  \"convallis\":  VARCHAR(42) \n  \"ipsum\":      VARCHAR(42) \n}\n\n\"ULTRICES\": { shape: sql_table\n  \"magna sodales\": VARCHAR(42) {constraint: [PK; FK]}\n  \"magna lacus\":   VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"NEC\".\"magna via_mollis\" -> \"LACUS\".\"magna\"\n\"NEC\".\"magna via_vitae\" -> \"SODALES\".\"magna\"\n\"ULTRICES\".\"magna sodales\" -> \"SODALES\".\"magna\"\n\"ULTRICES\".\"magna lacus\" -> \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_5_ddl.dbml",
    "content": "Table \"LACUS\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"tempor\"     VARCHAR(42)\n  \"fugit\"      VARCHAR(42)\n}\n\nTable \"NEC\" {\n  \"magna\"            VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\"       VARCHAR(42)\n  \"pulvinar\"         VARCHAR(42)\n  \"audis\"            VARCHAR(42)\n  \"magna via_mollis\" VARCHAR(42) [NOT NULL]\n  \"magna via_vitae\"  VARCHAR(42) [NOT NULL]\n}\n\nTable \"SODALES\" {\n  \"magna\"      VARCHAR(42) [pk, NOT NULL]\n  \"vestibulum\" VARCHAR(42)\n  \"convallis\"  VARCHAR(42)\n  \"ipsum\"      VARCHAR(42)\n}\n\nTable \"ULTRICES\" {\n  \"magna sodales\" VARCHAR(42) [NOT NULL]\n  \"magna lacus\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"magna sodales\", \"magna lacus\") [pk]\n  }\n}\n\nRef:\"NEC\".\"magna via_mollis\" > \"LACUS\".\"magna\"\nRef:\"NEC\".\"magna via_vitae\" > \"SODALES\".\"magna\"\nRef:\"ULTRICES\".\"magna sodales\" > \"SODALES\".\"magna\"\nRef:\"ULTRICES\".\"magna lacus\" > \"LACUS\".\"magna\"\n"
  },
  {
    "path": "test/zoo/inheritance/ddl/inheritance_5_ddl.sql",
    "content": "CREATE TABLE LACUS (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  tempor     VARCHAR(42),\n  fugit      VARCHAR(42)\n);\n\nCREATE TABLE NEC (\n  PRIMARY KEY (magna),\n  magna            VARCHAR(42) NOT NULL,\n  vestibulum       VARCHAR(42),\n  pulvinar         VARCHAR(42),\n  audis            VARCHAR(42),\n  magna_via_mollis VARCHAR(42) NOT NULL,\n  magna_via_vitae  VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE SODALES (\n  PRIMARY KEY (magna),\n  magna      VARCHAR(42) NOT NULL,\n  vestibulum VARCHAR(42),\n  convallis  VARCHAR(42),\n  ipsum      VARCHAR(42)\n);\n\nCREATE TABLE ULTRICES (\n  PRIMARY KEY (magna_sodales, magna_lacus),\n  magna_sodales VARCHAR(42) NOT NULL,\n  magna_lacus   VARCHAR(42) NOT NULL\n);\n\nALTER TABLE NEC ADD FOREIGN KEY (magna_via_vitae) REFERENCES SODALES (magna);\nALTER TABLE NEC ADD FOREIGN KEY (magna_via_mollis) REFERENCES LACUS (magna);\n\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_lacus) REFERENCES LACUS (magna);\nALTER TABLE ULTRICES ADD FOREIGN KEY (magna_sodales) REFERENCES SODALES (magna);\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"SUSCIPIT\"]\n  6 [label=\"SODALES\"]\n  10 [label=\"QUAM\"]\n  13 [label=\"CONSEQUAT\"]\n  5 [label=\"TRISTIS\"]\n  19 [label=\"NEC\"]\n  23 [label=\"CURABITUR\"]\n  26 [label=\"DIGNISSIM\"]\n  30 [label=\"LACUS\"]\n  34 [label=\"LIBERO\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"lorem\"]\n  8 [label=\"ipsum\"]\n  12 [label=\"sed\"]\n  15 [label=\"dederit\"]\n  18 [label=\"vestibulum\"]\n  21 [label=\"audis\"]\n  25 [label=\"amor\"]\n  28 [label=\"terra\"]\n  32 [label=\"fugit\"]\n  36 [label=\"lacrima\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>orci</u>>]\n  7 [label=<<u>convallis</u>>]\n  11 [label=<<u>cras</u>>]\n  14 [label=<<u>fermentum</u>>]\n  17 [label=<<u>magna</u>>]\n  20 [label=<<u>pulvinar</u>>]\n  24 [label=<<u>gravida</u>>]\n  27 [label=<<u>tellus</u>>]\n  31 [label=<<u>tempor</u>>]\n  35 [label=<<u>posuere</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"RHONCUS\"]\n  9 [label=\"VITAE\"]\n  16 [label=\"ELIT\"]\n  22 [label=\"MOLLIS\"]\n  29 [label=\"ALIQUET\"]\n  33 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 17\n  5 -- 18\n  6 -- 7\n  6 -- 8\n  10 -- 11\n  10 -- 12\n  13 -- 14\n  13 -- 15\n  19 -- 20\n  19 -- 21\n  23 -- 24\n  23 -- 25\n  26 -- 27\n  26 -- 28\n  30 -- 31\n  30 -- 32\n  34 -- 35\n  34 -- 36\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  5 -- 4\n  6 -- 9\n  13 -- 16\n  23 -- 22\n  edge [headlabel=M]\n  26 -- 29\n  30 -- 33\n  edge [headlabel=N]\n  1 -- 4\n  5 -- 16\n  5 -- 29\n  10 -- 9\n  19 -- 22\n  34 -- 33\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_0_erd_chen.txt",
    "content": "[CONSEQUAT] ==1== <ELIT>\n[CURABITUR] ==1== <MOLLIS>\n[DIGNISSIM] ==M== <ALIQUET>\n[LACUS] ==M== <ULTRICES>\n[LIBERO] ==N== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[QUAM] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SUSCIPIT] ==N== <RHONCUS>\n[TRISTIS] ==1== <RHONCUS>\n[TRISTIS] ==N== <ALIQUET>\n[TRISTIS] ==N== <ELIT>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SUSCIPIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">orci</td></tr>\n        <tr><td> </td><td align=\"left\">lorem</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >QUAM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">cras</td></tr>\n        <tr><td> </td><td align=\"left\">sed</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONSEQUAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">fermentum</td></tr>\n        <tr><td> </td><td align=\"left\">dederit</td></tr>\n    </table>\n>]\n  5 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  6 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  7 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CURABITUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">gravida</td></tr>\n        <tr><td> </td><td align=\"left\">amor</td></tr>\n    </table>\n>]\n  8 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >DIGNISSIM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tellus</td></tr>\n        <tr><td> </td><td align=\"left\">terra</td></tr>\n    </table>\n>]\n  9 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  10 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LIBERO</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">posuere</td></tr>\n        <tr><td> </td><td align=\"left\">lacrima</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  5 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"RHONCUS\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  5 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"ELIT\"]\n  7 -> 6 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  5 -> 8 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ALIQUET\"]\n  10 -> 9 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_0_erd_crow.mmd",
    "content": "erDiagram\n  SUSCIPIT {\n    TYPE orci PK\n    TYPE lorem\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  QUAM {\n    TYPE cras PK\n    TYPE sed\n  }\n  CONSEQUAT {\n    TYPE fermentum PK\n    TYPE dederit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  CURABITUR {\n    TYPE gravida PK\n    TYPE amor\n  }\n  DIGNISSIM {\n    TYPE tellus PK\n    TYPE terra\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  LIBERO {\n    TYPE posuere PK\n    TYPE lacrima\n  }\n  TRISTIS ||--|{ SUSCIPIT: RHONCUS\n  QUAM }|--|| SODALES: VITAE\n  TRISTIS }|--|| CONSEQUAT: ELIT\n  CURABITUR ||--|{ NEC: MOLLIS\n  TRISTIS }|--|{ DIGNISSIM: ALIQUET\n  LIBERO }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_0_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"SUSCIPIT\") {\n    {field} + pk(orci)\n    {field} + lorem\n}\n\n\"TRISTIS\" \"1\" --- \"1..*\" \"SUSCIPIT\": \"RHONCUS\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n\"QUAM\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\nTable(\"QUAM\") {\n    {field} + pk(cras)\n    {field} + sed\n}\n\nTable(\"CONSEQUAT\") {\n    {field} + pk(fermentum)\n    {field} + dederit\n}\n\n\"TRISTIS\" \"1..*\" --- \"1\" \"CONSEQUAT\": \"ELIT\"\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\n\"CURABITUR\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"CURABITUR\") {\n    {field} + pk(gravida)\n    {field} + amor\n}\n\nTable(\"DIGNISSIM\") {\n    {field} + pk(tellus)\n    {field} + terra\n}\n\n\"TRISTIS\" \"1..*\" --- \"1..*\" \"DIGNISSIM\": \"ALIQUET\"\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\n\"LIBERO\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"LIBERO\") {\n    {field} + pk(posuere)\n    {field} + lacrima\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"SUSCIPIT\"]\n  6 [label=\"SODALES\"]\n  10 [label=\"QUAM\"]\n  13 [label=\"CONSEQUAT\"]\n  5 [label=\"TRISTIS\"]\n  19 [label=\"NEC\"]\n  23 [label=\"CURABITUR\"]\n  26 [label=\"DIGNISSIM\"]\n  30 [label=\"LACUS\"]\n  34 [label=\"LIBERO\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"lorem\"]\n  8 [label=\"ipsum\"]\n  12 [label=\"sed\"]\n  15 [label=\"dederit\"]\n  18 [label=\"vestibulum\"]\n  21 [label=\"audis\"]\n  25 [label=\"amor\"]\n  28 [label=\"terra\"]\n  32 [label=\"fugit\"]\n  36 [label=\"lacrima\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>orci</u>>]\n  7 [label=<<u>convallis</u>>]\n  11 [label=<<u>cras</u>>]\n  14 [label=<<u>fermentum</u>>]\n  17 [label=<<u>magna</u>>]\n  20 [label=<<u>pulvinar</u>>]\n  24 [label=<<u>gravida</u>>]\n  27 [label=<<u>tellus</u>>]\n  31 [label=<<u>tempor</u>>]\n  35 [label=<<u>posuere</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"RHONCUS\"]\n  9 [label=\"VITAE\"]\n  16 [label=\"ELIT\"]\n  22 [label=\"MOLLIS\"]\n  29 [label=\"ALIQUET\"]\n  33 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 17\n  5 -- 18\n  6 -- 7\n  6 -- 8\n  10 -- 11\n  10 -- 12\n  13 -- 14\n  13 -- 15\n  19 -- 20\n  19 -- 21\n  23 -- 24\n  23 -- 25\n  26 -- 27\n  26 -- 28\n  30 -- 31\n  30 -- 32\n  34 -- 35\n  34 -- 36\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  5 -- 4\n  6 -- 9\n  13 -- 16\n  23 -- 22\n  edge [headlabel=M]\n  26 -- 29\n  30 -- 33\n  edge [headlabel=N]\n  1 -- 4\n  5 -- 16\n  5 -- 29\n  10 -- 9\n  19 -- 22\n  34 -- 33\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_1_erd_chen.txt",
    "content": "[CONSEQUAT] ==1== <ELIT>\n[CURABITUR] ==1== <MOLLIS>\n[DIGNISSIM] ==M== <ALIQUET>\n[LACUS] ==M== <ULTRICES>\n[LIBERO] ==N== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[QUAM] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SUSCIPIT] ==N== <RHONCUS>\n[TRISTIS] ==1== <RHONCUS>\n[TRISTIS] ==N== <ALIQUET>\n[TRISTIS] ==N== <ELIT>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_1_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SUSCIPIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">orci</td></tr>\n        <tr><td> </td><td align=\"left\">lorem</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >QUAM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">cras</td></tr>\n        <tr><td> </td><td align=\"left\">sed</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONSEQUAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">fermentum</td></tr>\n        <tr><td> </td><td align=\"left\">dederit</td></tr>\n    </table>\n>]\n  5 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  6 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  7 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CURABITUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">gravida</td></tr>\n        <tr><td> </td><td align=\"left\">amor</td></tr>\n    </table>\n>]\n  8 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >DIGNISSIM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tellus</td></tr>\n        <tr><td> </td><td align=\"left\">terra</td></tr>\n    </table>\n>]\n  9 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  10 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LIBERO</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">posuere</td></tr>\n        <tr><td> </td><td align=\"left\">lacrima</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  5 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"RHONCUS\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  5 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"ELIT\"]\n  7 -> 6 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  5 -> 8 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ALIQUET\"]\n  10 -> 9 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_1_erd_crow.mmd",
    "content": "erDiagram\n  SUSCIPIT {\n    TYPE orci PK\n    TYPE lorem\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  QUAM {\n    TYPE cras PK\n    TYPE sed\n  }\n  CONSEQUAT {\n    TYPE fermentum PK\n    TYPE dederit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  CURABITUR {\n    TYPE gravida PK\n    TYPE amor\n  }\n  DIGNISSIM {\n    TYPE tellus PK\n    TYPE terra\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  LIBERO {\n    TYPE posuere PK\n    TYPE lacrima\n  }\n  TRISTIS ||--|{ SUSCIPIT: RHONCUS\n  QUAM }|--|| SODALES: VITAE\n  TRISTIS }|--|| CONSEQUAT: ELIT\n  CURABITUR ||--|{ NEC: MOLLIS\n  TRISTIS }|--|{ DIGNISSIM: ALIQUET\n  LIBERO }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_1_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"SUSCIPIT\") {\n    {field} + pk(orci)\n    {field} + lorem\n}\n\n\"TRISTIS\" \"1\" --- \"1..*\" \"SUSCIPIT\": \"RHONCUS\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n\"QUAM\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\nTable(\"QUAM\") {\n    {field} + pk(cras)\n    {field} + sed\n}\n\nTable(\"CONSEQUAT\") {\n    {field} + pk(fermentum)\n    {field} + dederit\n}\n\n\"TRISTIS\" \"1..*\" --- \"1\" \"CONSEQUAT\": \"ELIT\"\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\n\"CURABITUR\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"CURABITUR\") {\n    {field} + pk(gravida)\n    {field} + amor\n}\n\nTable(\"DIGNISSIM\") {\n    {field} + pk(tellus)\n    {field} + terra\n}\n\n\"TRISTIS\" \"1..*\" --- \"1..*\" \"DIGNISSIM\": \"ALIQUET\"\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\n\"LIBERO\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"LIBERO\") {\n    {field} + pk(posuere)\n    {field} + lacrima\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_2_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"SUSCIPIT\"]\n  6 [label=\"SODALES\"]\n  10 [label=\"QUAM\"]\n  13 [label=\"CONSEQUAT\"]\n  5 [label=\"TRISTIS\"]\n  19 [label=\"NEC\"]\n  23 [label=\"CURABITUR\"]\n  26 [label=\"DIGNISSIM\"]\n  30 [label=\"LACUS\"]\n  34 [label=\"LIBERO\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"lorem\"]\n  8 [label=\"ipsum\"]\n  12 [label=\"sed\"]\n  15 [label=\"dederit\"]\n  18 [label=\"vestibulum\"]\n  21 [label=\"audis\"]\n  25 [label=\"amor\"]\n  28 [label=\"terra\"]\n  32 [label=\"fugit\"]\n  36 [label=\"lacrima\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>orci</u>>]\n  7 [label=<<u>convallis</u>>]\n  11 [label=<<u>cras</u>>]\n  14 [label=<<u>fermentum</u>>]\n  17 [label=<<u>magna</u>>]\n  20 [label=<<u>pulvinar</u>>]\n  24 [label=<<u>gravida</u>>]\n  27 [label=<<u>tellus</u>>]\n  31 [label=<<u>tempor</u>>]\n  35 [label=<<u>posuere</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"RHONCUS\"]\n  9 [label=\"VITAE\"]\n  16 [label=\"ELIT\"]\n  22 [label=\"MOLLIS\"]\n  29 [label=\"ALIQUET\"]\n  33 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 17\n  5 -- 18\n  6 -- 7\n  6 -- 8\n  10 -- 11\n  10 -- 12\n  13 -- 14\n  13 -- 15\n  19 -- 20\n  19 -- 21\n  23 -- 24\n  23 -- 25\n  26 -- 27\n  26 -- 28\n  30 -- 31\n  30 -- 32\n  34 -- 35\n  34 -- 36\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  5 -- 4\n  6 -- 9\n  13 -- 16\n  23 -- 22\n  edge [headlabel=M]\n  26 -- 29\n  30 -- 33\n  edge [headlabel=N]\n  1 -- 4\n  5 -- 16\n  5 -- 29\n  10 -- 9\n  19 -- 22\n  34 -- 33\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_2_erd_chen.txt",
    "content": "[CONSEQUAT] ==1== <ELIT>\n[CURABITUR] ==1== <MOLLIS>\n[DIGNISSIM] ==M== <ALIQUET>\n[LACUS] ==M== <ULTRICES>\n[LIBERO] ==N== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[QUAM] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SUSCIPIT] ==N== <RHONCUS>\n[TRISTIS] ==1== <RHONCUS>\n[TRISTIS] ==N== <ALIQUET>\n[TRISTIS] ==N== <ELIT>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_2_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SUSCIPIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">orci</td></tr>\n        <tr><td> </td><td align=\"left\">lorem</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >QUAM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">cras</td></tr>\n        <tr><td> </td><td align=\"left\">sed</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONSEQUAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">fermentum</td></tr>\n        <tr><td> </td><td align=\"left\">dederit</td></tr>\n    </table>\n>]\n  5 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  6 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  7 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CURABITUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">gravida</td></tr>\n        <tr><td> </td><td align=\"left\">amor</td></tr>\n    </table>\n>]\n  8 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >DIGNISSIM</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tellus</td></tr>\n        <tr><td> </td><td align=\"left\">terra</td></tr>\n    </table>\n>]\n  9 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  10 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LIBERO</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">posuere</td></tr>\n        <tr><td> </td><td align=\"left\">lacrima</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  5 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"RHONCUS\"]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  5 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"ELIT\"]\n  7 -> 6 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  5 -> 8 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ALIQUET\"]\n  10 -> 9 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_2_erd_crow.mmd",
    "content": "erDiagram\n  SUSCIPIT {\n    TYPE orci PK\n    TYPE lorem\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  QUAM {\n    TYPE cras PK\n    TYPE sed\n  }\n  CONSEQUAT {\n    TYPE fermentum PK\n    TYPE dederit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  CURABITUR {\n    TYPE gravida PK\n    TYPE amor\n  }\n  DIGNISSIM {\n    TYPE tellus PK\n    TYPE terra\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  LIBERO {\n    TYPE posuere PK\n    TYPE lacrima\n  }\n  TRISTIS ||--|{ SUSCIPIT: RHONCUS\n  QUAM }|--|| SODALES: VITAE\n  TRISTIS }|--|| CONSEQUAT: ELIT\n  CURABITUR ||--|{ NEC: MOLLIS\n  TRISTIS }|--|{ DIGNISSIM: ALIQUET\n  LIBERO }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_2_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"SUSCIPIT\") {\n    {field} + pk(orci)\n    {field} + lorem\n}\n\n\"TRISTIS\" \"1\" --- \"1..*\" \"SUSCIPIT\": \"RHONCUS\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n\"QUAM\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\nTable(\"QUAM\") {\n    {field} + pk(cras)\n    {field} + sed\n}\n\nTable(\"CONSEQUAT\") {\n    {field} + pk(fermentum)\n    {field} + dederit\n}\n\n\"TRISTIS\" \"1..*\" --- \"1\" \"CONSEQUAT\": \"ELIT\"\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\n\"CURABITUR\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"CURABITUR\") {\n    {field} + pk(gravida)\n    {field} + amor\n}\n\nTable(\"DIGNISSIM\") {\n    {field} + pk(tellus)\n    {field} + terra\n}\n\n\"TRISTIS\" \"1..*\" --- \"1..*\" \"DIGNISSIM\": \"ALIQUET\"\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\n\"LIBERO\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"LIBERO\") {\n    {field} + pk(posuere)\n    {field} + lacrima\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_3_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"NEC\"]\n  2 [label=\"LACUS\"]\n  12 [label=\"SODALES\"]\n\n  // Associative entities\n  8 [label=\"TRISTIS\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"audis\"]\n  7 [label=\"fugit\"]\n  10 [label=\"vestibulum\"]\n  15 [label=\"ipsum\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>pulvinar</u>>]\n  6 [label=<<u>tempor</u>>]\n  9 [label=<<u>magna</u>>]\n  14 [label=<<u>convallis</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"MOLLIS\"]\n  11 [label=\"VITAE\"]\n  13 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 6\n  2 -- 7\n  3 -- 4\n  3 -- 5\n  8 -- 9\n  8 -- 10\n  12 -- 14\n  12 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  2 -- 1\n  12 -- 11\n  edge [headlabel=M]\n  2 -- 13\n  edge [headlabel=N]\n  3 -- 1\n  3 -- 11\n  12 -- 13\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_3_erd_chen.txt",
    "content": "[LACUS] ==1== <MOLLIS>\n[LACUS] ==M== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[NEC] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SODALES] ==N== <ULTRICES>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_3_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  1 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  4 -> 2 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_3_erd_crow.mmd",
    "content": "erDiagram\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  LACUS ||--|{ NEC: MOLLIS\n  NEC }|--|| SODALES: VITAE\n  SODALES }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_3_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"LACUS\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\n\"NEC\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\n\"SODALES\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_4_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"NEC\"]\n  2 [label=\"LACUS\"]\n  12 [label=\"SODALES\"]\n\n  // Associative entities\n  8 [label=\"TRISTIS\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"audis\"]\n  7 [label=\"fugit\"]\n  10 [label=\"vestibulum\"]\n  15 [label=\"ipsum\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>pulvinar</u>>]\n  6 [label=<<u>tempor</u>>]\n  9 [label=<<u>magna</u>>]\n  14 [label=<<u>convallis</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"MOLLIS\"]\n  11 [label=\"VITAE\"]\n  13 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 6\n  2 -- 7\n  3 -- 4\n  3 -- 5\n  8 -- 9\n  8 -- 10\n  12 -- 14\n  12 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  2 -- 1\n  12 -- 11\n  edge [headlabel=M]\n  2 -- 13\n  edge [headlabel=N]\n  3 -- 1\n  3 -- 11\n  12 -- 13\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_4_erd_chen.txt",
    "content": "[LACUS] ==1== <MOLLIS>\n[LACUS] ==M== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[NEC] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SODALES] ==N== <ULTRICES>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_4_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  1 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  4 -> 2 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_4_erd_crow.mmd",
    "content": "erDiagram\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  LACUS ||--|{ NEC: MOLLIS\n  NEC }|--|| SODALES: VITAE\n  SODALES }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_4_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"LACUS\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\n\"NEC\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\n\"SODALES\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_5_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"NEC\"]\n  2 [label=\"LACUS\"]\n  12 [label=\"SODALES\"]\n\n  // Associative entities\n  8 [label=\"TRISTIS\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"audis\"]\n  7 [label=\"fugit\"]\n  10 [label=\"vestibulum\"]\n  15 [label=\"ipsum\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>pulvinar</u>>]\n  6 [label=<<u>tempor</u>>]\n  9 [label=<<u>magna</u>>]\n  14 [label=<<u>convallis</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"MOLLIS\"]\n  11 [label=\"VITAE\"]\n  13 [label=\"ULTRICES\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 6\n  2 -- 7\n  3 -- 4\n  3 -- 5\n  8 -- 9\n  8 -- 10\n  12 -- 14\n  12 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  2 -- 1\n  12 -- 11\n  edge [headlabel=M]\n  2 -- 13\n  edge [headlabel=N]\n  3 -- 1\n  3 -- 11\n  12 -- 13\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_5_erd_chen.txt",
    "content": "[LACUS] ==1== <MOLLIS>\n[LACUS] ==M== <ULTRICES>\n[NEC] ==N== <MOLLIS>\n[NEC] ==N== <VITAE>\n[SODALES] ==1== <VITAE>\n[SODALES] ==N== <ULTRICES>\n"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_5_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >NEC</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pulvinar</td></tr>\n        <tr><td> </td><td align=\"left\">audis</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >LACUS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">tempor</td></tr>\n        <tr><td> </td><td align=\"left\">fugit</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >TRISTIS</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">magna</td></tr>\n        <tr><td> </td><td align=\"left\">vestibulum</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SODALES</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">convallis</td></tr>\n        <tr><td> </td><td align=\"left\">ipsum</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"MOLLIS\"]\n  1 -> 4 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"VITAE\"]\n  4 -> 2 [arrowhead=\"crowtee\" arrowtail=\"crowtee\" label=\"ULTRICES\"]\n}"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_5_erd_crow.mmd",
    "content": "erDiagram\n  NEC {\n    TYPE pulvinar PK\n    TYPE audis\n  }\n  LACUS {\n    TYPE tempor PK\n    TYPE fugit\n  }\n  TRISTIS {\n    TYPE magna PK\n    TYPE vestibulum\n  }\n  SODALES {\n    TYPE convallis PK\n    TYPE ipsum\n  }\n  LACUS ||--|{ NEC: MOLLIS\n  NEC }|--|| SODALES: VITAE\n  SODALES }|--|{ LACUS: ULTRICES"
  },
  {
    "path": "test/zoo/inheritance/exported/inheritance_5_uml.puml",
    "content": "@startuml \"inheritance\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"LACUS\" \"1\" --- \"1..*\" \"NEC\": \"MOLLIS\"\n\nTable(\"NEC\") {\n    {field} + pk(pulvinar)\n    {field} + audis\n}\n\nTable(\"LACUS\") {\n    {field} + pk(tempor)\n    {field} + fugit\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- LACUS\nGENERALIZATION_0 -[dotted]- NEC\nGENERALIZATION_0 -[dotted]- SODALES\nTRISTIS <|-- LACUS\nTRISTIS <|-- NEC\nTRISTIS <|-- SODALES\n\nTable(\"TRISTIS\") {\n    {field} + pk(magna)\n    {field} + vestibulum\n}\n\n\"NEC\" \"1..*\" --- \"1\" \"SODALES\": \"VITAE\"\n\n\"SODALES\" \"1..*\" --- \"1..*\" \"LACUS\": \"ULTRICES\"\n\nTable(\"SODALES\") {\n    {field} + pk(convallis)\n    {field} + ipsum\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nALIQUET\tmagna\t!\t\tprimary_foreign_key\tTrue\tTRISTIS\tTRISTIS\tALIQUET\t\t\nALIQUET\ttellus\t!\t\tprimary_foreign_key\tTrue\tDIGNISSIM\tDIGNISSIM\tALIQUET\t\t\nCONSEQUAT\tfermentum\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONSEQUAT\tdederit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCURABITUR\tgravida\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCURABITUR\tamor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nDIGNISSIM\ttellus\t!\t\tprimary_key\tTrue\t\t\t\t\t\nDIGNISSIM\tterra\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLIBERO\tposuere\t!\t\tprimary_key\tTrue\t\t\t\t\t\nLIBERO\tlacrima\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nQUAM\tcras\t!\t\tprimary_key\tTrue\t\t\t\t\t\nQUAM\tsed\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nQUAM\tmagna\t!\t\tforeign_key\tFalse\tSODALES\tTRISTIS\tVITAE\t\t\nSUSCIPIT\torci\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSUSCIPIT\tlorem\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSUSCIPIT\tmagna\t!\t\tforeign_key\tFalse\tTRISTIS\tTRISTIS\tRHONCUS\t\t\nTRISTIS\tmagna\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTRISTIS\tvestibulum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTRISTIS\tfermentum\t!\t\tforeign_key\tFalse\tCONSEQUAT\tCONSEQUAT\tELIT\t\t\nTRISTIS\ttype\t!\t\tdeleted_child_discriminator_XT\tFalse\t\t\tXT\tUNSIGNED_INT_PLACEHOLDER\t\nTRISTIS\tconvallis\t?\t\tdeleted_child_attribute\tFalse\tSODALES\t\tXT\t\t\nTRISTIS\tipsum\t?\t\tdeleted_child_attribute\tFalse\tSODALES\t\tXT\t\t\nTRISTIS\tpulvinar\t?\t\tdeleted_child_attribute\tFalse\tNEC\t\tXT\t\t\nTRISTIS\taudis\t?\t\tdeleted_child_attribute\tFalse\tNEC\t\tXT\t\t\nTRISTIS\tgravida\t?\t\tdeleted_child_foreign_key\tFalse\tNEC\tCURABITUR\tXT\t\t\nTRISTIS\ttempor\t?\t\tdeleted_child_attribute\tFalse\tLACUS\t\tXT\t\t\nTRISTIS\tfugit\t?\t\tdeleted_child_attribute\tFalse\tLACUS\t\tXT\t\t\nULTRICES\tposuere\t!\t\tprimary_foreign_key\tTrue\tLIBERO\tLIBERO\tULTRICES\t\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tTRISTIS\tULTRICES\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"DIGNISSIM\" -> \"ALIQUET\"\n  \"TRISTIS\" -> \"ALIQUET\"\n  \"TRISTIS\" -> \"QUAM\"\n  \"TRISTIS\" -> \"SUSCIPIT\"\n  \"CURABITUR\" -> \"TRISTIS\"\n  \"CONSEQUAT\" -> \"TRISTIS\"\n  \"TRISTIS\" -> \"ULTRICES\"\n  \"LIBERO\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_0_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>ALIQUET</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='foreign primary'>#tellus</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>tellus</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>DIGNISSIM</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CONSEQUAT</span> (\n    <span class='primary'>fermentum</span>,\n    <span class='normal'>dederit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>fermentum</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONSEQUAT</i>.</li>\n    <li>Le champ <i>dederit</i> était déjà un simple attribut de l'entité <i>CONSEQUAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CURABITUR</span> (\n    <span class='primary'>gravida</span>,\n    <span class='normal'>amor</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>gravida</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CURABITUR</i>.</li>\n    <li>Le champ <i>amor</i> était déjà un simple attribut de l'entité <i>CURABITUR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>DIGNISSIM</span> (\n    <span class='primary'>tellus</span>,\n    <span class='normal'>terra</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>tellus</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>DIGNISSIM</i>.</li>\n    <li>Le champ <i>terra</i> était déjà un simple attribut de l'entité <i>DIGNISSIM</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>LIBERO</span> (\n    <span class='primary'>posuere</span>,\n    <span class='normal'>lacrima</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>lacrima</i> était déjà un simple attribut de l'entité <i>LIBERO</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>QUAM</span> (\n    <span class='primary'>cras</span>,\n    <span class='normal'>sed</span>,\n    <span class='foreign'>#magna!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>cras</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>QUAM</i>.</li>\n    <li>Le champ <i>sed</i> était déjà un simple attribut de l'entité <i>QUAM</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>VITAE</i> à partir de l'entité <i>TRISTIS</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SUSCIPIT</span> (\n    <span class='primary'>orci</span>,\n    <span class='normal'>lorem</span>,\n    <span class='foreign'>#magna!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>orci</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ <i>lorem</i> était déjà un simple attribut de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>RHONCUS</i> à partir de l'entité <i>TRISTIS</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>TRISTIS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='foreign'>#fermentum!</span>,\n    <span class='normal'>type!</span>,\n    <span class='normal'>convallis?</span>,\n    <span class='normal'>ipsum?</span>,\n    <span class='normal'>pulvinar?</span>,\n    <span class='normal'>audis?</span>,\n    <span class='foreign'>#gravida?</span>,\n    <span class='normal'>tempor?</span>,\n    <span class='normal'>fugit?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>vestibulum</i> était déjà un simple attribut de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ à saisie obligatoire <i>fermentum</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>ELIT</i> à partir de l'entité <i>CONSEQUAT</i> en perdant son caractère identifiant.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n    <li>Le champ à saisie facultative <i>convallis</i> a migré à partir de l'entité-fille <i>SODALES</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>ipsum</i> a migré à partir de l'entité-fille <i>SODALES</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>pulvinar</i> a migré à partir de l'entité-fille <i>NEC</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>audis</i> a migré à partir de l'entité-fille <i>NEC</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>gravida</i> est une clé étrangère. Il a migré à partir de l'entité-fille <i>NEC</i> (supprimée) dans laquelle il avait déjà migré à partir de l'entité <i>CURABITUR</i>.</li>\n    <li>Le champ à saisie facultative <i>tempor</i> a migré à partir de l'entité-fille <i>LACUS</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>fugit</i> a migré à partir de l'entité-fille <i>LACUS</i> (supprimée).</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#posuere</span>,\n    <span class='foreign primary'>#magna</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>TRISTIS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_mld.mcd",
    "content": "%%mocodo\n:\nSUSCIPIT: orci, lorem, #magna > TRISTIS > magna\n:::::::\nQUAM: cras, sed, #magna > TRISTIS > magna\n:\n\n\n:\nCONSEQUAT: fermentum, dederit\n:::\nTRISTIS: magna, vestibulum, #fermentum > CONSEQUAT > fermentum, type, convallis, ipsum, pulvinar, audis, #gravida > CURABITUR > gravida, tempor, fugit\n:::\nCURABITUR: gravida, amor\n:\n\n\n:\nDIGNISSIM: tellus, terra\n:\nALIQUET: #magna > TRISTIS > magna, _#tellus > DIGNISSIM > tellus\n:::\nULTRICES: #posuere > LIBERO > posuere, _#magna > TRISTIS > magna\n:\nLIBERO: posuere, lacrima\n:\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_mld.md",
    "content": "- **ALIQUET** (<u>_#magna_</u>, <u>_#tellus_</u>)\n  - Le champ _magna_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _TRISTIS_.\n  - Le champ _tellus_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _DIGNISSIM_.\n\n- **CONSEQUAT** (<u>fermentum</u>, dederit)\n  - Le champ _fermentum_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CONSEQUAT_.\n  - Le champ _dederit_ était déjà un simple attribut de l'entité _CONSEQUAT_.\n\n- **CURABITUR** (<u>gravida</u>, amor)\n  - Le champ _gravida_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CURABITUR_.\n  - Le champ _amor_ était déjà un simple attribut de l'entité _CURABITUR_.\n\n- **DIGNISSIM** (<u>tellus</u>, terra)\n  - Le champ _tellus_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _DIGNISSIM_.\n  - Le champ _terra_ était déjà un simple attribut de l'entité _DIGNISSIM_.\n\n- **LIBERO** (<u>posuere</u>, lacrima)\n  - Le champ _posuere_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _LIBERO_.\n  - Le champ _lacrima_ était déjà un simple attribut de l'entité _LIBERO_.\n\n- **QUAM** (<u>cras</u>, sed, _#magna!_)\n  - Le champ _cras_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _QUAM_.\n  - Le champ _sed_ était déjà un simple attribut de l'entité _QUAM_.\n  - Le champ à saisie obligatoire _magna_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _VITAE_ à partir de l'entité _TRISTIS_ en perdant son caractère identifiant.\n\n- **SUSCIPIT** (<u>orci</u>, lorem, _#magna!_)\n  - Le champ _orci_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _SUSCIPIT_.\n  - Le champ _lorem_ était déjà un simple attribut de l'entité _SUSCIPIT_.\n  - Le champ à saisie obligatoire _magna_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _RHONCUS_ à partir de l'entité _TRISTIS_ en perdant son caractère identifiant.\n\n- **TRISTIS** (<u>magna</u>, vestibulum, _#fermentum!_, type!, convallis?, ipsum?, pulvinar?, audis?, _#gravida?_, tempor?, fugit?)\n  - Le champ _magna_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _TRISTIS_.\n  - Le champ _vestibulum_ était déjà un simple attribut de l'entité _TRISTIS_.\n  - Le champ à saisie obligatoire _fermentum_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _ELIT_ à partir de l'entité _CONSEQUAT_ en perdant son caractère identifiant.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  - Le champ à saisie facultative _convallis_ a migré à partir de l'entité-fille _SODALES_ (supprimée).\n  - Le champ à saisie facultative _ipsum_ a migré à partir de l'entité-fille _SODALES_ (supprimée).\n  - Le champ à saisie facultative _pulvinar_ a migré à partir de l'entité-fille _NEC_ (supprimée).\n  - Le champ à saisie facultative _audis_ a migré à partir de l'entité-fille _NEC_ (supprimée).\n  - Le champ à saisie facultative _gravida_ est une clé étrangère. Il a migré à partir de l'entité-fille _NEC_ (supprimée) dans laquelle il avait déjà migré à partir de l'entité _CURABITUR_.\n  - Le champ à saisie facultative _tempor_ a migré à partir de l'entité-fille _LACUS_ (supprimée).\n  - Le champ à saisie facultative _fugit_ a migré à partir de l'entité-fille _LACUS_ (supprimée).\n\n- **ULTRICES** (<u>_#posuere_</u>, <u>_#magna_</u>)\n  - Le champ _posuere_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LIBERO_.\n  - Le champ _magna_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _TRISTIS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{ALIQUET} (\\foreign{\\prim{magna}}, \\foreign{\\prim{tellus}})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{tellus} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{DIGNISSIM}.\n  \\end{itemize}\n\n  \\item \\relat{CONSEQUAT} (\\prim{fermentum}, \\attr{dederit})\n  \\begin{itemize}\n    \\item Le champ \\emph{fermentum} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONSEQUAT}.\n    \\item Le champ \\emph{dederit} était déjà un simple attribut de l'entité \\emph{CONSEQUAT}.\n  \\end{itemize}\n\n  \\item \\relat{CURABITUR} (\\prim{gravida}, \\attr{amor})\n  \\begin{itemize}\n    \\item Le champ \\emph{gravida} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CURABITUR}.\n    \\item Le champ \\emph{amor} était déjà un simple attribut de l'entité \\emph{CURABITUR}.\n  \\end{itemize}\n\n  \\item \\relat{DIGNISSIM} (\\prim{tellus}, \\attr{terra})\n  \\begin{itemize}\n    \\item Le champ \\emph{tellus} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{DIGNISSIM}.\n    \\item Le champ \\emph{terra} était déjà un simple attribut de l'entité \\emph{DIGNISSIM}.\n  \\end{itemize}\n\n  \\item \\relat{LIBERO} (\\prim{posuere}, \\attr{lacrima})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{lacrima} était déjà un simple attribut de l'entité \\emph{LIBERO}.\n  \\end{itemize}\n\n  \\item \\relat{QUAM} (\\prim{cras}, \\attr{sed}, \\foreign{magna!})\n  \\begin{itemize}\n    \\item Le champ \\emph{cras} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{QUAM}.\n    \\item Le champ \\emph{sed} était déjà un simple attribut de l'entité \\emph{QUAM}.\n    \\item Le champ à saisie obligatoire \\emph{magna} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{VITAE} à partir de l'entité \\emph{TRISTIS} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{SUSCIPIT} (\\prim{orci}, \\attr{lorem}, \\foreign{magna!})\n  \\begin{itemize}\n    \\item Le champ \\emph{orci} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ \\emph{lorem} était déjà un simple attribut de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ à saisie obligatoire \\emph{magna} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{RHONCUS} à partir de l'entité \\emph{TRISTIS} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{TRISTIS} (\\prim{magna}, \\attr{vestibulum}, \\foreign{fermentum!}, \\attr{type!}, \\attr{convallis?}, \\attr{ipsum?}, \\attr{pulvinar?}, \\attr{audis?}, \\foreign{gravida?}, \\attr{tempor?}, \\attr{fugit?})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{vestibulum} était déjà un simple attribut de l'entité \\emph{TRISTIS}.\n    \\item Le champ à saisie obligatoire \\emph{fermentum} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{ELIT} à partir de l'entité \\emph{CONSEQUAT} en perdant son caractère identifiant.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n    \\item Le champ à saisie facultative \\emph{convallis} a migré à partir de l'entité-fille \\emph{SODALES} (supprimée).\n    \\item Le champ à saisie facultative \\emph{ipsum} a migré à partir de l'entité-fille \\emph{SODALES} (supprimée).\n    \\item Le champ à saisie facultative \\emph{pulvinar} a migré à partir de l'entité-fille \\emph{NEC} (supprimée).\n    \\item Le champ à saisie facultative \\emph{audis} a migré à partir de l'entité-fille \\emph{NEC} (supprimée).\n    \\item Le champ à saisie facultative \\emph{gravida} est une clé étrangère. Il a migré à partir de l'entité-fille \\emph{NEC} (supprimée) dans laquelle il avait déjà migré à partir de l'entité \\emph{CURABITUR}.\n    \\item Le champ à saisie facultative \\emph{tempor} a migré à partir de l'entité-fille \\emph{LACUS} (supprimée).\n    \\item Le champ à saisie facultative \\emph{fugit} a migré à partir de l'entité-fille \\emph{LACUS} (supprimée).\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{posuere}}, \\foreign{\\prim{magna}})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{TRISTIS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_0_mld.txt",
    "content": "- ALIQUET (_#magna_, _#tellus_)\n  - Le champ « magna » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « TRISTIS ».\n  - Le champ « tellus » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « DIGNISSIM ».\n\n- CONSEQUAT (_fermentum_, dederit)\n  - Le champ « fermentum » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CONSEQUAT ».\n  - Le champ « dederit » était déjà un simple attribut de l'entité « CONSEQUAT ».\n\n- CURABITUR (_gravida_, amor)\n  - Le champ « gravida » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CURABITUR ».\n  - Le champ « amor » était déjà un simple attribut de l'entité « CURABITUR ».\n\n- DIGNISSIM (_tellus_, terra)\n  - Le champ « tellus » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « DIGNISSIM ».\n  - Le champ « terra » était déjà un simple attribut de l'entité « DIGNISSIM ».\n\n- LIBERO (_posuere_, lacrima)\n  - Le champ « posuere » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « LIBERO ».\n  - Le champ « lacrima » était déjà un simple attribut de l'entité « LIBERO ».\n\n- QUAM (_cras_, sed, #magna!)\n  - Le champ « cras » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « QUAM ».\n  - Le champ « sed » était déjà un simple attribut de l'entité « QUAM ».\n  - Le champ à saisie obligatoire « magna » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « VITAE » à partir de l'entité « TRISTIS » en perdant son caractère identifiant.\n\n- SUSCIPIT (_orci_, lorem, #magna!)\n  - Le champ « orci » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « SUSCIPIT ».\n  - Le champ « lorem » était déjà un simple attribut de l'entité « SUSCIPIT ».\n  - Le champ à saisie obligatoire « magna » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « RHONCUS » à partir de l'entité « TRISTIS » en perdant son caractère identifiant.\n\n- TRISTIS (_magna_, vestibulum, #fermentum!, type!, convallis?, ipsum?, pulvinar?, audis?, #gravida?, tempor?, fugit?)\n  - Le champ « magna » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « TRISTIS ».\n  - Le champ « vestibulum » était déjà un simple attribut de l'entité « TRISTIS ».\n  - Le champ à saisie obligatoire « fermentum » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « ELIT » à partir de l'entité « CONSEQUAT » en perdant son caractère identifiant.\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  - Le champ à saisie facultative « convallis » a migré à partir de l'entité-fille « SODALES » (supprimée).\n  - Le champ à saisie facultative « ipsum » a migré à partir de l'entité-fille « SODALES » (supprimée).\n  - Le champ à saisie facultative « pulvinar » a migré à partir de l'entité-fille « NEC » (supprimée).\n  - Le champ à saisie facultative « audis » a migré à partir de l'entité-fille « NEC » (supprimée).\n  - Le champ à saisie facultative « gravida » est une clé étrangère. Il a migré à partir de l'entité-fille « NEC » (supprimée) dans laquelle il avait déjà migré à partir de l'entité « CURABITUR ».\n  - Le champ à saisie facultative « tempor » a migré à partir de l'entité-fille « LACUS » (supprimée).\n  - Le champ à saisie facultative « fugit » a migré à partir de l'entité-fille « LACUS » (supprimée).\n\n- ULTRICES (_#posuere_, _#magna_)\n  - Le champ « posuere » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LIBERO ».\n  - Le champ « magna » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « TRISTIS ».\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nALIQUET\tmagna\t!\t\tprimary_foreign_key\tTrue\tTRISTIS\tTRISTIS\tALIQUET\t\t\nALIQUET\ttellus\t!\t\tprimary_foreign_key\tTrue\tDIGNISSIM\tDIGNISSIM\tALIQUET\t\t\nCONSEQUAT\tfermentum\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONSEQUAT\tdederit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCURABITUR\tgravida\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCURABITUR\tamor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nDIGNISSIM\ttellus\t!\t\tprimary_key\tTrue\t\t\t\t\t\nDIGNISSIM\tterra\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nLACUS\ttempor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tfugit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLIBERO\tposuere\t!\t\tprimary_key\tTrue\t\t\t\t\t\nLIBERO\tlacrima\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nNEC\tpulvinar\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\taudis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tgravida\t!\t\tforeign_key\tFalse\tCURABITUR\tCURABITUR\tMOLLIS\t\t\nQUAM\tcras\t!\t\tprimary_key\tTrue\t\t\t\t\t\nQUAM\tsed\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nQUAM\tmagna\t!\t\tforeign_key\tFalse\tSODALES\tSODALES\tVITAE\t\t\nSODALES\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nSODALES\tconvallis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSODALES\tipsum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSUSCIPIT\torci\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSUSCIPIT\tlorem\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSUSCIPIT\tmagna\t!\t\tforeign_key\tFalse\tTRISTIS\tTRISTIS\tRHONCUS\t\t\nTRISTIS\tmagna\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTRISTIS\tvestibulum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTRISTIS\tfermentum\t!\t\tforeign_key\tFalse\tCONSEQUAT\tCONSEQUAT\tELIT\t\t\nTRISTIS\ttype\t!\t\tdeleted_child_discriminator_XT\tFalse\t\t\tXT\tUNSIGNED_INT_PLACEHOLDER\t\nULTRICES\tposuere\t!\t\tprimary_foreign_key\tTrue\tLIBERO\tLIBERO\tULTRICES\t\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tLACUS\tULTRICES\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"DIGNISSIM\" -> \"ALIQUET\"\n  \"TRISTIS\" -> \"ALIQUET\"\n  \"TRISTIS\" -> \"LACUS\"\n  \"CURABITUR\" -> \"NEC\"\n  \"TRISTIS\" -> \"NEC\"\n  \"SODALES\" -> \"QUAM\"\n  \"TRISTIS\" -> \"SODALES\"\n  \"TRISTIS\" -> \"SUSCIPIT\"\n  \"CONSEQUAT\" -> \"TRISTIS\"\n  \"LACUS\" -> \"ULTRICES\"\n  \"LIBERO\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_1_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>ALIQUET</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='foreign primary'>#tellus</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>tellus</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>DIGNISSIM</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CONSEQUAT</span> (\n    <span class='primary'>fermentum</span>,\n    <span class='normal'>dederit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>fermentum</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONSEQUAT</i>.</li>\n    <li>Le champ <i>dederit</i> était déjà un simple attribut de l'entité <i>CONSEQUAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CURABITUR</span> (\n    <span class='primary'>gravida</span>,\n    <span class='normal'>amor</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>gravida</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CURABITUR</i>.</li>\n    <li>Le champ <i>amor</i> était déjà un simple attribut de l'entité <i>CURABITUR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>DIGNISSIM</span> (\n    <span class='primary'>tellus</span>,\n    <span class='normal'>terra</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>tellus</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>DIGNISSIM</i>.</li>\n    <li>Le champ <i>terra</i> était déjà un simple attribut de l'entité <i>DIGNISSIM</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>LACUS</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>tempor</span>,\n    <span class='normal'>fugit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>tempor</i> et <i>fugit</i> étaient déjà de simples attributs de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>LIBERO</span> (\n    <span class='primary'>posuere</span>,\n    <span class='normal'>lacrima</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>lacrima</i> était déjà un simple attribut de l'entité <i>LIBERO</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>NEC</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>pulvinar</span>,\n    <span class='normal'>audis</span>,\n    <span class='foreign'>#gravida!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>pulvinar</i> et <i>audis</i> étaient déjà de simples attributs de l'entité <i>NEC</i>.</li>\n    <li>Le champ à saisie obligatoire <i>gravida</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>MOLLIS</i> à partir de l'entité <i>CURABITUR</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>QUAM</span> (\n    <span class='primary'>cras</span>,\n    <span class='normal'>sed</span>,\n    <span class='foreign'>#magna!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>cras</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>QUAM</i>.</li>\n    <li>Le champ <i>sed</i> était déjà un simple attribut de l'entité <i>QUAM</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>VITAE</i> à partir de l'entité <i>SODALES</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SODALES</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>convallis</span>,\n    <span class='normal'>ipsum</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>convallis</i> et <i>ipsum</i> étaient déjà de simples attributs de l'entité <i>SODALES</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SUSCIPIT</span> (\n    <span class='primary'>orci</span>,\n    <span class='normal'>lorem</span>,\n    <span class='foreign'>#magna!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>orci</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ <i>lorem</i> était déjà un simple attribut de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>RHONCUS</i> à partir de l'entité <i>TRISTIS</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>TRISTIS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='foreign'>#fermentum!</span>,\n    <span class='normal'>type!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>vestibulum</i> était déjà un simple attribut de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ à saisie obligatoire <i>fermentum</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>ELIT</i> à partir de l'entité <i>CONSEQUAT</i> en perdant son caractère identifiant.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#posuere</span>,\n    <span class='foreign primary'>#magna</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_mld.mcd",
    "content": "%%mocodo\n:\nSUSCIPIT: orci, lorem, #magna > TRISTIS > magna\n:::::\nSODALES: #magna > TRISTIS > magna, convallis, ipsum\n:::\nQUAM: cras, sed, #magna > SODALES > magna\n:\n\n\n:\nCONSEQUAT: fermentum, dederit\n:::\nTRISTIS: magna, vestibulum, #fermentum > CONSEQUAT > fermentum, type\n:\nNEC: #magna > TRISTIS > magna, pulvinar, audis, #gravida > CURABITUR > gravida\n:::\nCURABITUR: gravida, amor\n:\n\n\n:\nDIGNISSIM: tellus, terra\n:\nALIQUET: #magna > TRISTIS > magna, _#tellus > DIGNISSIM > tellus\n:::\nLACUS: #magna > TRISTIS > magna, tempor, fugit\n:\nULTRICES: #posuere > LIBERO > posuere, _#magna > LACUS > magna\n:\nLIBERO: posuere, lacrima\n:\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_mld.md",
    "content": "- **ALIQUET** (<u>_#magna_</u>, <u>_#tellus_</u>)\n  - Le champ _magna_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _TRISTIS_.\n  - Le champ _tellus_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _DIGNISSIM_.\n\n- **CONSEQUAT** (<u>fermentum</u>, dederit)\n  - Le champ _fermentum_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CONSEQUAT_.\n  - Le champ _dederit_ était déjà un simple attribut de l'entité _CONSEQUAT_.\n\n- **CURABITUR** (<u>gravida</u>, amor)\n  - Le champ _gravida_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CURABITUR_.\n  - Le champ _amor_ était déjà un simple attribut de l'entité _CURABITUR_.\n\n- **DIGNISSIM** (<u>tellus</u>, terra)\n  - Le champ _tellus_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _DIGNISSIM_.\n  - Le champ _terra_ était déjà un simple attribut de l'entité _DIGNISSIM_.\n\n- **LACUS** (<u>_#magna_</u>, tempor, fugit)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _tempor_ et _fugit_ étaient déjà de simples attributs de l'entité _LACUS_.\n\n- **LIBERO** (<u>posuere</u>, lacrima)\n  - Le champ _posuere_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _LIBERO_.\n  - Le champ _lacrima_ était déjà un simple attribut de l'entité _LIBERO_.\n\n- **NEC** (<u>_#magna_</u>, pulvinar, audis, _#gravida!_)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _pulvinar_ et _audis_ étaient déjà de simples attributs de l'entité _NEC_.\n  - Le champ à saisie obligatoire _gravida_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _MOLLIS_ à partir de l'entité _CURABITUR_ en perdant son caractère identifiant.\n\n- **QUAM** (<u>cras</u>, sed, _#magna!_)\n  - Le champ _cras_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _QUAM_.\n  - Le champ _sed_ était déjà un simple attribut de l'entité _QUAM_.\n  - Le champ à saisie obligatoire _magna_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _VITAE_ à partir de l'entité _SODALES_ en perdant son caractère identifiant.\n\n- **SODALES** (<u>_#magna_</u>, convallis, ipsum)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _convallis_ et _ipsum_ étaient déjà de simples attributs de l'entité _SODALES_.\n\n- **SUSCIPIT** (<u>orci</u>, lorem, _#magna!_)\n  - Le champ _orci_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _SUSCIPIT_.\n  - Le champ _lorem_ était déjà un simple attribut de l'entité _SUSCIPIT_.\n  - Le champ à saisie obligatoire _magna_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _RHONCUS_ à partir de l'entité _TRISTIS_ en perdant son caractère identifiant.\n\n- **TRISTIS** (<u>magna</u>, vestibulum, _#fermentum!_, type!)\n  - Le champ _magna_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _TRISTIS_.\n  - Le champ _vestibulum_ était déjà un simple attribut de l'entité _TRISTIS_.\n  - Le champ à saisie obligatoire _fermentum_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _ELIT_ à partir de l'entité _CONSEQUAT_ en perdant son caractère identifiant.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- **ULTRICES** (<u>_#posuere_</u>, <u>_#magna_</u>)\n  - Le champ _posuere_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LIBERO_.\n  - Le champ _magna_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LACUS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{ALIQUET} (\\foreign{\\prim{magna}}, \\foreign{\\prim{tellus}})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{tellus} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{DIGNISSIM}.\n  \\end{itemize}\n\n  \\item \\relat{CONSEQUAT} (\\prim{fermentum}, \\attr{dederit})\n  \\begin{itemize}\n    \\item Le champ \\emph{fermentum} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONSEQUAT}.\n    \\item Le champ \\emph{dederit} était déjà un simple attribut de l'entité \\emph{CONSEQUAT}.\n  \\end{itemize}\n\n  \\item \\relat{CURABITUR} (\\prim{gravida}, \\attr{amor})\n  \\begin{itemize}\n    \\item Le champ \\emph{gravida} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CURABITUR}.\n    \\item Le champ \\emph{amor} était déjà un simple attribut de l'entité \\emph{CURABITUR}.\n  \\end{itemize}\n\n  \\item \\relat{DIGNISSIM} (\\prim{tellus}, \\attr{terra})\n  \\begin{itemize}\n    \\item Le champ \\emph{tellus} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{DIGNISSIM}.\n    \\item Le champ \\emph{terra} était déjà un simple attribut de l'entité \\emph{DIGNISSIM}.\n  \\end{itemize}\n\n  \\item \\relat{LACUS} (\\foreign{\\prim{magna}}, \\attr{tempor}, \\attr{fugit})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{tempor} et \\emph{fugit} étaient déjà de simples attributs de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n  \\item \\relat{LIBERO} (\\prim{posuere}, \\attr{lacrima})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{lacrima} était déjà un simple attribut de l'entité \\emph{LIBERO}.\n  \\end{itemize}\n\n  \\item \\relat{NEC} (\\foreign{\\prim{magna}}, \\attr{pulvinar}, \\attr{audis}, \\foreign{gravida!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{pulvinar} et \\emph{audis} étaient déjà de simples attributs de l'entité \\emph{NEC}.\n    \\item Le champ à saisie obligatoire \\emph{gravida} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{MOLLIS} à partir de l'entité \\emph{CURABITUR} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{QUAM} (\\prim{cras}, \\attr{sed}, \\foreign{magna!})\n  \\begin{itemize}\n    \\item Le champ \\emph{cras} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{QUAM}.\n    \\item Le champ \\emph{sed} était déjà un simple attribut de l'entité \\emph{QUAM}.\n    \\item Le champ à saisie obligatoire \\emph{magna} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{VITAE} à partir de l'entité \\emph{SODALES} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{SODALES} (\\foreign{\\prim{magna}}, \\attr{convallis}, \\attr{ipsum})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{convallis} et \\emph{ipsum} étaient déjà de simples attributs de l'entité \\emph{SODALES}.\n  \\end{itemize}\n\n  \\item \\relat{SUSCIPIT} (\\prim{orci}, \\attr{lorem}, \\foreign{magna!})\n  \\begin{itemize}\n    \\item Le champ \\emph{orci} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ \\emph{lorem} était déjà un simple attribut de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ à saisie obligatoire \\emph{magna} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{RHONCUS} à partir de l'entité \\emph{TRISTIS} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{TRISTIS} (\\prim{magna}, \\attr{vestibulum}, \\foreign{fermentum!}, \\attr{type!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{vestibulum} était déjà un simple attribut de l'entité \\emph{TRISTIS}.\n    \\item Le champ à saisie obligatoire \\emph{fermentum} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{ELIT} à partir de l'entité \\emph{CONSEQUAT} en perdant son caractère identifiant.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{posuere}}, \\foreign{\\prim{magna}})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_1_mld.txt",
    "content": "- ALIQUET (_#magna_, _#tellus_)\n  - Le champ « magna » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « TRISTIS ».\n  - Le champ « tellus » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « DIGNISSIM ».\n\n- CONSEQUAT (_fermentum_, dederit)\n  - Le champ « fermentum » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CONSEQUAT ».\n  - Le champ « dederit » était déjà un simple attribut de l'entité « CONSEQUAT ».\n\n- CURABITUR (_gravida_, amor)\n  - Le champ « gravida » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CURABITUR ».\n  - Le champ « amor » était déjà un simple attribut de l'entité « CURABITUR ».\n\n- DIGNISSIM (_tellus_, terra)\n  - Le champ « tellus » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « DIGNISSIM ».\n  - Le champ « terra » était déjà un simple attribut de l'entité « DIGNISSIM ».\n\n- LACUS (_#magna_, tempor, fugit)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « tempor » et « fugit » étaient déjà de simples attributs de l'entité « LACUS ».\n\n- LIBERO (_posuere_, lacrima)\n  - Le champ « posuere » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « LIBERO ».\n  - Le champ « lacrima » était déjà un simple attribut de l'entité « LIBERO ».\n\n- NEC (_#magna_, pulvinar, audis, #gravida!)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « pulvinar » et « audis » étaient déjà de simples attributs de l'entité « NEC ».\n  - Le champ à saisie obligatoire « gravida » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « MOLLIS » à partir de l'entité « CURABITUR » en perdant son caractère identifiant.\n\n- QUAM (_cras_, sed, #magna!)\n  - Le champ « cras » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « QUAM ».\n  - Le champ « sed » était déjà un simple attribut de l'entité « QUAM ».\n  - Le champ à saisie obligatoire « magna » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « VITAE » à partir de l'entité « SODALES » en perdant son caractère identifiant.\n\n- SODALES (_#magna_, convallis, ipsum)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « convallis » et « ipsum » étaient déjà de simples attributs de l'entité « SODALES ».\n\n- SUSCIPIT (_orci_, lorem, #magna!)\n  - Le champ « orci » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « SUSCIPIT ».\n  - Le champ « lorem » était déjà un simple attribut de l'entité « SUSCIPIT ».\n  - Le champ à saisie obligatoire « magna » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « RHONCUS » à partir de l'entité « TRISTIS » en perdant son caractère identifiant.\n\n- TRISTIS (_magna_, vestibulum, #fermentum!, type!)\n  - Le champ « magna » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « TRISTIS ».\n  - Le champ « vestibulum » était déjà un simple attribut de l'entité « TRISTIS ».\n  - Le champ à saisie obligatoire « fermentum » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « ELIT » à partir de l'entité « CONSEQUAT » en perdant son caractère identifiant.\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- ULTRICES (_#posuere_, _#magna_)\n  - Le champ « posuere » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LIBERO ».\n  - Le champ « magna » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LACUS ».\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nALIQUET\tmagna\t!\t\tunsourced_primary_foreign_key\tTrue\tTRISTIS\t\tALIQUET\t\t\nALIQUET\ttellus\t!\t\tprimary_foreign_key\tTrue\tDIGNISSIM\tDIGNISSIM\tALIQUET\t\t\nALIQUET\ttype\t!\t\tdeleted_parent_discriminator_XT\tFalse\tTRISTIS\t\tALIQUET\tUNSIGNED_INT_PLACEHOLDER\t\nCONSEQUAT\tfermentum\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONSEQUAT\tdederit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCURABITUR\tgravida\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCURABITUR\tamor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nDIGNISSIM\ttellus\t!\t\tprimary_key\tTrue\t\t\t\t\t\nDIGNISSIM\tterra\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nLACUS\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nLACUS\tfermentum\t!\t\tdeleted_parent_foreign_key\tFalse\tTRISTIS\tCONSEQUAT\tXT\t\t\nLACUS\ttempor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tfugit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLIBERO\tposuere\t!\t\tprimary_key\tTrue\t\t\t\t\t\nLIBERO\tlacrima\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nNEC\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nNEC\tfermentum\t!\t\tdeleted_parent_foreign_key\tFalse\tTRISTIS\tCONSEQUAT\tXT\t\t\nNEC\tpulvinar\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\taudis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tgravida\t!\t\tforeign_key\tFalse\tCURABITUR\tCURABITUR\tMOLLIS\t\t\nQUAM\tcras\t!\t\tprimary_key\tTrue\t\t\t\t\t\nQUAM\tsed\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nQUAM\tmagna\t!\t\tforeign_key\tFalse\tSODALES\tSODALES\tVITAE\t\t\nSODALES\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nSODALES\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nSODALES\tfermentum\t!\t\tdeleted_parent_foreign_key\tFalse\tTRISTIS\tCONSEQUAT\tXT\t\t\nSODALES\tconvallis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSODALES\tipsum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSUSCIPIT\torci\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSUSCIPIT\tlorem\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSUSCIPIT\tmagna\t!\t\tunsourced_foreign_key\tFalse\tTRISTIS\t\tRHONCUS\t\t\nSUSCIPIT\ttype\t!\t\tdeleted_parent_discriminator_XT\tFalse\tTRISTIS\t\tRHONCUS\tUNSIGNED_INT_PLACEHOLDER\t\nULTRICES\tposuere\t!\t\tprimary_foreign_key\tTrue\tLIBERO\tLIBERO\tULTRICES\t\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tLACUS\tULTRICES\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"DIGNISSIM\" -> \"ALIQUET\"\n  \"CONSEQUAT\" -> \"LACUS\"\n  \"CURABITUR\" -> \"NEC\"\n  \"CONSEQUAT\" -> \"NEC\"\n  \"SODALES\" -> \"QUAM\"\n  \"CONSEQUAT\" -> \"SODALES\"\n  \"LACUS\" -> \"ULTRICES\"\n  \"LIBERO\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_2_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>ALIQUET</span> (\n    <span class='primary'>magna</span>,\n    <span class='foreign primary'>#tellus</span>,\n    <span class='normal'>type!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. Il a migré par l'association de dépendance fonctionnelle <i>ALIQUET</i> à partir de l'entité <i>TRISTIS</i> (supprimée). <strong>Attention</strong> : aucune contrainte d'intégrité référentielle n'est plus assurée.</li>\n    <li>Le champ <i>tellus</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>DIGNISSIM</i>.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CONSEQUAT</span> (\n    <span class='primary'>fermentum</span>,\n    <span class='normal'>dederit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>fermentum</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONSEQUAT</i>.</li>\n    <li>Le champ <i>dederit</i> était déjà un simple attribut de l'entité <i>CONSEQUAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>CURABITUR</span> (\n    <span class='primary'>gravida</span>,\n    <span class='normal'>amor</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>gravida</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CURABITUR</i>.</li>\n    <li>Le champ <i>amor</i> était déjà un simple attribut de l'entité <i>CURABITUR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>DIGNISSIM</span> (\n    <span class='primary'>tellus</span>,\n    <span class='normal'>terra</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>tellus</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>DIGNISSIM</i>.</li>\n    <li>Le champ <i>terra</i> était déjà un simple attribut de l'entité <i>DIGNISSIM</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>LACUS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='foreign'>#fermentum!</span>,\n    <span class='normal'>tempor</span>,\n    <span class='normal'>fugit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ à saisie obligatoire <i>fermentum</i> est une clé étrangère. Il a migré à travers l'entité-mère <i>TRISTIS</i> (supprimée), et réfère maintenant directement à l'entité <i>CONSEQUAT</i>.</li>\n    <li>Les champs <i>tempor</i> et <i>fugit</i> étaient déjà de simples attributs de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>LIBERO</span> (\n    <span class='primary'>posuere</span>,\n    <span class='normal'>lacrima</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>lacrima</i> était déjà un simple attribut de l'entité <i>LIBERO</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>NEC</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='foreign'>#fermentum!</span>,\n    <span class='normal'>pulvinar</span>,\n    <span class='normal'>audis</span>,\n    <span class='foreign'>#gravida!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ à saisie obligatoire <i>fermentum</i> est une clé étrangère. Il a migré à travers l'entité-mère <i>TRISTIS</i> (supprimée), et réfère maintenant directement à l'entité <i>CONSEQUAT</i>.</li>\n    <li>Les champs <i>pulvinar</i> et <i>audis</i> étaient déjà de simples attributs de l'entité <i>NEC</i>.</li>\n    <li>Le champ à saisie obligatoire <i>gravida</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>MOLLIS</i> à partir de l'entité <i>CURABITUR</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>QUAM</span> (\n    <span class='primary'>cras</span>,\n    <span class='normal'>sed</span>,\n    <span class='foreign'>#magna!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>cras</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>QUAM</i>.</li>\n    <li>Le champ <i>sed</i> était déjà un simple attribut de l'entité <i>QUAM</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>VITAE</i> à partir de l'entité <i>SODALES</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SODALES</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='foreign'>#fermentum!</span>,\n    <span class='normal'>convallis</span>,\n    <span class='normal'>ipsum</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ à saisie obligatoire <i>fermentum</i> est une clé étrangère. Il a migré à travers l'entité-mère <i>TRISTIS</i> (supprimée), et réfère maintenant directement à l'entité <i>CONSEQUAT</i>.</li>\n    <li>Les champs <i>convallis</i> et <i>ipsum</i> étaient déjà de simples attributs de l'entité <i>SODALES</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SUSCIPIT</span> (\n    <span class='primary'>orci</span>,\n    <span class='normal'>lorem</span>,\n    <span class='normal'>magna!</span>,\n    <span class='normal'>type!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>orci</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ <i>lorem</i> était déjà un simple attribut de l'entité <i>SUSCIPIT</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna</i> a migré par l'association de dépendance fonctionnelle <i>RHONCUS</i> à partir de l'entité <i>TRISTIS</i> (supprimée). <strong>Attention</strong> : aucune contrainte d'intégrité référentielle n'est plus assurée.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#posuere</span>,\n    <span class='foreign primary'>#magna</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>posuere</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LIBERO</i>.</li>\n    <li>Le champ <i>magna</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_mld.mcd",
    "content": "%%mocodo\n:\nSUSCIPIT: orci, lorem, magna, type\n:::\nSODALES: magna, vestibulum, #fermentum > CONSEQUAT > fermentum, convallis, ipsum\n:::\nQUAM: cras, sed, #magna > SODALES > magna\n:\n\n\n:\nCONSEQUAT: fermentum, dederit\n:::\nNEC: magna, vestibulum, #fermentum > CONSEQUAT > fermentum, pulvinar, audis, #gravida > CURABITUR > gravida\n:::\nCURABITUR: gravida, amor\n:\n\n\n:\nDIGNISSIM: tellus, terra\n:\nALIQUET: magna, _#tellus > DIGNISSIM > tellus, type\n:\nLACUS: magna, vestibulum, #fermentum > CONSEQUAT > fermentum, tempor, fugit\n:\nULTRICES: #posuere > LIBERO > posuere, _#magna > LACUS > magna\n:\nLIBERO: posuere, lacrima\n:\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_mld.md",
    "content": "- **ALIQUET** (<u>magna</u>, <u>_#tellus_</u>, type!)\n  - Le champ _magna_ fait partie de la clé primaire de la table. Il a migré par l'association de dépendance fonctionnelle _ALIQUET_ à partir de l'entité _TRISTIS_ (supprimée). **Attention** : aucune contrainte d'intégrité référentielle n'est plus assurée.\n  - Le champ _tellus_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _DIGNISSIM_.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- **CONSEQUAT** (<u>fermentum</u>, dederit)\n  - Le champ _fermentum_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CONSEQUAT_.\n  - Le champ _dederit_ était déjà un simple attribut de l'entité _CONSEQUAT_.\n\n- **CURABITUR** (<u>gravida</u>, amor)\n  - Le champ _gravida_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _CURABITUR_.\n  - Le champ _amor_ était déjà un simple attribut de l'entité _CURABITUR_.\n\n- **DIGNISSIM** (<u>tellus</u>, terra)\n  - Le champ _tellus_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _DIGNISSIM_.\n  - Le champ _terra_ était déjà un simple attribut de l'entité _DIGNISSIM_.\n\n- **LACUS** (<u>magna</u>, vestibulum, _#fermentum!_, tempor, fugit)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ à saisie obligatoire _fermentum_ est une clé étrangère. Il a migré à travers l'entité-mère _TRISTIS_ (supprimée), et réfère maintenant directement à l'entité _CONSEQUAT_.\n  - Les champs _tempor_ et _fugit_ étaient déjà de simples attributs de l'entité _LACUS_.\n\n- **LIBERO** (<u>posuere</u>, lacrima)\n  - Le champ _posuere_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _LIBERO_.\n  - Le champ _lacrima_ était déjà un simple attribut de l'entité _LIBERO_.\n\n- **NEC** (<u>magna</u>, vestibulum, _#fermentum!_, pulvinar, audis, _#gravida!_)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ à saisie obligatoire _fermentum_ est une clé étrangère. Il a migré à travers l'entité-mère _TRISTIS_ (supprimée), et réfère maintenant directement à l'entité _CONSEQUAT_.\n  - Les champs _pulvinar_ et _audis_ étaient déjà de simples attributs de l'entité _NEC_.\n  - Le champ à saisie obligatoire _gravida_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _MOLLIS_ à partir de l'entité _CURABITUR_ en perdant son caractère identifiant.\n\n- **QUAM** (<u>cras</u>, sed, _#magna!_)\n  - Le champ _cras_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _QUAM_.\n  - Le champ _sed_ était déjà un simple attribut de l'entité _QUAM_.\n  - Le champ à saisie obligatoire _magna_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _VITAE_ à partir de l'entité _SODALES_ en perdant son caractère identifiant.\n\n- **SODALES** (<u>magna</u>, vestibulum, _#fermentum!_, convallis, ipsum)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ à saisie obligatoire _fermentum_ est une clé étrangère. Il a migré à travers l'entité-mère _TRISTIS_ (supprimée), et réfère maintenant directement à l'entité _CONSEQUAT_.\n  - Les champs _convallis_ et _ipsum_ étaient déjà de simples attributs de l'entité _SODALES_.\n\n- **SUSCIPIT** (<u>orci</u>, lorem, magna!, type!)\n  - Le champ _orci_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _SUSCIPIT_.\n  - Le champ _lorem_ était déjà un simple attribut de l'entité _SUSCIPIT_.\n  - Le champ à saisie obligatoire _magna_ a migré par l'association de dépendance fonctionnelle _RHONCUS_ à partir de l'entité _TRISTIS_ (supprimée). **Attention** : aucune contrainte d'intégrité référentielle n'est plus assurée.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- **ULTRICES** (<u>_#posuere_</u>, <u>_#magna_</u>)\n  - Le champ _posuere_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LIBERO_.\n  - Le champ _magna_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LACUS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{ALIQUET} (\\prim{magna}, \\foreign{\\prim{tellus}}, \\attr{type!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. Il a migré par l'association de dépendance fonctionnelle \\emph{ALIQUET} à partir de l'entité \\emph{TRISTIS} (supprimée). \\paragraph{Attention} : aucune contrainte d'intégrité référentielle n'est plus assurée.\n    \\item Le champ \\emph{tellus} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{DIGNISSIM}.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  \\end{itemize}\n\n  \\item \\relat{CONSEQUAT} (\\prim{fermentum}, \\attr{dederit})\n  \\begin{itemize}\n    \\item Le champ \\emph{fermentum} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONSEQUAT}.\n    \\item Le champ \\emph{dederit} était déjà un simple attribut de l'entité \\emph{CONSEQUAT}.\n  \\end{itemize}\n\n  \\item \\relat{CURABITUR} (\\prim{gravida}, \\attr{amor})\n  \\begin{itemize}\n    \\item Le champ \\emph{gravida} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CURABITUR}.\n    \\item Le champ \\emph{amor} était déjà un simple attribut de l'entité \\emph{CURABITUR}.\n  \\end{itemize}\n\n  \\item \\relat{DIGNISSIM} (\\prim{tellus}, \\attr{terra})\n  \\begin{itemize}\n    \\item Le champ \\emph{tellus} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{DIGNISSIM}.\n    \\item Le champ \\emph{terra} était déjà un simple attribut de l'entité \\emph{DIGNISSIM}.\n  \\end{itemize}\n\n  \\item \\relat{LACUS} (\\prim{magna}, \\attr{vestibulum}, \\foreign{fermentum!}, \\attr{tempor}, \\attr{fugit})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ à saisie obligatoire \\emph{fermentum} est une clé étrangère. Il a migré à travers l'entité-mère \\emph{TRISTIS} (supprimée), et réfère maintenant directement à l'entité \\emph{CONSEQUAT}.\n    \\item Les champs \\emph{tempor} et \\emph{fugit} étaient déjà de simples attributs de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n  \\item \\relat{LIBERO} (\\prim{posuere}, \\attr{lacrima})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{lacrima} était déjà un simple attribut de l'entité \\emph{LIBERO}.\n  \\end{itemize}\n\n  \\item \\relat{NEC} (\\prim{magna}, \\attr{vestibulum}, \\foreign{fermentum!}, \\attr{pulvinar}, \\attr{audis}, \\foreign{gravida!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ à saisie obligatoire \\emph{fermentum} est une clé étrangère. Il a migré à travers l'entité-mère \\emph{TRISTIS} (supprimée), et réfère maintenant directement à l'entité \\emph{CONSEQUAT}.\n    \\item Les champs \\emph{pulvinar} et \\emph{audis} étaient déjà de simples attributs de l'entité \\emph{NEC}.\n    \\item Le champ à saisie obligatoire \\emph{gravida} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{MOLLIS} à partir de l'entité \\emph{CURABITUR} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{QUAM} (\\prim{cras}, \\attr{sed}, \\foreign{magna!})\n  \\begin{itemize}\n    \\item Le champ \\emph{cras} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{QUAM}.\n    \\item Le champ \\emph{sed} était déjà un simple attribut de l'entité \\emph{QUAM}.\n    \\item Le champ à saisie obligatoire \\emph{magna} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{VITAE} à partir de l'entité \\emph{SODALES} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{SODALES} (\\prim{magna}, \\attr{vestibulum}, \\foreign{fermentum!}, \\attr{convallis}, \\attr{ipsum})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ à saisie obligatoire \\emph{fermentum} est une clé étrangère. Il a migré à travers l'entité-mère \\emph{TRISTIS} (supprimée), et réfère maintenant directement à l'entité \\emph{CONSEQUAT}.\n    \\item Les champs \\emph{convallis} et \\emph{ipsum} étaient déjà de simples attributs de l'entité \\emph{SODALES}.\n  \\end{itemize}\n\n  \\item \\relat{SUSCIPIT} (\\prim{orci}, \\attr{lorem}, \\attr{magna!}, \\attr{type!})\n  \\begin{itemize}\n    \\item Le champ \\emph{orci} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ \\emph{lorem} était déjà un simple attribut de l'entité \\emph{SUSCIPIT}.\n    \\item Le champ à saisie obligatoire \\emph{magna} a migré par l'association de dépendance fonctionnelle \\emph{RHONCUS} à partir de l'entité \\emph{TRISTIS} (supprimée). \\paragraph{Attention} : aucune contrainte d'intégrité référentielle n'est plus assurée.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{posuere}}, \\foreign{\\prim{magna}})\n  \\begin{itemize}\n    \\item Le champ \\emph{posuere} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LIBERO}.\n    \\item Le champ \\emph{magna} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_2_mld.txt",
    "content": "- ALIQUET (_magna_, _#tellus_, type!)\n  - Le champ « magna » fait partie de la clé primaire de la table. Il a migré par l'association de dépendance fonctionnelle « ALIQUET » à partir de l'entité « TRISTIS » (supprimée). Attention : aucune contrainte d'intégrité référentielle n'est plus assurée.\n  - Le champ « tellus » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « DIGNISSIM ».\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- CONSEQUAT (_fermentum_, dederit)\n  - Le champ « fermentum » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CONSEQUAT ».\n  - Le champ « dederit » était déjà un simple attribut de l'entité « CONSEQUAT ».\n\n- CURABITUR (_gravida_, amor)\n  - Le champ « gravida » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « CURABITUR ».\n  - Le champ « amor » était déjà un simple attribut de l'entité « CURABITUR ».\n\n- DIGNISSIM (_tellus_, terra)\n  - Le champ « tellus » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « DIGNISSIM ».\n  - Le champ « terra » était déjà un simple attribut de l'entité « DIGNISSIM ».\n\n- LACUS (_magna_, vestibulum, #fermentum!, tempor, fugit)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ à saisie obligatoire « fermentum » est une clé étrangère. Il a migré à travers l'entité-mère « TRISTIS » (supprimée), et réfère maintenant directement à l'entité « CONSEQUAT ».\n  - Les champs « tempor » et « fugit » étaient déjà de simples attributs de l'entité « LACUS ».\n\n- LIBERO (_posuere_, lacrima)\n  - Le champ « posuere » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « LIBERO ».\n  - Le champ « lacrima » était déjà un simple attribut de l'entité « LIBERO ».\n\n- NEC (_magna_, vestibulum, #fermentum!, pulvinar, audis, #gravida!)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ à saisie obligatoire « fermentum » est une clé étrangère. Il a migré à travers l'entité-mère « TRISTIS » (supprimée), et réfère maintenant directement à l'entité « CONSEQUAT ».\n  - Les champs « pulvinar » et « audis » étaient déjà de simples attributs de l'entité « NEC ».\n  - Le champ à saisie obligatoire « gravida » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « MOLLIS » à partir de l'entité « CURABITUR » en perdant son caractère identifiant.\n\n- QUAM (_cras_, sed, #magna!)\n  - Le champ « cras » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « QUAM ».\n  - Le champ « sed » était déjà un simple attribut de l'entité « QUAM ».\n  - Le champ à saisie obligatoire « magna » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « VITAE » à partir de l'entité « SODALES » en perdant son caractère identifiant.\n\n- SODALES (_magna_, vestibulum, #fermentum!, convallis, ipsum)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ à saisie obligatoire « fermentum » est une clé étrangère. Il a migré à travers l'entité-mère « TRISTIS » (supprimée), et réfère maintenant directement à l'entité « CONSEQUAT ».\n  - Les champs « convallis » et « ipsum » étaient déjà de simples attributs de l'entité « SODALES ».\n\n- SUSCIPIT (_orci_, lorem, magna!, type!)\n  - Le champ « orci » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « SUSCIPIT ».\n  - Le champ « lorem » était déjà un simple attribut de l'entité « SUSCIPIT ».\n  - Le champ à saisie obligatoire « magna » a migré par l'association de dépendance fonctionnelle « RHONCUS » à partir de l'entité « TRISTIS » (supprimée). Attention : aucune contrainte d'intégrité référentielle n'est plus assurée.\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- ULTRICES (_#posuere_, _#magna_)\n  - Le champ « posuere » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LIBERO ».\n  - Le champ « magna » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LACUS ».\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nTRISTIS\tmagna\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTRISTIS\tvestibulum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTRISTIS\ttype\t!\t\tdeleted_child_discriminator_XT\tFalse\t\t\tXT\tUNSIGNED_INT_PLACEHOLDER\t\nTRISTIS\tconvallis\t?\t\tdeleted_child_attribute\tFalse\tSODALES\t\tXT\t\t\nTRISTIS\tipsum\t?\t\tdeleted_child_attribute\tFalse\tSODALES\t\tXT\t\t\nTRISTIS\tpulvinar\t?\t\tdeleted_child_attribute\tFalse\tNEC\t\tXT\t\t\nTRISTIS\taudis\t?\t\tdeleted_child_attribute\tFalse\tNEC\t\tXT\t\t\nTRISTIS\tmagna\t?\t\tdeleted_child_foreign_key\tFalse\tNEC\tTRISTIS\tXT\t\tvia_mollis\nTRISTIS\tmagna\t?\t\tdeleted_child_foreign_key\tFalse\tNEC\tTRISTIS\tXT\t\tvia_vitae\nTRISTIS\ttempor\t?\t\tdeleted_child_attribute\tFalse\tLACUS\t\tXT\t\t\nTRISTIS\tfugit\t?\t\tdeleted_child_attribute\tFalse\tLACUS\t\tXT\t\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tSODALES\tTRISTIS\tULTRICES\t\tsodales\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tTRISTIS\tULTRICES\t\tlacus\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"TRISTIS\" -> \"TRISTIS\"\n  \"TRISTIS\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_3_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>TRISTIS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='normal'>type!</span>,\n    <span class='normal'>convallis?</span>,\n    <span class='normal'>ipsum?</span>,\n    <span class='normal'>pulvinar?</span>,\n    <span class='normal'>audis?</span>,\n    <span class='foreign'>#magna via_mollis?</span>,\n    <span class='foreign'>#magna via_vitae?</span>,\n    <span class='normal'>tempor?</span>,\n    <span class='normal'>fugit?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>vestibulum</i> était déjà un simple attribut de l'entité <i>TRISTIS</i>.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n    <li>Le champ à saisie facultative <i>convallis</i> a migré à partir de l'entité-fille <i>SODALES</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>ipsum</i> a migré à partir de l'entité-fille <i>SODALES</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>pulvinar</i> a migré à partir de l'entité-fille <i>NEC</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>audis</i> a migré à partir de l'entité-fille <i>NEC</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>magna via_mollis</i> est une clé étrangère. Il a migré à partir de l'entité-fille <i>NEC</i> (supprimée) dans laquelle il avait déjà migré à partir de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ à saisie facultative <i>magna via_vitae</i> est une clé étrangère. Il a migré à partir de l'entité-fille <i>NEC</i> (supprimée) dans laquelle il avait déjà migré à partir de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ à saisie facultative <i>tempor</i> a migré à partir de l'entité-fille <i>LACUS</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>fugit</i> a migré à partir de l'entité-fille <i>LACUS</i> (supprimée).</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#magna sodales</span>,\n    <span class='foreign primary'>#magna lacus</span>\n  )</summary>\n  <ul>\n    <li>Les champs <i>magna sodales</i> et <i>magna lacus</i> constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité <i>TRISTIS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_mld.mcd",
    "content": ":::\nTRISTIS: magna, vestibulum, type, convallis, ipsum, pulvinar, audis, #magna via_mollis > TRISTIS > magna, #magna via_vitae > TRISTIS > magna, tempor, fugit\n:\n\n\n:\nULTRICES: #magna sodales > TRISTIS > magna, _#magna lacus > TRISTIS > magna\n:::\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_mld.md",
    "content": "- **TRISTIS** (<u>magna</u>, vestibulum, type!, convallis?, ipsum?, pulvinar?, audis?, _#magna via_mollis?_, _#magna via_vitae?_, tempor?, fugit?)\n  - Le champ _magna_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _TRISTIS_.\n  - Le champ _vestibulum_ était déjà un simple attribut de l'entité _TRISTIS_.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  - Le champ à saisie facultative _convallis_ a migré à partir de l'entité-fille _SODALES_ (supprimée).\n  - Le champ à saisie facultative _ipsum_ a migré à partir de l'entité-fille _SODALES_ (supprimée).\n  - Le champ à saisie facultative _pulvinar_ a migré à partir de l'entité-fille _NEC_ (supprimée).\n  - Le champ à saisie facultative _audis_ a migré à partir de l'entité-fille _NEC_ (supprimée).\n  - Le champ à saisie facultative _magna via_mollis_ est une clé étrangère. Il a migré à partir de l'entité-fille _NEC_ (supprimée) dans laquelle il avait déjà migré à partir de l'entité _TRISTIS_.\n  - Le champ à saisie facultative _magna via_vitae_ est une clé étrangère. Il a migré à partir de l'entité-fille _NEC_ (supprimée) dans laquelle il avait déjà migré à partir de l'entité _TRISTIS_.\n  - Le champ à saisie facultative _tempor_ a migré à partir de l'entité-fille _LACUS_ (supprimée).\n  - Le champ à saisie facultative _fugit_ a migré à partir de l'entité-fille _LACUS_ (supprimée).\n\n- **ULTRICES** (<u>_#magna sodales_</u>, <u>_#magna lacus_</u>)\n  - Les champs _magna sodales_ et _magna lacus_ constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité _TRISTIS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{TRISTIS} (\\prim{magna}, \\attr{vestibulum}, \\attr{type!}, \\attr{convallis?}, \\attr{ipsum?}, \\attr{pulvinar?}, \\attr{audis?}, \\foreign{magna via\\_mollis?}, \\foreign{magna via\\_vitae?}, \\attr{tempor?}, \\attr{fugit?})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{vestibulum} était déjà un simple attribut de l'entité \\emph{TRISTIS}.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n    \\item Le champ à saisie facultative \\emph{convallis} a migré à partir de l'entité-fille \\emph{SODALES} (supprimée).\n    \\item Le champ à saisie facultative \\emph{ipsum} a migré à partir de l'entité-fille \\emph{SODALES} (supprimée).\n    \\item Le champ à saisie facultative \\emph{pulvinar} a migré à partir de l'entité-fille \\emph{NEC} (supprimée).\n    \\item Le champ à saisie facultative \\emph{audis} a migré à partir de l'entité-fille \\emph{NEC} (supprimée).\n    \\item Le champ à saisie facultative \\emph{magna via\\_mollis} est une clé étrangère. Il a migré à partir de l'entité-fille \\emph{NEC} (supprimée) dans laquelle il avait déjà migré à partir de l'entité \\emph{TRISTIS}.\n    \\item Le champ à saisie facultative \\emph{magna via\\_vitae} est une clé étrangère. Il a migré à partir de l'entité-fille \\emph{NEC} (supprimée) dans laquelle il avait déjà migré à partir de l'entité \\emph{TRISTIS}.\n    \\item Le champ à saisie facultative \\emph{tempor} a migré à partir de l'entité-fille \\emph{LACUS} (supprimée).\n    \\item Le champ à saisie facultative \\emph{fugit} a migré à partir de l'entité-fille \\emph{LACUS} (supprimée).\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{magna sodales}}, \\foreign{\\prim{magna lacus}})\n  \\begin{itemize}\n    \\item Les champs \\emph{magna sodales} et \\emph{magna lacus} constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité \\emph{TRISTIS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_3_mld.txt",
    "content": "- TRISTIS (_magna_, vestibulum, type!, convallis?, ipsum?, pulvinar?, audis?, #magna via_mollis?, #magna via_vitae?, tempor?, fugit?)\n  - Le champ « magna » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « TRISTIS ».\n  - Le champ « vestibulum » était déjà un simple attribut de l'entité « TRISTIS ».\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  - Le champ à saisie facultative « convallis » a migré à partir de l'entité-fille « SODALES » (supprimée).\n  - Le champ à saisie facultative « ipsum » a migré à partir de l'entité-fille « SODALES » (supprimée).\n  - Le champ à saisie facultative « pulvinar » a migré à partir de l'entité-fille « NEC » (supprimée).\n  - Le champ à saisie facultative « audis » a migré à partir de l'entité-fille « NEC » (supprimée).\n  - Le champ à saisie facultative « magna via_mollis » est une clé étrangère. Il a migré à partir de l'entité-fille « NEC » (supprimée) dans laquelle il avait déjà migré à partir de l'entité « TRISTIS ».\n  - Le champ à saisie facultative « magna via_vitae » est une clé étrangère. Il a migré à partir de l'entité-fille « NEC » (supprimée) dans laquelle il avait déjà migré à partir de l'entité « TRISTIS ».\n  - Le champ à saisie facultative « tempor » a migré à partir de l'entité-fille « LACUS » (supprimée).\n  - Le champ à saisie facultative « fugit » a migré à partir de l'entité-fille « LACUS » (supprimée).\n\n- ULTRICES (_#magna sodales_, _#magna lacus_)\n  - Les champs « magna sodales » et « magna lacus » constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité « TRISTIS ».\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nLACUS\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nLACUS\ttempor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tfugit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nNEC\tpulvinar\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\taudis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tforeign_key\tFalse\tLACUS\tLACUS\tMOLLIS\t\tvia_mollis\nNEC\tmagna\t!\t\tforeign_key\tFalse\tSODALES\tSODALES\tVITAE\t\tvia_vitae\nSODALES\tmagna\t!\t\tparent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nSODALES\tconvallis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSODALES\tipsum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTRISTIS\tmagna\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTRISTIS\tvestibulum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTRISTIS\ttype\t!\t\tdeleted_child_discriminator_XT\tFalse\t\t\tXT\tUNSIGNED_INT_PLACEHOLDER\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tSODALES\tSODALES\tULTRICES\t\tsodales\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tLACUS\tULTRICES\t\tlacus\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"TRISTIS\" -> \"LACUS\"\n  \"SODALES\" -> \"NEC\"\n  \"LACUS\" -> \"NEC\"\n  \"TRISTIS\" -> \"NEC\"\n  \"TRISTIS\" -> \"SODALES\"\n  \"LACUS\" -> \"ULTRICES\"\n  \"SODALES\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_4_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>LACUS</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>tempor</span>,\n    <span class='normal'>fugit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>tempor</i> et <i>fugit</i> étaient déjà de simples attributs de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>NEC</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>pulvinar</span>,\n    <span class='normal'>audis</span>,\n    <span class='foreign'>#magna via_mollis!</span>,\n    <span class='foreign'>#magna via_vitae!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>pulvinar</i> et <i>audis</i> étaient déjà de simples attributs de l'entité <i>NEC</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna via_mollis</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>MOLLIS</i> à partir de l'entité <i>LACUS</i> en perdant son caractère identifiant.</li>\n    <li>Le champ à saisie obligatoire <i>magna via_vitae</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>VITAE</i> à partir de l'entité <i>SODALES</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SODALES</span> (\n    <span class='foreign primary'>#magna</span>,\n    <span class='normal'>convallis</span>,\n    <span class='normal'>ipsum</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>TRISTIS</i>.</li>\n    <li>Les champs <i>convallis</i> et <i>ipsum</i> étaient déjà de simples attributs de l'entité <i>SODALES</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>TRISTIS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='normal'>type!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>TRISTIS</i>.</li>\n    <li>Le champ <i>vestibulum</i> était déjà un simple attribut de l'entité <i>TRISTIS</i>.</li>\n    <li>Un discriminateur à saisie obligatoire <i>type</i> est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#magna sodales</span>,\n    <span class='foreign primary'>#magna lacus</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna sodales</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>SODALES</i>.</li>\n    <li>Le champ <i>magna lacus</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_mld.mcd",
    "content": "%%mocodo\n:::::\nNEC: #magna > TRISTIS > magna, pulvinar, audis, #magna via_mollis > LACUS > magna, #magna via_vitae > SODALES > magna\n:\n\n\n:\nLACUS: #magna > TRISTIS > magna, tempor, fugit\n:::\nTRISTIS: magna, vestibulum, type\n:\n\n\n:::\nULTRICES: #magna sodales > SODALES > magna, _#magna lacus > LACUS > magna\n:\nSODALES: #magna > TRISTIS > magna, convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_mld.md",
    "content": "- **LACUS** (<u>_#magna_</u>, tempor, fugit)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _tempor_ et _fugit_ étaient déjà de simples attributs de l'entité _LACUS_.\n\n- **NEC** (<u>_#magna_</u>, pulvinar, audis, _#magna via_mollis!_, _#magna via_vitae!_)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _pulvinar_ et _audis_ étaient déjà de simples attributs de l'entité _NEC_.\n  - Le champ à saisie obligatoire _magna via_mollis_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _MOLLIS_ à partir de l'entité _LACUS_ en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire _magna via_vitae_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _VITAE_ à partir de l'entité _SODALES_ en perdant son caractère identifiant.\n\n- **SODALES** (<u>_#magna_</u>, convallis, ipsum)\n  - Le champ _magna_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _TRISTIS_.\n  - Les champs _convallis_ et _ipsum_ étaient déjà de simples attributs de l'entité _SODALES_.\n\n- **TRISTIS** (<u>magna</u>, vestibulum, type!)\n  - Le champ _magna_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _TRISTIS_.\n  - Le champ _vestibulum_ était déjà un simple attribut de l'entité _TRISTIS_.\n  - Un discriminateur à saisie obligatoire _type_ est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- **ULTRICES** (<u>_#magna sodales_</u>, <u>_#magna lacus_</u>)\n  - Le champ _magna sodales_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _SODALES_.\n  - Le champ _magna lacus_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LACUS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{LACUS} (\\foreign{\\prim{magna}}, \\attr{tempor}, \\attr{fugit})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{tempor} et \\emph{fugit} étaient déjà de simples attributs de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n  \\item \\relat{NEC} (\\foreign{\\prim{magna}}, \\attr{pulvinar}, \\attr{audis}, \\foreign{magna via\\_mollis!}, \\foreign{magna via\\_vitae!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{pulvinar} et \\emph{audis} étaient déjà de simples attributs de l'entité \\emph{NEC}.\n    \\item Le champ à saisie obligatoire \\emph{magna via\\_mollis} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{MOLLIS} à partir de l'entité \\emph{LACUS} en perdant son caractère identifiant.\n    \\item Le champ à saisie obligatoire \\emph{magna via\\_vitae} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{VITAE} à partir de l'entité \\emph{SODALES} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{SODALES} (\\foreign{\\prim{magna}}, \\attr{convallis}, \\attr{ipsum})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{TRISTIS}.\n    \\item Les champs \\emph{convallis} et \\emph{ipsum} étaient déjà de simples attributs de l'entité \\emph{SODALES}.\n  \\end{itemize}\n\n  \\item \\relat{TRISTIS} (\\prim{magna}, \\attr{vestibulum}, \\attr{type!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{TRISTIS}.\n    \\item Le champ \\emph{vestibulum} était déjà un simple attribut de l'entité \\emph{TRISTIS}.\n    \\item Un discriminateur à saisie obligatoire \\emph{type} est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{magna sodales}}, \\foreign{\\prim{magna lacus}})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna sodales} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{SODALES}.\n    \\item Le champ \\emph{magna lacus} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_4_mld.txt",
    "content": "- LACUS (_#magna_, tempor, fugit)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « tempor » et « fugit » étaient déjà de simples attributs de l'entité « LACUS ».\n\n- NEC (_#magna_, pulvinar, audis, #magna via_mollis!, #magna via_vitae!)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « pulvinar » et « audis » étaient déjà de simples attributs de l'entité « NEC ».\n  - Le champ à saisie obligatoire « magna via_mollis » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « MOLLIS » à partir de l'entité « LACUS » en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire « magna via_vitae » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « VITAE » à partir de l'entité « SODALES » en perdant son caractère identifiant.\n\n- SODALES (_#magna_, convallis, ipsum)\n  - Le champ « magna » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « TRISTIS ».\n  - Les champs « convallis » et « ipsum » étaient déjà de simples attributs de l'entité « SODALES ».\n\n- TRISTIS (_magna_, vestibulum, type!)\n  - Le champ « magna » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « TRISTIS ».\n  - Le champ « vestibulum » était déjà un simple attribut de l'entité « TRISTIS ».\n  - Un discriminateur à saisie obligatoire « type » est ajouté pour indiquer la nature de la spécialisation. Jamais vide, du fait de la contrainte de totalité.\n\n- ULTRICES (_#magna sodales_, _#magna lacus_)\n  - Le champ « magna sodales » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « SODALES ».\n  - Le champ « magna lacus » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LACUS ».\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nLACUS\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nLACUS\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nLACUS\ttempor\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nLACUS\tfugit\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nNEC\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nNEC\tpulvinar\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\taudis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nNEC\tmagna\t!\t\tforeign_key\tFalse\tLACUS\tLACUS\tMOLLIS\t\tvia_mollis\nNEC\tmagna\t!\t\tforeign_key\tFalse\tSODALES\tSODALES\tVITAE\t\tvia_vitae\nSODALES\tmagna\t!\t\tdeleted_parent_primary_key\tTrue\tTRISTIS\tTRISTIS\tXT\t\t\nSODALES\tvestibulum\t\t\tdeleted_parent_attribute\tFalse\tTRISTIS\t\tXT\t\t\nSODALES\tconvallis\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSODALES\tipsum\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tSODALES\tSODALES\tULTRICES\t\tsodales\nULTRICES\tmagna\t!\t\tprimary_foreign_key\tTrue\tLACUS\tLACUS\tULTRICES\t\tlacus\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"SODALES\" -> \"NEC\"\n  \"LACUS\" -> \"NEC\"\n  \"LACUS\" -> \"ULTRICES\"\n  \"SODALES\" -> \"ULTRICES\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"inheritance_5_mld.svg\"/></center><figcaption>MCD <i>inheritance</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>LACUS</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='normal'>tempor</span>,\n    <span class='normal'>fugit</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Les champs <i>tempor</i> et <i>fugit</i> étaient déjà de simples attributs de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>NEC</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='normal'>pulvinar</span>,\n    <span class='normal'>audis</span>,\n    <span class='foreign'>#magna via_mollis!</span>,\n    <span class='foreign'>#magna via_vitae!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Les champs <i>pulvinar</i> et <i>audis</i> étaient déjà de simples attributs de l'entité <i>NEC</i>.</li>\n    <li>Le champ à saisie obligatoire <i>magna via_mollis</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>MOLLIS</i> à partir de l'entité <i>LACUS</i> en perdant son caractère identifiant.</li>\n    <li>Le champ à saisie obligatoire <i>magna via_vitae</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>VITAE</i> à partir de l'entité <i>SODALES</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SODALES</span> (\n    <span class='primary'>magna</span>,\n    <span class='normal'>vestibulum</span>,\n    <span class='normal'>convallis</span>,\n    <span class='normal'>ipsum</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Le champ <i>vestibulum</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>TRISTIS</i> (supprimée).</li>\n    <li>Les champs <i>convallis</i> et <i>ipsum</i> étaient déjà de simples attributs de l'entité <i>SODALES</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>ULTRICES</span> (\n    <span class='foreign primary'>#magna sodales</span>,\n    <span class='foreign primary'>#magna lacus</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>magna sodales</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>SODALES</i>.</li>\n    <li>Le champ <i>magna lacus</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>LACUS</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_mld.mcd",
    "content": "%%mocodo\n:::::\nNEC: magna, vestibulum, pulvinar, audis, #magna via_mollis > LACUS > magna, #magna via_vitae > SODALES > magna\n:\n\n\n:\nLACUS: magna, vestibulum, tempor, fugit\n:::::\n\n\n:::\nULTRICES: #magna sodales > SODALES > magna, _#magna lacus > LACUS > magna\n:\nSODALES: magna, vestibulum, convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_mld.md",
    "content": "- **LACUS** (<u>magna</u>, vestibulum, tempor, fugit)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Les champs _tempor_ et _fugit_ étaient déjà de simples attributs de l'entité _LACUS_.\n\n- **NEC** (<u>magna</u>, vestibulum, pulvinar, audis, _#magna via_mollis!_, _#magna via_vitae!_)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Les champs _pulvinar_ et _audis_ étaient déjà de simples attributs de l'entité _NEC_.\n  - Le champ à saisie obligatoire _magna via_mollis_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _MOLLIS_ à partir de l'entité _LACUS_ en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire _magna via_vitae_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _VITAE_ à partir de l'entité _SODALES_ en perdant son caractère identifiant.\n\n- **SODALES** (<u>magna</u>, vestibulum, convallis, ipsum)\n  - Le champ _magna_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _TRISTIS_ (supprimée).\n  - Le champ _vestibulum_ est un simple attribut. Il était simple attribut de l'entité-mère _TRISTIS_ (supprimée).\n  - Les champs _convallis_ et _ipsum_ étaient déjà de simples attributs de l'entité _SODALES_.\n\n- **ULTRICES** (<u>_#magna sodales_</u>, <u>_#magna lacus_</u>)\n  - Le champ _magna sodales_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _SODALES_.\n  - Le champ _magna lacus_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _LACUS_.\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{LACUS} (\\prim{magna}, \\attr{vestibulum}, \\attr{tempor}, \\attr{fugit})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Les champs \\emph{tempor} et \\emph{fugit} étaient déjà de simples attributs de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n  \\item \\relat{NEC} (\\prim{magna}, \\attr{vestibulum}, \\attr{pulvinar}, \\attr{audis}, \\foreign{magna via\\_mollis!}, \\foreign{magna via\\_vitae!})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Les champs \\emph{pulvinar} et \\emph{audis} étaient déjà de simples attributs de l'entité \\emph{NEC}.\n    \\item Le champ à saisie obligatoire \\emph{magna via\\_mollis} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{MOLLIS} à partir de l'entité \\emph{LACUS} en perdant son caractère identifiant.\n    \\item Le champ à saisie obligatoire \\emph{magna via\\_vitae} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{VITAE} à partir de l'entité \\emph{SODALES} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{SODALES} (\\prim{magna}, \\attr{vestibulum}, \\attr{convallis}, \\attr{ipsum})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Le champ \\emph{vestibulum} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{TRISTIS} (supprimée).\n    \\item Les champs \\emph{convallis} et \\emph{ipsum} étaient déjà de simples attributs de l'entité \\emph{SODALES}.\n  \\end{itemize}\n\n  \\item \\relat{ULTRICES} (\\foreign{\\prim{magna sodales}}, \\foreign{\\prim{magna lacus}})\n  \\begin{itemize}\n    \\item Le champ \\emph{magna sodales} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{SODALES}.\n    \\item Le champ \\emph{magna lacus} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{LACUS}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance/mld/inheritance_5_mld.txt",
    "content": "- LACUS (_magna_, vestibulum, tempor, fugit)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Les champs « tempor » et « fugit » étaient déjà de simples attributs de l'entité « LACUS ».\n\n- NEC (_magna_, vestibulum, pulvinar, audis, #magna via_mollis!, #magna via_vitae!)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Les champs « pulvinar » et « audis » étaient déjà de simples attributs de l'entité « NEC ».\n  - Le champ à saisie obligatoire « magna via_mollis » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « MOLLIS » à partir de l'entité « LACUS » en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire « magna via_vitae » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « VITAE » à partir de l'entité « SODALES » en perdant son caractère identifiant.\n\n- SODALES (_magna_, vestibulum, convallis, ipsum)\n  - Le champ « magna » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « TRISTIS » (supprimée).\n  - Le champ « vestibulum » est un simple attribut. Il était simple attribut de l'entité-mère « TRISTIS » (supprimée).\n  - Les champs « convallis » et « ipsum » étaient déjà de simples attributs de l'entité « SODALES ».\n\n- ULTRICES (_#magna sodales_, _#magna lacus_)\n  - Le champ « magna sodales » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « SODALES ».\n  - Le champ « magna lacus » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « LACUS ».\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_create_df_arrows=across.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N> TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N> SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N> CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N> CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_drown.mcd",
    "content": "ENTITÉ 01_: at 01 1, at 01 2\nASSOC 11_, 1N ENTITÉ 05_, 11 ENTITÉ 01_\n:\n:\nENTITÉ 02_: at 02 1, at 02 2\nASSOC 12_, 11 ENTITÉ 03_, 1N ENTITÉ 02_\nENTITÉ 03_: at 03 1, at 03 2\n\nENTITÉ 04_: at 04 1, at 04 2\nASSOC 13_, 11 ENTITÉ 05_, 1N ENTITÉ 04_\nENTITÉ 05_: at 05 1, at 05 2\n/XT\\ ENTITÉ 05_ <- ENTITÉ 02_, ENTITÉ 06_, ENTITÉ 09_: type\nENTITÉ 06_: at 06 1, at 06 2\nASSOC 14_, 1N ENTITÉ 07_, 11 ENTITÉ 06_\nENTITÉ 07_: at 07 1, at 07 2\n\nENTITÉ 08_: at 08 1, at 08 2\nASSOC 15_, 1N ENTITÉ 05_, 1N ENTITÉ 08_\n:\n:\nENTITÉ 09_: at 09 1, at 09 2\nASSOC 16_, 1N ENTITÉ 10_, 1N ENTITÉ 09_\nENTITÉ 10_: at 10 1, at 10 2\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=2,weak.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, _11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES:\nDF, _11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, _11 ALIQUET, 1N TRISTIS\nALIQUET:\nDF, _11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=2.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, 11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES: id. ultrices\nDF, 11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, 11 ALIQUET, 1N TRISTIS\nALIQUET: id. aliquet\nDF, 11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_create_df_arrows=across.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N> TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N> SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N> CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N> CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_drown.mcd",
    "content": "ENTITÉ 01_: at 01 1, at 01 2\nASSOC 11_, 1N ENTITÉ 05_, 11 ENTITÉ 01_\n:\n:\nENTITÉ 02_: at 02 1, at 02 2\nASSOC 12_, 11 ENTITÉ 03_, 1N ENTITÉ 02_\nENTITÉ 03_: at 03 1, at 03 2\n\nENTITÉ 04_: at 04 1, at 04 2\nASSOC 13_, 11 ENTITÉ 05_, 1N ENTITÉ 04_\nENTITÉ 05_: at 05 1, at 05 2\n/XT\\ ENTITÉ 05_ -> ENTITÉ 02_, ENTITÉ 06_, ENTITÉ 09_: type\nENTITÉ 06_: at 06 1, at 06 2\nASSOC 14_, 1N ENTITÉ 07_, 11 ENTITÉ 06_\nENTITÉ 07_: at 07 1, at 07 2\n\nENTITÉ 08_: at 08 1, at 08 2\nASSOC 15_, 1N ENTITÉ 05_, 1N ENTITÉ 08_\n:\n:\nENTITÉ 09_: at 09 1, at 09 2\nASSOC 16_, 1N ENTITÉ 10_, 1N ENTITÉ 09_\nENTITÉ 10_: at 10 1, at 10 2\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=2,weak.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, _11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES:\nDF, _11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, _11 ALIQUET, 1N TRISTIS\nALIQUET:\nDF, _11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=2.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, 11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES: id. ultrices\nDF, 11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, 11 ALIQUET, 1N TRISTIS\nALIQUET: id. aliquet\nDF, 11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_create_df_arrows=across.mcd",
    "content": "SUSCIPIT: orci, lorem\nRHONCUS, 1N> TRISTIS, 11 SUSCIPIT\n:\n:\nSODALES: convallis, ipsum\nVITAE, 11 QUAM, 1N> SODALES\nQUAM: cras, sed\n\nCONSEQUAT: fermentum, dederit\nELIT, 11 TRISTIS, 1N> CONSEQUAT\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\nMOLLIS, 1N> CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n\nDIGNISSIM: tellus, terra\nALIQUET, 1N TRISTIS, 1N DIGNISSIM\n:\n:\nLACUS: tempor, fugit\nULTRICES, 1N LIBERO, 1N LACUS\nLIBERO: posuere, lacrima\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_drown.mcd",
    "content": "ENTITÉ 01_: at 01 1, at 01 2\nASSOC 11_, 1N ENTITÉ 05_, 11 ENTITÉ 01_\n:\n:\nENTITÉ 02_: at 02 1, at 02 2\nASSOC 12_, 11 ENTITÉ 03_, 1N ENTITÉ 02_\nENTITÉ 03_: at 03 1, at 03 2\n\nENTITÉ 04_: at 04 1, at 04 2\nASSOC 13_, 11 ENTITÉ 05_, 1N ENTITÉ 04_\nENTITÉ 05_: at 05 1, at 05 2\n/XT\\ ENTITÉ 05_ => ENTITÉ 02_, ENTITÉ 06_, ENTITÉ 09_: type\nENTITÉ 06_: at 06 1, at 06 2\nASSOC 14_, 1N ENTITÉ 07_, 11 ENTITÉ 06_\nENTITÉ 07_: at 07 1, at 07 2\n\nENTITÉ 08_: at 08 1, at 08 2\nASSOC 15_, 1N ENTITÉ 05_, 1N ENTITÉ 08_\n:\n:\nENTITÉ 09_: at 09 1, at 09 2\nASSOC 16_, 1N ENTITÉ 10_, 1N ENTITÉ 09_\nENTITÉ 10_: at 10 1, at 10 2\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=2,weak.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, _11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES:\nDF, _11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, _11 ALIQUET, 1N TRISTIS\nALIQUET:\nDF, _11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=2.mcd",
    "content": "LIBERO: posuere, lacrima\n:\n:\n:\n:\n:\n:\n\nDF, 11 ULTRICES, 1N LIBERO\n:\nMOLLIS, 1N CURABITUR, 11 NEC\nCURABITUR: gravida, amor\n:\n:\n:\n\nULTRICES: id. ultrices\nDF, 11 ULTRICES, 1N LACUS\nNEC: pulvinar, audis\nRHONCUS, 1N TRISTIS, 11 SUSCIPIT\nSUSCIPIT: orci, lorem\n:\n:\n\n:\nLACUS: tempor, fugit\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nDF, 11 ALIQUET, 1N TRISTIS\nALIQUET: id. aliquet\nDF, 11 ALIQUET, 1N DIGNISSIM\n\n:\n:\nSODALES: convallis, ipsum\nELIT, 11 TRISTIS, 1N CONSEQUAT\nCONSEQUAT: fermentum, dederit\n:\nDIGNISSIM: tellus, terra\n\n:\nQUAM: cras, sed\nVITAE, 11 QUAM, 1N SODALES\n:\n:\n:\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_2_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_create_df_arrows=across.mcd",
    "content": ":\nMOLLIS, 1N> [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N> [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_drown.mcd",
    "content": ":\nASSOC 5_, 1N [rôle 1] ENTITÉ 2_, 11 ENTITÉ 1_\nENTITÉ 1_: at 1 1, at 1 2\n:\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 3_ <- ENTITÉ 4_, ENTITÉ 1_, ENTITÉ 2_: type\nENTITÉ 3_: at 3 1, at 3 2\nASSOC 6_, 11 ENTITÉ 1_, 1N [rôle 1] ENTITÉ 4_\n\n:\nASSOC 7_, 1N [rôle 1] ENTITÉ 4_, 1N [rôle 2] ENTITÉ 2_\nENTITÉ 4_: at 4 1, at 4 2\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=2,weak.mcd",
    "content": ":\nDF, _11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES:\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, _11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=2.mcd",
    "content": ":\nDF, 11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES: id. ultrices\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS <- SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, 11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_3_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_create_df_arrows=across.mcd",
    "content": ":\nMOLLIS, 1N> [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N> [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_drown.mcd",
    "content": ":\nASSOC 5_, 1N [rôle 1] ENTITÉ 2_, 11 ENTITÉ 1_\nENTITÉ 1_: at 1 1, at 1 2\n:\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 3_ -> ENTITÉ 4_, ENTITÉ 1_, ENTITÉ 2_: type\nENTITÉ 3_: at 3 1, at 3 2\nASSOC 6_, 11 ENTITÉ 1_, 1N [rôle 1] ENTITÉ 4_\n\n:\nASSOC 7_, 1N [rôle 1] ENTITÉ 4_, 1N [rôle 2] ENTITÉ 2_\nENTITÉ 4_: at 4 1, at 4 2\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=2,weak.mcd",
    "content": ":\nDF, _11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES:\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, _11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=2.mcd",
    "content": ":\nDF, 11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES: id. ultrices\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS -> SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, 11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_4_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_create_df_arrows=across.mcd",
    "content": ":\nMOLLIS, 1N> [via_mollis] LACUS, 11 NEC\nNEC: pulvinar, audis\n:\n\nLACUS: tempor, fugit\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nTRISTIS: magna, vestibulum\nVITAE, 11 NEC, 1N> [via_vitae] SODALES\n\n:\nULTRICES, 1N [sodales] SODALES, 1N [lacus] LACUS\nSODALES: convallis, ipsum\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_drown.mcd",
    "content": ":\nASSOC 5_, 1N [rôle 1] ENTITÉ 2_, 11 ENTITÉ 1_\nENTITÉ 1_: at 1 1, at 1 2\n:\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 3_ => ENTITÉ 4_, ENTITÉ 1_, ENTITÉ 2_: type\nENTITÉ 3_: at 3 1, at 3 2\nASSOC 6_, 11 ENTITÉ 1_, 1N [rôle 1] ENTITÉ 4_\n\n:\nASSOC 7_, 1N [rôle 1] ENTITÉ 4_, 1N [rôle 2] ENTITÉ 2_\nENTITÉ 4_: at 4 1, at 4 2\n:\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=2,weak.mcd",
    "content": ":\nDF, _11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES:\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, _11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=2.mcd",
    "content": ":\nDF, 11 ULTRICES, 1N [sodales] SODALES\nSODALES: convallis, ipsum\nVITAE, 11 NEC, 1N [via_vitae] SODALES\n\nULTRICES: id. ultrices\nTRISTIS: magna, vestibulum\n/XT\\ TRISTIS => SODALES, NEC, LACUS: type\nNEC: pulvinar, audis\n\n:\nDF, 11 ULTRICES, 1N [lacus] LACUS\nLACUS: tempor, fugit\nMOLLIS, 1N [via_mollis] LACUS, 11 NEC\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance/rewritten/inheritance_5_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/_strong_child_0.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Class table inheritance: all entities are preserved\n\nDF, _11 CONTRAT, 1N VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR -> VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/_strong_child_1.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Single table inheritance: children are merged into the parent table\n\nDF, _11 CONTRAT, 1N VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR <- VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/_strong_child_2.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Concrete table inheritance: parent disappears\n\nDF, _11 CONTRAT, 1N VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR => VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_0_ddl.d2",
    "content": "\"CONTRAT\": { shape: sql_table\n  \"num prof\":                VARCHAR(42) {constraint: [PK; FK]}\n  \"date contrat\":            VARCHAR(42) {constraint: PK}\n  \"salaire horaire contrat\": VARCHAR(42) \n}\n\n\"PROFESSEUR\": { shape: sql_table\n  \"num prof\":       VARCHAR(42) {constraint: PK}\n  \"nom prof\":       VARCHAR(42) \n  \"prénom prof\":    VARCHAR(42) \n  \"téléphone prof\": VARCHAR(42) \n}\n\n\"SALARIÉ\": { shape: sql_table\n  \"num prof\":              VARCHAR(42) {constraint: [PK; FK]}\n  \"date embauche salarié\": VARCHAR(42) \n  \"échelon salarié\":       VARCHAR(42) \n  \"salaire salarié\":       VARCHAR(42) \n}\n\n\"VACATAIRE\": { shape: sql_table\n  \"num prof\":         VARCHAR(42) {constraint: [PK; FK]}\n  \"statut vacataire\": VARCHAR(42) \n}\n\n\"CONTRAT\".\"num prof\" -> \"VACATAIRE\".\"num prof\"\n\"SALARIÉ\".\"num prof\" -> \"PROFESSEUR\".\"num prof\"\n\"VACATAIRE\".\"num prof\" -> \"PROFESSEUR\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_0_ddl.dbml",
    "content": "Table \"CONTRAT\" {\n  \"num prof\"                VARCHAR(42) [NOT NULL]\n  \"date contrat\"            VARCHAR(42) [NOT NULL]\n  \"salaire horaire contrat\" VARCHAR(42)\n  Indexes {\n    (\"num prof\", \"date contrat\") [pk]\n  }\n}\n\nTable \"PROFESSEUR\" {\n  \"num prof\"       VARCHAR(42) [pk, NOT NULL]\n  \"nom prof\"       VARCHAR(42)\n  \"prénom prof\"    VARCHAR(42)\n  \"téléphone prof\" VARCHAR(42)\n}\n\nTable \"SALARIÉ\" {\n  \"num prof\"              VARCHAR(42) [pk, NOT NULL]\n  \"date embauche salarié\" VARCHAR(42)\n  \"échelon salarié\"       VARCHAR(42)\n  \"salaire salarié\"       VARCHAR(42)\n}\n\nTable \"VACATAIRE\" {\n  \"num prof\"         VARCHAR(42) [pk, NOT NULL]\n  \"statut vacataire\" VARCHAR(42)\n}\n\nRef:\"CONTRAT\".\"num prof\" > \"VACATAIRE\".\"num prof\"\nRef:\"SALARIÉ\".\"num prof\" > \"PROFESSEUR\".\"num prof\"\nRef:\"VACATAIRE\".\"num prof\" > \"PROFESSEUR\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_0_ddl.sql",
    "content": "CREATE TABLE CONTRAT (\n  PRIMARY KEY (num_prof, date_contrat),\n  num_prof                VARCHAR(8) NOT NULL,\n  date_contrat            DATE NOT NULL,\n  salaire_horaire_contrat VARCHAR(42)\n);\n\nCREATE TABLE PROFESSEUR (\n  PRIMARY KEY (num_prof),\n  num_prof       VARCHAR(8) NOT NULL,\n  nom_prof       VARCHAR(255),\n  prenom_prof    VARCHAR(255),\n  telephone_prof VARCHAR(20)\n);\n\nCREATE TABLE SALARIE (\n  PRIMARY KEY (num_prof),\n  num_prof              VARCHAR(8) NOT NULL,\n  date_embauche_salarie DATE,\n  echelon_salarie       VARCHAR(42),\n  salaire_salarie       VARCHAR(42)\n);\n\nCREATE TABLE VACATAIRE (\n  PRIMARY KEY (num_prof),\n  num_prof         VARCHAR(8) NOT NULL,\n  statut_vacataire VARCHAR(20)\n);\n\nALTER TABLE CONTRAT ADD FOREIGN KEY (num_prof) REFERENCES VACATAIRE (num_prof);\n\nALTER TABLE SALARIE ADD FOREIGN KEY (num_prof) REFERENCES PROFESSEUR (num_prof);\n\nALTER TABLE VACATAIRE ADD FOREIGN KEY (num_prof) REFERENCES PROFESSEUR (num_prof);\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_1_ddl.d2",
    "content": "\"CONTRAT\": { shape: sql_table\n  \"num prof\":                VARCHAR(42) {constraint: [PK; FK]}\n  \"date contrat\":            VARCHAR(42) {constraint: PK}\n  \"salaire horaire contrat\": VARCHAR(42) \n}\n\n\"PROFESSEUR\": { shape: sql_table\n  \"num prof\":              VARCHAR(42) {constraint: PK}\n  \"nom prof\":              VARCHAR(42) \n  \"prénom prof\":           VARCHAR(42) \n  \"téléphone prof\":        VARCHAR(42) \n  \"statut vacataire\":      VARCHAR(42) {constraint: \"NULL\"}\n  \"date embauche salarié\": VARCHAR(42) {constraint: \"NULL\"}\n  \"échelon salarié\":       VARCHAR(42) {constraint: \"NULL\"}\n  \"salaire salarié\":       VARCHAR(42) {constraint: \"NULL\"}\n}\n\n\"CONTRAT\".\"num prof\" -> \"PROFESSEUR\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_1_ddl.dbml",
    "content": "Table \"CONTRAT\" {\n  \"num prof\"                VARCHAR(42) [NOT NULL]\n  \"date contrat\"            VARCHAR(42) [NOT NULL]\n  \"salaire horaire contrat\" VARCHAR(42)\n  Indexes {\n    (\"num prof\", \"date contrat\") [pk]\n  }\n}\n\nTable \"PROFESSEUR\" {\n  \"num prof\"              VARCHAR(42) [pk, NOT NULL]\n  \"nom prof\"              VARCHAR(42)\n  \"prénom prof\"           VARCHAR(42)\n  \"téléphone prof\"        VARCHAR(42)\n  \"statut vacataire\"      VARCHAR(42) [\"NULL\"]\n  \"date embauche salarié\" VARCHAR(42) [\"NULL\"]\n  \"échelon salarié\"       VARCHAR(42) [\"NULL\"]\n  \"salaire salarié\"       VARCHAR(42) [\"NULL\"]\n}\n\nRef:\"CONTRAT\".\"num prof\" > \"PROFESSEUR\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_1_ddl.sql",
    "content": "CREATE TABLE CONTRAT (\n  PRIMARY KEY (num_prof, date_contrat),\n  num_prof                VARCHAR(8) NOT NULL,\n  date_contrat            DATE NOT NULL,\n  salaire_horaire_contrat VARCHAR(42)\n);\n\nCREATE TABLE PROFESSEUR (\n  PRIMARY KEY (num_prof),\n  num_prof              VARCHAR(8) NOT NULL,\n  nom_prof              VARCHAR(255),\n  prenom_prof           VARCHAR(255),\n  telephone_prof        VARCHAR(20),\n  statut_vacataire      VARCHAR(20) NULL,\n  date_embauche_salarie DATE NULL,\n  echelon_salarie       VARCHAR(42) NULL,\n  salaire_salarie       VARCHAR(42) NULL\n);\n\nALTER TABLE CONTRAT ADD FOREIGN KEY (num_prof) REFERENCES PROFESSEUR (num_prof);\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_2_ddl.d2",
    "content": "\"CONTRAT\": { shape: sql_table\n  \"num prof\":                VARCHAR(42) {constraint: [PK; FK]}\n  \"date contrat\":            VARCHAR(42) {constraint: PK}\n  \"salaire horaire contrat\": VARCHAR(42) \n}\n\n\"SALARIÉ\": { shape: sql_table\n  \"num prof\":              VARCHAR(42) {constraint: PK}\n  \"nom prof\":              VARCHAR(42) \n  \"prénom prof\":           VARCHAR(42) \n  \"téléphone prof\":        VARCHAR(42) \n  \"date embauche salarié\": VARCHAR(42) \n  \"échelon salarié\":       VARCHAR(42) \n  \"salaire salarié\":       VARCHAR(42) \n}\n\n\"VACATAIRE\": { shape: sql_table\n  \"num prof\":         VARCHAR(42) {constraint: PK}\n  \"nom prof\":         VARCHAR(42) \n  \"prénom prof\":      VARCHAR(42) \n  \"téléphone prof\":   VARCHAR(42) \n  \"statut vacataire\": VARCHAR(42) \n}\n\n\"CONTRAT\".\"num prof\" -> \"VACATAIRE\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_2_ddl.dbml",
    "content": "Table \"CONTRAT\" {\n  \"num prof\"                VARCHAR(42) [NOT NULL]\n  \"date contrat\"            VARCHAR(42) [NOT NULL]\n  \"salaire horaire contrat\" VARCHAR(42)\n  Indexes {\n    (\"num prof\", \"date contrat\") [pk]\n  }\n}\n\nTable \"SALARIÉ\" {\n  \"num prof\"              VARCHAR(42) [pk, NOT NULL]\n  \"nom prof\"              VARCHAR(42)\n  \"prénom prof\"           VARCHAR(42)\n  \"téléphone prof\"        VARCHAR(42)\n  \"date embauche salarié\" VARCHAR(42)\n  \"échelon salarié\"       VARCHAR(42)\n  \"salaire salarié\"       VARCHAR(42)\n}\n\nTable \"VACATAIRE\" {\n  \"num prof\"         VARCHAR(42) [pk, NOT NULL]\n  \"nom prof\"         VARCHAR(42)\n  \"prénom prof\"      VARCHAR(42)\n  \"téléphone prof\"   VARCHAR(42)\n  \"statut vacataire\" VARCHAR(42)\n}\n\nRef:\"CONTRAT\".\"num prof\" > \"VACATAIRE\".\"num prof\"\n"
  },
  {
    "path": "test/zoo/inheritance_weak/ddl/strong_child_2_ddl.sql",
    "content": "CREATE TABLE CONTRAT (\n  PRIMARY KEY (num_prof, date_contrat),\n  num_prof                VARCHAR(8) NOT NULL,\n  date_contrat            DATE NOT NULL,\n  salaire_horaire_contrat VARCHAR(42)\n);\n\nCREATE TABLE SALARIE (\n  PRIMARY KEY (num_prof),\n  num_prof              VARCHAR(8) NOT NULL,\n  nom_prof              VARCHAR(255),\n  prenom_prof           VARCHAR(255),\n  telephone_prof        VARCHAR(20),\n  date_embauche_salarie DATE,\n  echelon_salarie       VARCHAR(42),\n  salaire_salarie       VARCHAR(42)\n);\n\nCREATE TABLE VACATAIRE (\n  PRIMARY KEY (num_prof),\n  num_prof         VARCHAR(8) NOT NULL,\n  nom_prof         VARCHAR(255),\n  prenom_prof      VARCHAR(255),\n  telephone_prof   VARCHAR(20),\n  statut_vacataire VARCHAR(20)\n);\n\nALTER TABLE CONTRAT ADD FOREIGN KEY (num_prof) REFERENCES VACATAIRE (num_prof);\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"VACATAIRE\"]\n  2 [label=\"CONTRAT\",peripheries=2]\n\n  // Associative entities\n  7 [label=\"SALARIÉ\",shape=Mdiamond]\n  11 [label=\"PROFESSEUR\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"salaire\\nhoraire\\ncontrat\"]\n  9 [label=\"échelon\\nsalarié\"]\n  10 [label=\"salaire\\nsalarié\"]\n  13 [label=\"nom prof\"]\n  14 [label=\"prénom\\nprof\"]\n  15 [label=\"téléphone\\nprof\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>statut<br/>vacataire</u>>]\n  5 [label=<<u>date<br/>contrat</u>> style=\"dashed,filled\"]\n  8 [label=<<u>date<br/>embauche<br/>salarié</u>>]\n  12 [label=<<u>num prof</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 5\n  2 -- 6\n  3 -- 4\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  11 -- 12\n  11 -- 13\n  11 -- 14\n  11 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  3 -- 1\n  edge [headlabel=N]\n  2 -- 1\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_0_erd_chen.txt",
    "content": "[VACATAIRE] ==1== <<DF>>\n[[CONTRAT]] ==N== <<DF>>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >VACATAIRE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">statut vacataire</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONTRAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date contrat</td></tr>\n        <tr><td> </td><td align=\"left\">salaire horaire contrat</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SALARIÉ</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date embauche salarié</td></tr>\n        <tr><td> </td><td align=\"left\">échelon salarié</td></tr>\n        <tr><td> </td><td align=\"left\">salaire salarié</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PROFESSEUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num prof</td></tr>\n        <tr><td> </td><td align=\"left\">nom prof</td></tr>\n        <tr><td> </td><td align=\"left\">prénom prof</td></tr>\n        <tr><td> </td><td align=\"left\">téléphone prof</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_0_erd_crow.mmd",
    "content": "erDiagram\n  VACATAIRE {\n    TYPE statut_vacataire PK\n  }\n  CONTRAT {\n    TYPE date_contrat PK\n    TYPE salaire_horaire_contrat\n  }\n  SALARIE {\n    TYPE date_embauche_salarie PK\n    TYPE echelon_salarie\n    TYPE salaire_salarie\n  }\n  PROFESSEUR {\n    TYPE num_prof PK\n    TYPE nom_prof\n    TYPE prenom_prof\n    TYPE telephone_prof\n  }\n  CONTRAT }|..|| VACATAIRE: DF"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_0_uml.puml",
    "content": "@startuml \"inheritance_weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"CONTRAT\" \"1..*\" --* \"1\" \"VACATAIRE\"\n\nTable(\"VACATAIRE\") {\n    {field} + pk(statut vacataire)\n}\n\nTable(\"CONTRAT\") {\n    {field} + pk(date contrat)\n    {field} + salaire horaire contrat\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- SALARIÉ\nGENERALIZATION_0 -[dotted]- VACATAIRE\nPROFESSEUR <|-- SALARIÉ\nPROFESSEUR <|-- VACATAIRE\n\nTable(\"SALARIÉ\") {\n    {field} + pk(date embauche salarié)\n    {field} + échelon salarié\n    {field} + salaire salarié\n}\n\nTable(\"PROFESSEUR\") {\n    {field} + pk(num prof)\n    {field} + nom prof\n    {field} + prénom prof\n    {field} + téléphone prof\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"VACATAIRE\"]\n  2 [label=\"CONTRAT\",peripheries=2]\n\n  // Associative entities\n  7 [label=\"SALARIÉ\",shape=Mdiamond]\n  11 [label=\"PROFESSEUR\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"salaire\\nhoraire\\ncontrat\"]\n  9 [label=\"échelon\\nsalarié\"]\n  10 [label=\"salaire\\nsalarié\"]\n  13 [label=\"nom prof\"]\n  14 [label=\"prénom\\nprof\"]\n  15 [label=\"téléphone\\nprof\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>statut<br/>vacataire</u>>]\n  5 [label=<<u>date<br/>contrat</u>> style=\"dashed,filled\"]\n  8 [label=<<u>date<br/>embauche<br/>salarié</u>>]\n  12 [label=<<u>num prof</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 5\n  2 -- 6\n  3 -- 4\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  11 -- 12\n  11 -- 13\n  11 -- 14\n  11 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  3 -- 1\n  edge [headlabel=N]\n  2 -- 1\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_1_erd_chen.txt",
    "content": "[VACATAIRE] ==1== <<DF>>\n[[CONTRAT]] ==N== <<DF>>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_1_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >VACATAIRE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">statut vacataire</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONTRAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date contrat</td></tr>\n        <tr><td> </td><td align=\"left\">salaire horaire contrat</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SALARIÉ</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date embauche salarié</td></tr>\n        <tr><td> </td><td align=\"left\">échelon salarié</td></tr>\n        <tr><td> </td><td align=\"left\">salaire salarié</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PROFESSEUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num prof</td></tr>\n        <tr><td> </td><td align=\"left\">nom prof</td></tr>\n        <tr><td> </td><td align=\"left\">prénom prof</td></tr>\n        <tr><td> </td><td align=\"left\">téléphone prof</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_1_erd_crow.mmd",
    "content": "erDiagram\n  VACATAIRE {\n    TYPE statut_vacataire PK\n  }\n  CONTRAT {\n    TYPE date_contrat PK\n    TYPE salaire_horaire_contrat\n  }\n  SALARIE {\n    TYPE date_embauche_salarie PK\n    TYPE echelon_salarie\n    TYPE salaire_salarie\n  }\n  PROFESSEUR {\n    TYPE num_prof PK\n    TYPE nom_prof\n    TYPE prenom_prof\n    TYPE telephone_prof\n  }\n  CONTRAT }|..|| VACATAIRE: DF"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_1_uml.puml",
    "content": "@startuml \"inheritance_weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"CONTRAT\" \"1..*\" --* \"1\" \"VACATAIRE\"\n\nTable(\"VACATAIRE\") {\n    {field} + pk(statut vacataire)\n}\n\nTable(\"CONTRAT\") {\n    {field} + pk(date contrat)\n    {field} + salaire horaire contrat\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- SALARIÉ\nGENERALIZATION_0 -[dotted]- VACATAIRE\nPROFESSEUR <|-- SALARIÉ\nPROFESSEUR <|-- VACATAIRE\n\nTable(\"SALARIÉ\") {\n    {field} + pk(date embauche salarié)\n    {field} + échelon salarié\n    {field} + salaire salarié\n}\n\nTable(\"PROFESSEUR\") {\n    {field} + pk(num prof)\n    {field} + nom prof\n    {field} + prénom prof\n    {field} + téléphone prof\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_2_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"VACATAIRE\"]\n  2 [label=\"CONTRAT\",peripheries=2]\n\n  // Associative entities\n  7 [label=\"SALARIÉ\",shape=Mdiamond]\n  11 [label=\"PROFESSEUR\",shape=Mdiamond]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"salaire\\nhoraire\\ncontrat\"]\n  9 [label=\"échelon\\nsalarié\"]\n  10 [label=\"salaire\\nsalarié\"]\n  13 [label=\"nom prof\"]\n  14 [label=\"prénom\\nprof\"]\n  15 [label=\"téléphone\\nprof\"]\n\n  // Weak and strong entity attributes\n  4 [label=<<u>statut<br/>vacataire</u>>]\n  5 [label=<<u>date<br/>contrat</u>> style=\"dashed,filled\"]\n  8 [label=<<u>date<br/>embauche<br/>salarié</u>>]\n  12 [label=<<u>num prof</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  2 -- 5\n  2 -- 6\n  3 -- 4\n  7 -- 8\n  7 -- 9\n  7 -- 10\n  11 -- 12\n  11 -- 13\n  11 -- 14\n  11 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  3 -- 1\n  edge [headlabel=N]\n  2 -- 1\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_2_erd_chen.txt",
    "content": "[VACATAIRE] ==1== <<DF>>\n[[CONTRAT]] ==N== <<DF>>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_2_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >VACATAIRE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">statut vacataire</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >CONTRAT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date contrat</td></tr>\n        <tr><td> </td><td align=\"left\">salaire horaire contrat</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SALARIÉ</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">date embauche salarié</td></tr>\n        <tr><td> </td><td align=\"left\">échelon salarié</td></tr>\n        <tr><td> </td><td align=\"left\">salaire salarié</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PROFESSEUR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num prof</td></tr>\n        <tr><td> </td><td align=\"left\">nom prof</td></tr>\n        <tr><td> </td><td align=\"left\">prénom prof</td></tr>\n        <tr><td> </td><td align=\"left\">téléphone prof</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_2_erd_crow.mmd",
    "content": "erDiagram\n  VACATAIRE {\n    TYPE statut_vacataire PK\n  }\n  CONTRAT {\n    TYPE date_contrat PK\n    TYPE salaire_horaire_contrat\n  }\n  SALARIE {\n    TYPE date_embauche_salarie PK\n    TYPE echelon_salarie\n    TYPE salaire_salarie\n  }\n  PROFESSEUR {\n    TYPE num_prof PK\n    TYPE nom_prof\n    TYPE prenom_prof\n    TYPE telephone_prof\n  }\n  CONTRAT }|..|| VACATAIRE: DF"
  },
  {
    "path": "test/zoo/inheritance_weak/exported/strong_child_2_uml.puml",
    "content": "@startuml \"inheritance_weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\n\"CONTRAT\" \"1..*\" --* \"1\" \"VACATAIRE\"\n\nTable(\"VACATAIRE\") {\n    {field} + pk(statut vacataire)\n}\n\nTable(\"CONTRAT\") {\n    {field} + pk(date contrat)\n    {field} + salaire horaire contrat\n}\n\nnote \"{complete, disjoint}\" as GENERALIZATION_0\nGENERALIZATION_0 -[dotted]- SALARIÉ\nGENERALIZATION_0 -[dotted]- VACATAIRE\nPROFESSEUR <|-- SALARIÉ\nPROFESSEUR <|-- VACATAIRE\n\nTable(\"SALARIÉ\") {\n    {field} + pk(date embauche salarié)\n    {field} + échelon salarié\n    {field} + salaire salarié\n}\n\nTable(\"PROFESSEUR\") {\n    {field} + pk(num prof)\n    {field} + nom prof\n    {field} + prénom prof\n    {field} + téléphone prof\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCONTRAT\tnum prof\t!\t\tstrengthening_primary_foreign_key\tTrue\tVACATAIRE\tVACATAIRE\tDF\t\t\nCONTRAT\tdate contrat\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONTRAT\tsalaire horaire contrat\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\tnum prof\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPROFESSEUR\tnom prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\tprénom prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\ttéléphone prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\tnum prof\t!\t\tparent_primary_key\tTrue\tPROFESSEUR\tPROFESSEUR\tXT\t\t\nSALARIÉ\tdate embauche salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\téchelon salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\tsalaire salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nVACATAIRE\tnum prof\t!\t\tparent_primary_key\tTrue\tPROFESSEUR\tPROFESSEUR\tXT\t\t\nVACATAIRE\tstatut vacataire\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"VACATAIRE\" -> \"CONTRAT\"\n  \"PROFESSEUR\" -> \"SALARIÉ\"\n  \"PROFESSEUR\" -> \"VACATAIRE\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"strong_child_0_mld.svg\"/></center><figcaption>MCD <i>inheritance_weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CONTRAT</span> (\n    <span class='foreign primary'>#num prof</span>,\n    <span class='primary'>date contrat</span>,\n    <span class='normal'>salaire horaire contrat</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>VACATAIRE</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>date contrat</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONTRAT</i>.</li>\n    <li>Le champ <i>salaire horaire contrat</i> était déjà un simple attribut de l'entité <i>CONTRAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PROFESSEUR</span> (\n    <span class='primary'>num prof</span>,\n    <span class='normal'>nom prof</span>,\n    <span class='normal'>prénom prof</span>,\n    <span class='normal'>téléphone prof</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PROFESSEUR</i>.</li>\n    <li>Les champs <i>nom prof</i>, <i>prénom prof</i> et <i>téléphone prof</i> étaient déjà de simples attributs de l'entité <i>PROFESSEUR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SALARIÉ</span> (\n    <span class='foreign primary'>#num prof</span>,\n    <span class='normal'>date embauche salarié</span>,\n    <span class='normal'>échelon salarié</span>,\n    <span class='normal'>salaire salarié</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>PROFESSEUR</i>.</li>\n    <li>Les champs <i>date embauche salarié</i>, <i>échelon salarié</i> et <i>salaire salarié</i> étaient déjà de simples attributs de l'entité <i>SALARIÉ</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>VACATAIRE</span> (\n    <span class='foreign primary'>#num prof</span>,\n    <span class='normal'>statut vacataire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère <i>PROFESSEUR</i>.</li>\n    <li>Le champ <i>statut vacataire</i> était déjà un simple attribut de l'entité <i>VACATAIRE</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_mld.mcd",
    "content": "%%mocodo\n:::\nVACATAIRE: #num prof > PROFESSEUR > num prof, statut vacataire\n:::\n\n\n:\nCONTRAT: #num prof > VACATAIRE > num prof, _date contrat, salaire horaire contrat\n:::\nSALARIÉ: #num prof > PROFESSEUR > num prof, date embauche salarié, échelon salarié, salaire salarié\n:\n\n\n:::\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n:::\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_mld.md",
    "content": "- **CONTRAT** (<u>_#num prof_</u>, <u>date contrat</u>, salaire horaire contrat)\n  - Le champ _num prof_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _VACATAIRE_ pour renforcer l'identifiant.\n  - Le champ _date contrat_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _CONTRAT_.\n  - Le champ _salaire horaire contrat_ était déjà un simple attribut de l'entité _CONTRAT_.\n\n- **PROFESSEUR** (<u>num prof</u>, nom prof, prénom prof, téléphone prof)\n  - Le champ _num prof_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PROFESSEUR_.\n  - Les champs _nom prof_, _prénom prof_ et _téléphone prof_ étaient déjà de simples attributs de l'entité _PROFESSEUR_.\n\n- **SALARIÉ** (<u>_#num prof_</u>, date embauche salarié, échelon salarié, salaire salarié)\n  - Le champ _num prof_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _PROFESSEUR_.\n  - Les champs _date embauche salarié_, _échelon salarié_ et _salaire salarié_ étaient déjà de simples attributs de l'entité _SALARIÉ_.\n\n- **VACATAIRE** (<u>_#num prof_</u>, statut vacataire)\n  - Le champ _num prof_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère _PROFESSEUR_.\n  - Le champ _statut vacataire_ était déjà un simple attribut de l'entité _VACATAIRE_.\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance\\_weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CONTRAT} (\\foreign{\\prim{num prof}}, \\prim{date contrat}, \\attr{salaire horaire contrat})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{VACATAIRE} pour renforcer l'identifiant.\n    \\item Le champ \\emph{date contrat} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONTRAT}.\n    \\item Le champ \\emph{salaire horaire contrat} était déjà un simple attribut de l'entité \\emph{CONTRAT}.\n  \\end{itemize}\n\n  \\item \\relat{PROFESSEUR} (\\prim{num prof}, \\attr{nom prof}, \\attr{prénom prof}, \\attr{téléphone prof})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PROFESSEUR}.\n    \\item Les champs \\emph{nom prof}, \\emph{prénom prof} et \\emph{téléphone prof} étaient déjà de simples attributs de l'entité \\emph{PROFESSEUR}.\n  \\end{itemize}\n\n  \\item \\relat{SALARIÉ} (\\foreign{\\prim{num prof}}, \\attr{date embauche salarié}, \\attr{échelon salarié}, \\attr{salaire salarié})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{PROFESSEUR}.\n    \\item Les champs \\emph{date embauche salarié}, \\emph{échelon salarié} et \\emph{salaire salarié} étaient déjà de simples attributs de l'entité \\emph{SALARIÉ}.\n  \\end{itemize}\n\n  \\item \\relat{VACATAIRE} (\\foreign{\\prim{num prof}}, \\attr{statut vacataire})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère \\emph{PROFESSEUR}.\n    \\item Le champ \\emph{statut vacataire} était déjà un simple attribut de l'entité \\emph{VACATAIRE}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_0_mld.txt",
    "content": "- CONTRAT (_#num prof_, _date contrat_, salaire horaire contrat)\n  - Le champ « num prof » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « VACATAIRE » pour renforcer l'identifiant.\n  - Le champ « date contrat » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « CONTRAT ».\n  - Le champ « salaire horaire contrat » était déjà un simple attribut de l'entité « CONTRAT ».\n\n- PROFESSEUR (_num prof_, nom prof, prénom prof, téléphone prof)\n  - Le champ « num prof » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PROFESSEUR ».\n  - Les champs « nom prof », « prénom prof » et « téléphone prof » étaient déjà de simples attributs de l'entité « PROFESSEUR ».\n\n- SALARIÉ (_#num prof_, date embauche salarié, échelon salarié, salaire salarié)\n  - Le champ « num prof » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « PROFESSEUR ».\n  - Les champs « date embauche salarié », « échelon salarié » et « salaire salarié » étaient déjà de simples attributs de l'entité « SALARIÉ ».\n\n- VACATAIRE (_#num prof_, statut vacataire)\n  - Le champ « num prof » constitue la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité-mère « PROFESSEUR ».\n  - Le champ « statut vacataire » était déjà un simple attribut de l'entité « VACATAIRE ».\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCONTRAT\tnum prof\t!\t\tstrengthening_primary_foreign_key\tTrue\tVACATAIRE\tPROFESSEUR\tDF\t\t\nCONTRAT\tdate contrat\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONTRAT\tsalaire horaire contrat\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\tnum prof\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPROFESSEUR\tnom prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\tprénom prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\ttéléphone prof\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROFESSEUR\tstatut vacataire\t?\t\tdeleted_child_attribute\tFalse\tVACATAIRE\t\tXT\t\t\nPROFESSEUR\tdate embauche salarié\t?\t\tdeleted_child_attribute\tFalse\tSALARIÉ\t\tXT\t\t\nPROFESSEUR\téchelon salarié\t?\t\tdeleted_child_attribute\tFalse\tSALARIÉ\t\tXT\t\t\nPROFESSEUR\tsalaire salarié\t?\t\tdeleted_child_attribute\tFalse\tSALARIÉ\t\tXT\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"PROFESSEUR\" -> \"CONTRAT\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"strong_child_1_mld.svg\"/></center><figcaption>MCD <i>inheritance_weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CONTRAT</span> (\n    <span class='foreign primary'>#num prof</span>,\n    <span class='primary'>date contrat</span>,\n    <span class='normal'>salaire horaire contrat</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>PROFESSEUR</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>date contrat</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONTRAT</i>.</li>\n    <li>Le champ <i>salaire horaire contrat</i> était déjà un simple attribut de l'entité <i>CONTRAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PROFESSEUR</span> (\n    <span class='primary'>num prof</span>,\n    <span class='normal'>nom prof</span>,\n    <span class='normal'>prénom prof</span>,\n    <span class='normal'>téléphone prof</span>,\n    <span class='normal'>statut vacataire?</span>,\n    <span class='normal'>date embauche salarié?</span>,\n    <span class='normal'>échelon salarié?</span>,\n    <span class='normal'>salaire salarié?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PROFESSEUR</i>.</li>\n    <li>Les champs <i>nom prof</i>, <i>prénom prof</i> et <i>téléphone prof</i> étaient déjà de simples attributs de l'entité <i>PROFESSEUR</i>.</li>\n    <li>Le champ à saisie facultative <i>statut vacataire</i> a migré à partir de l'entité-fille <i>VACATAIRE</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>date embauche salarié</i> a migré à partir de l'entité-fille <i>SALARIÉ</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>échelon salarié</i> a migré à partir de l'entité-fille <i>SALARIÉ</i> (supprimée).</li>\n    <li>Le champ à saisie facultative <i>salaire salarié</i> a migré à partir de l'entité-fille <i>SALARIÉ</i> (supprimée).</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_mld.mcd",
    "content": ":\nCONTRAT: #num prof > PROFESSEUR > num prof, _date contrat, salaire horaire contrat\n:::\n\n\n:::\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof, statut vacataire, date embauche salarié, échelon salarié, salaire salarié\n:\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_mld.md",
    "content": "- **CONTRAT** (<u>_#num prof_</u>, <u>date contrat</u>, salaire horaire contrat)\n  - Le champ _num prof_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _PROFESSEUR_ pour renforcer l'identifiant.\n  - Le champ _date contrat_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _CONTRAT_.\n  - Le champ _salaire horaire contrat_ était déjà un simple attribut de l'entité _CONTRAT_.\n\n- **PROFESSEUR** (<u>num prof</u>, nom prof, prénom prof, téléphone prof, statut vacataire?, date embauche salarié?, échelon salarié?, salaire salarié?)\n  - Le champ _num prof_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PROFESSEUR_.\n  - Les champs _nom prof_, _prénom prof_ et _téléphone prof_ étaient déjà de simples attributs de l'entité _PROFESSEUR_.\n  - Le champ à saisie facultative _statut vacataire_ a migré à partir de l'entité-fille _VACATAIRE_ (supprimée).\n  - Le champ à saisie facultative _date embauche salarié_ a migré à partir de l'entité-fille _SALARIÉ_ (supprimée).\n  - Le champ à saisie facultative _échelon salarié_ a migré à partir de l'entité-fille _SALARIÉ_ (supprimée).\n  - Le champ à saisie facultative _salaire salarié_ a migré à partir de l'entité-fille _SALARIÉ_ (supprimée).\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance\\_weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CONTRAT} (\\foreign{\\prim{num prof}}, \\prim{date contrat}, \\attr{salaire horaire contrat})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{PROFESSEUR} pour renforcer l'identifiant.\n    \\item Le champ \\emph{date contrat} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONTRAT}.\n    \\item Le champ \\emph{salaire horaire contrat} était déjà un simple attribut de l'entité \\emph{CONTRAT}.\n  \\end{itemize}\n\n  \\item \\relat{PROFESSEUR} (\\prim{num prof}, \\attr{nom prof}, \\attr{prénom prof}, \\attr{téléphone prof}, \\attr{statut vacataire?}, \\attr{date embauche salarié?}, \\attr{échelon salarié?}, \\attr{salaire salarié?})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PROFESSEUR}.\n    \\item Les champs \\emph{nom prof}, \\emph{prénom prof} et \\emph{téléphone prof} étaient déjà de simples attributs de l'entité \\emph{PROFESSEUR}.\n    \\item Le champ à saisie facultative \\emph{statut vacataire} a migré à partir de l'entité-fille \\emph{VACATAIRE} (supprimée).\n    \\item Le champ à saisie facultative \\emph{date embauche salarié} a migré à partir de l'entité-fille \\emph{SALARIÉ} (supprimée).\n    \\item Le champ à saisie facultative \\emph{échelon salarié} a migré à partir de l'entité-fille \\emph{SALARIÉ} (supprimée).\n    \\item Le champ à saisie facultative \\emph{salaire salarié} a migré à partir de l'entité-fille \\emph{SALARIÉ} (supprimée).\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_1_mld.txt",
    "content": "- CONTRAT (_#num prof_, _date contrat_, salaire horaire contrat)\n  - Le champ « num prof » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « PROFESSEUR » pour renforcer l'identifiant.\n  - Le champ « date contrat » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « CONTRAT ».\n  - Le champ « salaire horaire contrat » était déjà un simple attribut de l'entité « CONTRAT ».\n\n- PROFESSEUR (_num prof_, nom prof, prénom prof, téléphone prof, statut vacataire?, date embauche salarié?, échelon salarié?, salaire salarié?)\n  - Le champ « num prof » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PROFESSEUR ».\n  - Les champs « nom prof », « prénom prof » et « téléphone prof » étaient déjà de simples attributs de l'entité « PROFESSEUR ».\n  - Le champ à saisie facultative « statut vacataire » a migré à partir de l'entité-fille « VACATAIRE » (supprimée).\n  - Le champ à saisie facultative « date embauche salarié » a migré à partir de l'entité-fille « SALARIÉ » (supprimée).\n  - Le champ à saisie facultative « échelon salarié » a migré à partir de l'entité-fille « SALARIÉ » (supprimée).\n  - Le champ à saisie facultative « salaire salarié » a migré à partir de l'entité-fille « SALARIÉ » (supprimée).\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCONTRAT\tnum prof\t!\t\tstrengthening_primary_foreign_key\tTrue\tVACATAIRE\tVACATAIRE\tDF\t\t\nCONTRAT\tdate contrat\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCONTRAT\tsalaire horaire contrat\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\tnum prof\t!\t\tdeleted_parent_primary_key\tTrue\tPROFESSEUR\tPROFESSEUR\tXT\t\t\nSALARIÉ\tnom prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nSALARIÉ\tprénom prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nSALARIÉ\ttéléphone prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nSALARIÉ\tdate embauche salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\téchelon salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSALARIÉ\tsalaire salarié\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nVACATAIRE\tnum prof\t!\t\tdeleted_parent_primary_key\tTrue\tPROFESSEUR\tPROFESSEUR\tXT\t\t\nVACATAIRE\tnom prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nVACATAIRE\tprénom prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nVACATAIRE\ttéléphone prof\t\t\tdeleted_parent_attribute\tFalse\tPROFESSEUR\t\tXT\t\t\nVACATAIRE\tstatut vacataire\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"VACATAIRE\" -> \"CONTRAT\"\n}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"strong_child_2_mld.svg\"/></center><figcaption>MCD <i>inheritance_weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>CONTRAT</span> (\n    <span class='foreign primary'>#num prof</span>,\n    <span class='primary'>date contrat</span>,\n    <span class='normal'>salaire horaire contrat</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>VACATAIRE</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>date contrat</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>CONTRAT</i>.</li>\n    <li>Le champ <i>salaire horaire contrat</i> était déjà un simple attribut de l'entité <i>CONTRAT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SALARIÉ</span> (\n    <span class='primary'>num prof</span>,\n    <span class='normal'>nom prof</span>,\n    <span class='normal'>prénom prof</span>,\n    <span class='normal'>téléphone prof</span>,\n    <span class='normal'>date embauche salarié</span>,\n    <span class='normal'>échelon salarié</span>,\n    <span class='normal'>salaire salarié</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>nom prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>prénom prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>téléphone prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Les champs <i>date embauche salarié</i>, <i>échelon salarié</i> et <i>salaire salarié</i> étaient déjà de simples attributs de l'entité <i>SALARIÉ</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>VACATAIRE</span> (\n    <span class='primary'>num prof</span>,\n    <span class='normal'>nom prof</span>,\n    <span class='normal'>prénom prof</span>,\n    <span class='normal'>téléphone prof</span>,\n    <span class='normal'>statut vacataire</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num prof</i> constitue la clé primaire de la table. Il était clé primaire de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>nom prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>prénom prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>téléphone prof</i> est un simple attribut. Il était simple attribut de l'entité-mère <i>PROFESSEUR</i> (supprimée).</li>\n    <li>Le champ <i>statut vacataire</i> était déjà un simple attribut de l'entité <i>VACATAIRE</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_mld.mcd",
    "content": "%%mocodo\n:::\nVACATAIRE: num prof, nom prof, prénom prof, téléphone prof, statut vacataire\n:::\n\n\n:\nCONTRAT: #num prof > VACATAIRE > num prof, _date contrat, salaire horaire contrat\n:::\nSALARIÉ: num prof, nom prof, prénom prof, téléphone prof, date embauche salarié, échelon salarié, salaire salarié\n:\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_mld.md",
    "content": "- **CONTRAT** (<u>_#num prof_</u>, <u>date contrat</u>, salaire horaire contrat)\n  - Le champ _num prof_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _VACATAIRE_ pour renforcer l'identifiant.\n  - Le champ _date contrat_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _CONTRAT_.\n  - Le champ _salaire horaire contrat_ était déjà un simple attribut de l'entité _CONTRAT_.\n\n- **SALARIÉ** (<u>num prof</u>, nom prof, prénom prof, téléphone prof, date embauche salarié, échelon salarié, salaire salarié)\n  - Le champ _num prof_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _nom prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _prénom prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _téléphone prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Les champs _date embauche salarié_, _échelon salarié_ et _salaire salarié_ étaient déjà de simples attributs de l'entité _SALARIÉ_.\n\n- **VACATAIRE** (<u>num prof</u>, nom prof, prénom prof, téléphone prof, statut vacataire)\n  - Le champ _num prof_ constitue la clé primaire de la table. Il était clé primaire de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _nom prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _prénom prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _téléphone prof_ est un simple attribut. Il était simple attribut de l'entité-mère _PROFESSEUR_ (supprimée).\n  - Le champ _statut vacataire_ était déjà un simple attribut de l'entité _VACATAIRE_.\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{inheritance\\_weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{CONTRAT} (\\foreign{\\prim{num prof}}, \\prim{date contrat}, \\attr{salaire horaire contrat})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{VACATAIRE} pour renforcer l'identifiant.\n    \\item Le champ \\emph{date contrat} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{CONTRAT}.\n    \\item Le champ \\emph{salaire horaire contrat} était déjà un simple attribut de l'entité \\emph{CONTRAT}.\n  \\end{itemize}\n\n  \\item \\relat{SALARIÉ} (\\prim{num prof}, \\attr{nom prof}, \\attr{prénom prof}, \\attr{téléphone prof}, \\attr{date embauche salarié}, \\attr{échelon salarié}, \\attr{salaire salarié})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{nom prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{prénom prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{téléphone prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Les champs \\emph{date embauche salarié}, \\emph{échelon salarié} et \\emph{salaire salarié} étaient déjà de simples attributs de l'entité \\emph{SALARIÉ}.\n  \\end{itemize}\n\n  \\item \\relat{VACATAIRE} (\\prim{num prof}, \\attr{nom prof}, \\attr{prénom prof}, \\attr{téléphone prof}, \\attr{statut vacataire})\n  \\begin{itemize}\n    \\item Le champ \\emph{num prof} constitue la clé primaire de la table. Il était clé primaire de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{nom prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{prénom prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{téléphone prof} est un simple attribut. Il était simple attribut de l'entité-mère \\emph{PROFESSEUR} (supprimée).\n    \\item Le champ \\emph{statut vacataire} était déjà un simple attribut de l'entité \\emph{VACATAIRE}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/inheritance_weak/mld/strong_child_2_mld.txt",
    "content": "- CONTRAT (_#num prof_, _date contrat_, salaire horaire contrat)\n  - Le champ « num prof » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « VACATAIRE » pour renforcer l'identifiant.\n  - Le champ « date contrat » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « CONTRAT ».\n  - Le champ « salaire horaire contrat » était déjà un simple attribut de l'entité « CONTRAT ».\n\n- SALARIÉ (_num prof_, nom prof, prénom prof, téléphone prof, date embauche salarié, échelon salarié, salaire salarié)\n  - Le champ « num prof » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « nom prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « prénom prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « téléphone prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Les champs « date embauche salarié », « échelon salarié » et « salaire salarié » étaient déjà de simples attributs de l'entité « SALARIÉ ».\n\n- VACATAIRE (_num prof_, nom prof, prénom prof, téléphone prof, statut vacataire)\n  - Le champ « num prof » constitue la clé primaire de la table. Il était clé primaire de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « nom prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « prénom prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « téléphone prof » est un simple attribut. Il était simple attribut de l'entité-mère « PROFESSEUR » (supprimée).\n  - Le champ « statut vacataire » était déjà un simple attribut de l'entité « VACATAIRE ».\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_create_df_arrows=across.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Class table inheritance: all entities are preserved\n\nDF, _11 CONTRAT, 1N> VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR -> VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_drown.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Class table inheritance: all entities are preserved\n\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 1_\nENTITÉ 1_: at 1 1\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 4_ -> ENTITÉ 1_, ENTITÉ 3_\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n\nENTITÉ 4_: at 4 1, at 4 2, at 4 3, at 4 4\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_create_df_arrows=across.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Single table inheritance: children are merged into the parent table\n\nDF, _11 CONTRAT, 1N> VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR <- VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_drown.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Single table inheritance: children are merged into the parent table\n\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 1_\nENTITÉ 1_: at 1 1\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 4_ <- ENTITÉ 1_, ENTITÉ 3_\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n\nENTITÉ 4_: at 4 1, at 4 2, at 4 3, at 4 4\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_create_df_arrows=across.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Concrete table inheritance: parent disappears\n\nDF, _11 CONTRAT, 1N> VACATAIRE\nVACATAIRE: statut vacataire\n\nCONTRAT: date contrat, salaire horaire contrat\n/XT\\ PROFESSEUR => VACATAIRE, SALARIÉ\nSALARIÉ: date embauche salarié, échelon salarié, salaire salarié\n\nPROFESSEUR: num prof, nom prof, prénom prof, téléphone prof\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_drown.mcd",
    "content": "% https://github.com/laowantong/mocodo/issues/118\n% Concrete table inheritance: parent disappears\n\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 1_\nENTITÉ 1_: at 1 1\n\nENTITÉ 2_: at 2 1, at 2 2\n/XT\\ ENTITÉ 4_ => ENTITÉ 1_, ENTITÉ 3_\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n\nENTITÉ 4_: at 4 1, at 4 2, at 4 3, at 4 4\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/inheritance_weak/rewritten/strong_child_2_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/landing/_landing.mcd",
    "content": "AYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/ddl/landing_ddl.d2",
    "content": "\"AYANT-DROIT\": { shape: sql_table\n  \"matricule\":       VARCHAR(42) {constraint: [PK; FK]}\n  \"nom ayant-droit\": VARCHAR(42) {constraint: PK}\n  \"lien\":            VARCHAR(42) \n}\n\n\"COMPOSER\": { shape: sql_table\n  \"réf. pièce composée\":   VARCHAR(42) {constraint: [PK; FK]}\n  \"réf. pièce composante\": VARCHAR(42) {constraint: [PK; FK]}\n  \"quantité\":              VARCHAR(42) \n}\n\n\"DÉPARTEMENT\": { shape: sql_table\n  \"num. département\": VARCHAR(42) {constraint: PK}\n  \"nom département\":  VARCHAR(42) \n}\n\n\"EMPLOYÉ\": { shape: sql_table\n  \"matricule\":        VARCHAR(42) {constraint: PK}\n  \"nom employé\":      VARCHAR(42) \n  \"num. département\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"FOURNIR\": { shape: sql_table\n  \"num. projet\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"réf. pièce\":   VARCHAR(42) {constraint: [PK; FK]}\n  \"num. société\": VARCHAR(42) {constraint: [PK; FK]}\n  \"qté fournie\":  VARCHAR(42) \n}\n\n\"PIÈCE\": { shape: sql_table\n  \"réf. pièce\":    VARCHAR(42) {constraint: PK}\n  \"libellé pièce\": VARCHAR(42) \n}\n\n\"PROJET\": { shape: sql_table\n  \"num. projet\":           VARCHAR(42) {constraint: PK}\n  \"nom projet\":            VARCHAR(42) \n  \"matricule responsable\": VARCHAR(42) {constraint: [FK; \"NULL\"]}\n}\n\n\"REQUÉRIR\": { shape: sql_table\n  \"num. projet\": VARCHAR(42) {constraint: [PK; FK]}\n  \"réf. pièce\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"qté requise\": VARCHAR(42) \n}\n\n\"SOCIÉTÉ\": { shape: sql_table\n  \"num. société\":      VARCHAR(42) {constraint: PK}\n  \"raison sociale\":    VARCHAR(42) \n  \"num. société mère\": VARCHAR(42) {constraint: [FK; \"NULL\"]}\n}\n\n\"TRAVAILLER\": { shape: sql_table\n  \"matricule\":   VARCHAR(42) {constraint: [PK; FK]}\n  \"num. projet\": VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"AYANT-DROIT\".\"matricule\" -> \"EMPLOYÉ\".\"matricule\"\n\"COMPOSER\".\"réf. pièce composée\" -> \"PIÈCE\".\"réf. pièce\"\n\"COMPOSER\".\"réf. pièce composante\" -> \"PIÈCE\".\"réf. pièce\"\n\"EMPLOYÉ\".\"num. département\" -> \"DÉPARTEMENT\".\"num. département\"\n\"FOURNIR\".\"num. projet\" -> \"PROJET\".\"num. projet\"\n\"FOURNIR\".\"réf. pièce\" -> \"PIÈCE\".\"réf. pièce\"\n\"FOURNIR\".\"num. société\" -> \"SOCIÉTÉ\".\"num. société\"\n\"PROJET\".\"matricule responsable\" -> \"EMPLOYÉ\".\"matricule\"\n\"REQUÉRIR\".\"num. projet\" -> \"PROJET\".\"num. projet\"\n\"REQUÉRIR\".\"réf. pièce\" -> \"PIÈCE\".\"réf. pièce\"\n\"SOCIÉTÉ\".\"num. société mère\" -> \"SOCIÉTÉ\".\"num. société\"\n\"TRAVAILLER\".\"matricule\" -> \"EMPLOYÉ\".\"matricule\"\n\"TRAVAILLER\".\"num. projet\" -> \"PROJET\".\"num. projet\"\n"
  },
  {
    "path": "test/zoo/landing/ddl/landing_ddl.dbml",
    "content": "Table \"AYANT-DROIT\" {\n  \"matricule\"       VARCHAR(42) [NOT NULL]\n  \"nom ayant-droit\" VARCHAR(42) [NOT NULL]\n  \"lien\"            VARCHAR(42)\n  Indexes {\n    (\"matricule\", \"nom ayant-droit\") [pk]\n  }\n}\n\nTable \"COMPOSER\" {\n  \"réf. pièce composée\"   VARCHAR(42) [NOT NULL]\n  \"réf. pièce composante\" VARCHAR(42) [NOT NULL]\n  \"quantité\"              VARCHAR(42)\n  Indexes {\n    (\"réf. pièce composée\", \"réf. pièce composante\") [pk]\n  }\n}\n\nTable \"DÉPARTEMENT\" {\n  \"num. département\" VARCHAR(42) [pk, NOT NULL]\n  \"nom département\"  VARCHAR(42)\n}\n\nTable \"EMPLOYÉ\" {\n  \"matricule\"        VARCHAR(42) [pk, NOT NULL]\n  \"nom employé\"      VARCHAR(42)\n  \"num. département\" VARCHAR(42) [NOT NULL]\n}\n\nTable \"FOURNIR\" {\n  \"num. projet\"  VARCHAR(42) [NOT NULL]\n  \"réf. pièce\"   VARCHAR(42) [NOT NULL]\n  \"num. société\" VARCHAR(42) [NOT NULL]\n  \"qté fournie\"  VARCHAR(42)\n  Indexes {\n    (\"num. projet\", \"réf. pièce\", \"num. société\") [pk]\n  }\n}\n\nTable \"PIÈCE\" {\n  \"réf. pièce\"    VARCHAR(42) [pk, NOT NULL]\n  \"libellé pièce\" VARCHAR(42)\n}\n\nTable \"PROJET\" {\n  \"num. projet\"           VARCHAR(42) [pk, NOT NULL]\n  \"nom projet\"            VARCHAR(42)\n  \"matricule responsable\" VARCHAR(42) [\"NULL\"]\n}\n\nTable \"REQUÉRIR\" {\n  \"num. projet\" VARCHAR(42) [NOT NULL]\n  \"réf. pièce\"  VARCHAR(42) [NOT NULL]\n  \"qté requise\" VARCHAR(42)\n  Indexes {\n    (\"num. projet\", \"réf. pièce\") [pk]\n  }\n}\n\nTable \"SOCIÉTÉ\" {\n  \"num. société\"      VARCHAR(42) [pk, NOT NULL]\n  \"raison sociale\"    VARCHAR(42)\n  \"num. société mère\" VARCHAR(42) [\"NULL\"]\n}\n\nTable \"TRAVAILLER\" {\n  \"matricule\"   VARCHAR(42) [NOT NULL]\n  \"num. projet\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"matricule\", \"num. projet\") [pk]\n  }\n}\n\nRef:\"AYANT-DROIT\".\"matricule\" > \"EMPLOYÉ\".\"matricule\"\nRef:\"COMPOSER\".(\"réf. pièce composée\", \"réf. pièce composante\") > \"PIÈCE\".(\"réf. pièce\", \"réf. pièce\")\nRef:\"EMPLOYÉ\".\"num. département\" > \"DÉPARTEMENT\".\"num. département\"\nRef:\"FOURNIR\".\"num. projet\" > \"PROJET\".\"num. projet\"\nRef:\"FOURNIR\".\"réf. pièce\" > \"PIÈCE\".\"réf. pièce\"\nRef:\"FOURNIR\".\"num. société\" > \"SOCIÉTÉ\".\"num. société\"\nRef:\"PROJET\".\"matricule responsable\" > \"EMPLOYÉ\".\"matricule\"\nRef:\"REQUÉRIR\".\"num. projet\" > \"PROJET\".\"num. projet\"\nRef:\"REQUÉRIR\".\"réf. pièce\" > \"PIÈCE\".\"réf. pièce\"\nRef:\"SOCIÉTÉ\".\"num. société mère\" > \"SOCIÉTÉ\".\"num. société\"\nRef:\"TRAVAILLER\".\"matricule\" > \"EMPLOYÉ\".\"matricule\"\nRef:\"TRAVAILLER\".\"num. projet\" > \"PROJET\".\"num. projet\"\n"
  },
  {
    "path": "test/zoo/landing/ddl/landing_ddl.sql",
    "content": "CREATE TABLE AYANT_DROIT (\n  PRIMARY KEY (matricule, nom_ayant_droit),\n  matricule       VARCHAR(42) NOT NULL,\n  nom_ayant_droit VARCHAR(255) NOT NULL,\n  lien            VARCHAR(42)\n);\n\nCREATE TABLE COMPOSER (\n  PRIMARY KEY (ref_piece_composee, ref_piece_composante),\n  ref_piece_composee   VARCHAR(8) NOT NULL,\n  ref_piece_composante VARCHAR(8) NOT NULL,\n  quantite             INTEGER\n);\n\nCREATE TABLE DEPARTEMENT (\n  PRIMARY KEY (num_departement),\n  num_departement VARCHAR(8) NOT NULL,\n  nom_departement VARCHAR(255)\n);\n\nCREATE TABLE EMPLOYE (\n  PRIMARY KEY (matricule),\n  matricule       VARCHAR(42) NOT NULL,\n  nom_employe     VARCHAR(255),\n  num_departement VARCHAR(8) NOT NULL\n);\n\nCREATE TABLE FOURNIR (\n  PRIMARY KEY (num_projet, ref_piece, num_societe),\n  num_projet  VARCHAR(8) NOT NULL,\n  ref_piece   VARCHAR(8) NOT NULL,\n  num_societe VARCHAR(8) NOT NULL,\n  qte_fournie INTEGER\n);\n\nCREATE TABLE PIECE (\n  PRIMARY KEY (ref_piece),\n  ref_piece     VARCHAR(8) NOT NULL,\n  libelle_piece VARCHAR(42)\n);\n\nCREATE TABLE PROJET (\n  PRIMARY KEY (num_projet),\n  num_projet            VARCHAR(8) NOT NULL,\n  nom_projet            VARCHAR(255),\n  matricule_responsable VARCHAR(42) NULL\n);\n\nCREATE TABLE REQUERIR (\n  PRIMARY KEY (num_projet, ref_piece),\n  num_projet  VARCHAR(8) NOT NULL,\n  ref_piece   VARCHAR(8) NOT NULL,\n  qte_requise INTEGER\n);\n\nCREATE TABLE SOCIETE (\n  PRIMARY KEY (num_societe),\n  num_societe      VARCHAR(8) NOT NULL,\n  raison_sociale   VARCHAR(42),\n  num_societe_mere VARCHAR(8) NULL\n);\n\nCREATE TABLE TRAVAILLER (\n  PRIMARY KEY (matricule, num_projet),\n  matricule  VARCHAR(42) NOT NULL,\n  num_projet VARCHAR(8) NOT NULL\n);\n\nALTER TABLE AYANT_DROIT ADD FOREIGN KEY (matricule) REFERENCES EMPLOYE (matricule);\n\nALTER TABLE COMPOSER ADD FOREIGN KEY (ref_piece_composante) REFERENCES PIECE (ref_piece);\nALTER TABLE COMPOSER ADD FOREIGN KEY (ref_piece_composee) REFERENCES PIECE (ref_piece);\n\nALTER TABLE EMPLOYE ADD FOREIGN KEY (num_departement) REFERENCES DEPARTEMENT (num_departement);\n\nALTER TABLE FOURNIR ADD FOREIGN KEY (num_societe) REFERENCES SOCIETE (num_societe);\nALTER TABLE FOURNIR ADD FOREIGN KEY (ref_piece) REFERENCES PIECE (ref_piece);\nALTER TABLE FOURNIR ADD FOREIGN KEY (num_projet) REFERENCES PROJET (num_projet);\n\nALTER TABLE PROJET ADD FOREIGN KEY (matricule_responsable) REFERENCES EMPLOYE (matricule);\n\nALTER TABLE REQUERIR ADD FOREIGN KEY (ref_piece) REFERENCES PIECE (ref_piece);\nALTER TABLE REQUERIR ADD FOREIGN KEY (num_projet) REFERENCES PROJET (num_projet);\n\nALTER TABLE SOCIETE ADD FOREIGN KEY (num_societe_mere) REFERENCES SOCIETE (num_societe);\n\nALTER TABLE TRAVAILLER ADD FOREIGN KEY (num_projet) REFERENCES PROJET (num_projet);\nALTER TABLE TRAVAILLER ADD FOREIGN KEY (matricule) REFERENCES EMPLOYE (matricule);\n"
  },
  {
    "path": "test/zoo/landing/exported/landing_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"AYANT-\\nDROIT\",peripheries=2]\n  8 [label=\"PIÈCE\"]\n  5 [label=\"EMPLOYÉ\"]\n  6 [label=\"PROJET\"]\n  22 [label=\"DÉPARTEMENT\"]\n  20 [label=\"SOCIÉTÉ\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"lien\"]\n  11 [label=\"libellé\\npièce\"]\n  16 [label=\"nom\\nemployé\"]\n  18 [label=\"nom\\nprojet\"]\n  24 [label=\"nom\\ndépartement\"]\n  28 [label=\"raison\\nsociale\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>nom ayant-<br/>droit</u>> style=\"dashed,filled\"]\n  10 [label=<<u>réf.<br/>pièce</u>>]\n  15 [label=<<u>matricule</u>>]\n  17 [label=<<u>num.<br/>projet</u>>]\n  23 [label=<<u>num.<br/>département</u>>]\n  27 [label=<<u>num.<br/>société</u>>]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  9 [label=\"qté\\nrequise\"]\n  13 [label=\"quantité\"]\n  21 [label=\"qté\\nfournie\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"DIRIGER\"]\n  7 [label=\"REQUÉRIR\"]\n  12 [label=\"COMPOSER\"]\n  14 [label=\"DF\",peripheries=2]\n  19 [label=\"FOURNIR\"]\n  25 [label=\"EMPLOYER\"]\n  26 [label=\"TRAVAILLER\"]\n  29 [label=\"CONTRÔLER\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 15\n  5 -- 16\n  6 -- 17\n  6 -- 18\n  8 -- 10\n  8 -- 11\n  20 -- 27\n  20 -- 28\n  22 -- 23\n  22 -- 24\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  7 -- 9\n  12 -- 13\n  19 -- 21\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  22 -- 25\n  5 -- 4 [color=\"#000000\"]\n  5 -- 14 [color=\"#000000\"]\n  20 -- 29 [color=\"#000000\"]\n  edge [headlabel=M]\n  6 -- 26\n  8 -- 7 [color=\"#000000\"]\n  8 -- 12 [color=\"#000000\"]\n  edge [headlabel=N]\n  1 -- 14\n  5 -- 25\n  6 -- 7\n  6 -- 19\n  8 -- 19\n  20 -- 19\n  5 -- 26 [color=\"#000000\"]\n  6 -- 4 [color=\"#000000\"]\n  12 -- 8 [color=\"#000000\"]\n  29 -- 20 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/landing/exported/landing_erd_chen.txt",
    "content": "[DÉPARTEMENT] ==1== <EMPLOYER>\n[EMPLOYÉ] --1-- <<DF>>\n[EMPLOYÉ] --1-- <DIRIGER>\n[EMPLOYÉ] --N-- <TRAVAILLER>\n[EMPLOYÉ] ==N== <EMPLOYER>\n[PIÈCE] --M-- <COMPOSER>\n[PIÈCE] --M-- <REQUÉRIR>\n[PIÈCE] --N-- <COMPOSER>\n[PIÈCE] ==N== <FOURNIR>\n[PROJET] --N-- <DIRIGER>\n[PROJET] ==M== <TRAVAILLER>\n[PROJET] ==N== <FOURNIR>\n[PROJET] ==N== <REQUÉRIR>\n[SOCIÉTÉ] --1-- <CONTRÔLER>\n[SOCIÉTÉ] --N-- <CONTRÔLER>\n[SOCIÉTÉ] ==N== <FOURNIR>\n[[AYANT-DROIT]] ==N== <<DF>>\n"
  },
  {
    "path": "test/zoo/landing/exported/landing_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >AYANT-DROIT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">nom ayant-droit</td></tr>\n        <tr><td> </td><td align=\"left\">lien</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >REQUÉRIR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">qté requise</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PIÈCE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">réf. pièce</td></tr>\n        <tr><td> </td><td align=\"left\">libellé pièce</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >COMPOSER</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">quantité</td></tr>\n    </table>\n>]\n  5 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >EMPLOYÉ</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">matricule</td></tr>\n        <tr><td> </td><td align=\"left\">nom employé</td></tr>\n    </table>\n>]\n  6 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PROJET</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num. projet</td></tr>\n        <tr><td> </td><td align=\"left\">nom projet</td></tr>\n    </table>\n>]\n  7 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >FOURNIR</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">qté fournie</td></tr>\n    </table>\n>]\n  8 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >DÉPARTEMENT</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num. département</td></tr>\n        <tr><td> </td><td align=\"left\">nom département</td></tr>\n    </table>\n>]\n  9 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >SOCIÉTÉ</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num. société</td></tr>\n        <tr><td> </td><td align=\"left\">raison sociale</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  5 -> 6 [arrowhead=\"crowodot\" arrowtail=\"teeodot\" label=\"DIRIGER\"]\n  2 -> 6 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  2 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  4 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  4 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  1 -> 5 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"DF\" style=dotted]\n  7 -> 6 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  7 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  7 -> 9 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"DF\" style=dotted]\n  5 -> 8 [arrowhead=\"teetee\" arrowtail=\"crowtee\" label=\"EMPLOYER\"]\n  5 -> 6 [arrowhead=\"crowodot\" arrowtail=\"crowtee\" label=\"TRAVAILLER\"]\n  9 -> 9 [arrowhead=\"crowodot\" arrowtail=\"teeodot\" label=\"CONTRÔLER\"]\n}"
  },
  {
    "path": "test/zoo/landing/exported/landing_erd_crow.mmd",
    "content": "erDiagram\n  AYANT_DROIT {\n    TYPE nom_ayant_droit PK\n    TYPE lien\n  }\n  REQUERIR {\n    TYPE qte_requise PK\n  }\n  PIECE {\n    TYPE ref_piece PK\n    TYPE libelle_piece\n  }\n  COMPOSER {\n    TYPE quantite PK\n  }\n  EMPLOYE {\n    TYPE matricule PK\n    TYPE nom_employe\n  }\n  PROJET {\n    TYPE num_projet PK\n    TYPE nom_projet\n  }\n  FOURNIR {\n    TYPE qte_fournie PK\n  }\n  DEPARTEMENT {\n    TYPE num_departement PK\n    TYPE nom_departement\n  }\n  SOCIETE {\n    TYPE num_societe PK\n    TYPE raison_sociale\n  }\n  EMPLOYE |o--o{ PROJET: DIRIGER\n  REQUERIR }|..|| PROJET: DF\n  REQUERIR }o..|| PIECE: DF\n  COMPOSER }o..|| PIECE: DF\n  COMPOSER }o..|| PIECE: DF\n  AYANT_DROIT }o..|| EMPLOYE: DF\n  FOURNIR }|..|| PROJET: DF\n  FOURNIR }|..|| PIECE: DF\n  FOURNIR }|..|| SOCIETE: DF\n  EMPLOYE }|--|| DEPARTEMENT: EMPLOYER\n  EMPLOYE }|--o{ PROJET: TRAVAILLER\n  SOCIETE |o--o{ SOCIETE: CONTROLER"
  },
  {
    "path": "test/zoo/landing/exported/landing_uml.puml",
    "content": "@startuml \"landing\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"AYANT-DROIT\") {\n    {field} + pk(nom ayant-droit)\n    {field} + lien\n}\n\n\"EMPLOYÉ\" \"1..*\" --- \"*\" \"PROJET\": \"DIRIGER\"\n\n\"PROJET\" \"*\" --- \"1..*\" \"PIÈCE\": \"REQUÉRIR\"\n(\"PROJET\", \"PIÈCE\") .. \"REQUÉRIR\"\nTable(\"REQUÉRIR\") {\n    {field} + qté requise\n}\n\nTable(\"PIÈCE\") {\n    {field} + pk(réf. pièce)\n    {field} + libellé pièce\n}\n\n\"PIÈCE\" \"*\" --- \"*\" \"PIÈCE\": \"COMPOSER\"\n(\"PIÈCE\", \"PIÈCE\") .. \"COMPOSER\"\nTable(\"COMPOSER\") {\n    {field} + quantité\n}\n\n\"AYANT-DROIT\" \"*\" --* \"1\" \"EMPLOYÉ\"\n\nTable(\"EMPLOYÉ\") {\n    {field} + pk(matricule)\n    {field} + nom employé\n}\n\nTable(\"PROJET\") {\n    {field} + pk(num. projet)\n    {field} + nom projet\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1..*\" \"PROJET\"\nN_ARY_0 -- \"1..*\" \"PIÈCE\"\nN_ARY_0 -- \"1..*\" \"SOCIÉTÉ\"\nN_ARY_0 \"FOURNIR\" .. \"FOURNIR\"\nTable(\"FOURNIR\") {\n    {field} + qté fournie\n}\n\nTable(\"DÉPARTEMENT\") {\n    {field} + pk(num. département)\n    {field} + nom département\n}\n\n\"EMPLOYÉ\" \"1..*\" --- \"1\" \"DÉPARTEMENT\": \"EMPLOYER\"\n\n\"EMPLOYÉ\" \"1..*\" --- \"*\" \"PROJET\": \"TRAVAILLER\"\n\nTable(\"SOCIÉTÉ\") {\n    {field} + pk(num. société)\n    {field} + raison sociale\n}\n\n\"SOCIÉTÉ\" \"1..*\" --- \"*\" \"SOCIÉTÉ\": \"CONTRÔLER\"\n\n@enduml\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAYANT-DROIT\tmatricule\t!\t\tstrengthening_primary_foreign_key\tTrue\tEMPLOYÉ\tEMPLOYÉ\tDF\t\t\nAYANT-DROIT\tnom ayant-droit\t!\t\tprimary_key\tTrue\t\t\t\t\t\nAYANT-DROIT\tlien\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nCOMPOSER\tréf. pièce\t!\t\tprimary_foreign_key\tTrue\tPIÈCE\tPIÈCE\tCOMPOSER\t\tcomposée\nCOMPOSER\tréf. pièce\t!\t\tprimary_foreign_key\tTrue\tPIÈCE\tPIÈCE\tCOMPOSER\t\tcomposante\nCOMPOSER\tquantité\t\t\tassociation_attribute\tFalse\t\t\tCOMPOSER\t\t\nDÉPARTEMENT\tnum. département\t!\t\tprimary_key\tTrue\t\t\t\t\t\nDÉPARTEMENT\tnom département\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nEMPLOYÉ\tmatricule\t!\t\tprimary_key\tTrue\t\t\t\t\t\nEMPLOYÉ\tnom employé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nEMPLOYÉ\tnum. département\t!\t\tforeign_key\tFalse\tDÉPARTEMENT\tDÉPARTEMENT\tEMPLOYER\t\t\nFOURNIR\tnum. projet\t!\t\tprimary_foreign_key\tTrue\tPROJET\tPROJET\tFOURNIR\t\t\nFOURNIR\tréf. pièce\t!\t\tprimary_foreign_key\tTrue\tPIÈCE\tPIÈCE\tFOURNIR\t\t\nFOURNIR\tnum. société\t!\t\tprimary_foreign_key\tTrue\tSOCIÉTÉ\tSOCIÉTÉ\tFOURNIR\t\t\nFOURNIR\tqté fournie\t\t\tassociation_attribute\tFalse\t\t\tFOURNIR\t\t\nPIÈCE\tréf. pièce\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPIÈCE\tlibellé pièce\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROJET\tnum. projet\t!\t\tprimary_key\tTrue\t\t\t\t\t\nPROJET\tnom projet\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nPROJET\tmatricule\t?\t\tforeign_key\tFalse\tEMPLOYÉ\tEMPLOYÉ\tDIRIGER\t\tresponsable\nREQUÉRIR\tnum. projet\t!\t\tprimary_foreign_key\tTrue\tPROJET\tPROJET\tREQUÉRIR\t\t\nREQUÉRIR\tréf. pièce\t!\t\tprimary_foreign_key\tTrue\tPIÈCE\tPIÈCE\tREQUÉRIR\t\t\nREQUÉRIR\tqté requise\t\t\tassociation_attribute\tFalse\t\t\tREQUÉRIR\t\t\nSOCIÉTÉ\tnum. société\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSOCIÉTÉ\traison sociale\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSOCIÉTÉ\tnum. société\t?\t\tforeign_key\tFalse\tSOCIÉTÉ\tSOCIÉTÉ\tCONTRÔLER\t\tmère\nTRAVAILLER\tmatricule\t!\t\tprimary_foreign_key\tTrue\tEMPLOYÉ\tEMPLOYÉ\tTRAVAILLER\t\t\nTRAVAILLER\tnum. projet\t!\t\tprimary_foreign_key\tTrue\tPROJET\tPROJET\tTRAVAILLER\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"EMPLOYÉ\" -> \"AYANT-DROIT\"\n  \"PIÈCE\" -> \"COMPOSER\"\n  \"DÉPARTEMENT\" -> \"EMPLOYÉ\"\n  \"SOCIÉTÉ\" -> \"FOURNIR\"\n  \"PIÈCE\" -> \"FOURNIR\"\n  \"PROJET\" -> \"FOURNIR\"\n  \"EMPLOYÉ\" -> \"PROJET\"\n  \"PIÈCE\" -> \"REQUÉRIR\"\n  \"PROJET\" -> \"REQUÉRIR\"\n  \"SOCIÉTÉ\" -> \"SOCIÉTÉ\"\n  \"PROJET\" -> \"TRAVAILLER\"\n  \"EMPLOYÉ\" -> \"TRAVAILLER\"\n}\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"landing_mld.svg\"/></center><figcaption>MCD <i>landing</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>AYANT-DROIT</span> (\n    <span class='foreign primary'>#matricule</span>,\n    <span class='primary'>nom ayant-droit</span>,\n    <span class='normal'>lien</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>matricule</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>EMPLOYÉ</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>nom ayant-droit</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>AYANT-DROIT</i>.</li>\n    <li>Le champ <i>lien</i> était déjà un simple attribut de l'entité <i>AYANT-DROIT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>COMPOSER</span> (\n    <span class='foreign primary'>#réf. pièce composée</span>,\n    <span class='foreign primary'>#réf. pièce composante</span>,\n    <span class='normal'>quantité</span>\n  )</summary>\n  <ul>\n    <li>Les champs <i>réf. pièce composée</i> et <i>réf. pièce composante</i> constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité <i>PIÈCE</i>.</li>\n    <li>Le champ <i>quantité</i> était déjà un simple attribut de l'association <i>COMPOSER</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>DÉPARTEMENT</span> (\n    <span class='primary'>num. département</span>,\n    <span class='normal'>nom département</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. département</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>DÉPARTEMENT</i>.</li>\n    <li>Le champ <i>nom département</i> était déjà un simple attribut de l'entité <i>DÉPARTEMENT</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>EMPLOYÉ</span> (\n    <span class='primary'>matricule</span>,\n    <span class='normal'>nom employé</span>,\n    <span class='foreign'>#num. département!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>matricule</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>EMPLOYÉ</i>.</li>\n    <li>Le champ <i>nom employé</i> était déjà un simple attribut de l'entité <i>EMPLOYÉ</i>.</li>\n    <li>Le champ à saisie obligatoire <i>num. département</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>EMPLOYER</i> à partir de l'entité <i>DÉPARTEMENT</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>FOURNIR</span> (\n    <span class='foreign primary'>#num. projet</span>,\n    <span class='foreign primary'>#réf. pièce</span>,\n    <span class='foreign primary'>#num. société</span>,\n    <span class='normal'>qté fournie</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PROJET</i>.</li>\n    <li>Le champ <i>réf. pièce</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PIÈCE</i>.</li>\n    <li>Le champ <i>num. société</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>SOCIÉTÉ</i>.</li>\n    <li>Le champ <i>qté fournie</i> était déjà un simple attribut de l'association <i>FOURNIR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PIÈCE</span> (\n    <span class='primary'>réf. pièce</span>,\n    <span class='normal'>libellé pièce</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>réf. pièce</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PIÈCE</i>.</li>\n    <li>Le champ <i>libellé pièce</i> était déjà un simple attribut de l'entité <i>PIÈCE</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>PROJET</span> (\n    <span class='primary'>num. projet</span>,\n    <span class='normal'>nom projet</span>,\n    <span class='foreign'>#matricule responsable?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. projet</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>PROJET</i>.</li>\n    <li>Le champ <i>nom projet</i> était déjà un simple attribut de l'entité <i>PROJET</i>.</li>\n    <li>Le champ à saisie facultative <i>matricule responsable</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>DIRIGER</i> à partir de l'entité <i>EMPLOYÉ</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>REQUÉRIR</span> (\n    <span class='foreign primary'>#num. projet</span>,\n    <span class='foreign primary'>#réf. pièce</span>,\n    <span class='normal'>qté requise</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PROJET</i>.</li>\n    <li>Le champ <i>réf. pièce</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PIÈCE</i>.</li>\n    <li>Le champ <i>qté requise</i> était déjà un simple attribut de l'association <i>REQUÉRIR</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>SOCIÉTÉ</span> (\n    <span class='primary'>num. société</span>,\n    <span class='normal'>raison sociale</span>,\n    <span class='foreign'>#num. société mère?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>num. société</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>SOCIÉTÉ</i>.</li>\n    <li>Le champ <i>raison sociale</i> était déjà un simple attribut de l'entité <i>SOCIÉTÉ</i>.</li>\n    <li>Le champ à saisie facultative <i>num. société mère</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>CONTRÔLER</i> à partir de l'entité <i>SOCIÉTÉ</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>TRAVAILLER</span> (\n    <span class='foreign primary'>#matricule</span>,\n    <span class='foreign primary'>#num. projet</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>matricule</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>EMPLOYÉ</i>.</li>\n    <li>Le champ <i>num. projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>PROJET</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_mld.mcd",
    "content": "%%mocodo\n:\nAYANT-DROIT: #matricule > EMPLOYÉ > matricule, _nom ayant-droit, lien\n:::\nREQUÉRIR: #num. projet > PROJET > num. projet, _#réf. pièce > PIÈCE > réf. pièce, qté requise\n:\nPIÈCE: réf. pièce, libellé pièce\n:\nCOMPOSER: #réf. pièce composée > PIÈCE > réf. pièce, _#réf. pièce composante > PIÈCE > réf. pièce, quantité\n:\n\n\n:::\nEMPLOYÉ: matricule, nom employé, #num. département > DÉPARTEMENT > num. département\n:\nPROJET: num. projet, nom projet, #matricule responsable > EMPLOYÉ > matricule\n:\nFOURNIR: #num. projet > PROJET > num. projet, _#réf. pièce > PIÈCE > réf. pièce, _#num. société > SOCIÉTÉ > num. société, qté fournie\n:::\n\n\n:\nDÉPARTEMENT: num. département, nom département\n:::\nTRAVAILLER: #matricule > EMPLOYÉ > matricule, _#num. projet > PROJET > num. projet\n:\nSOCIÉTÉ: num. société, raison sociale, #num. société mère > SOCIÉTÉ > num. société\n:::\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_mld.md",
    "content": "- **AYANT-DROIT** (<u>_#matricule_</u>, <u>nom ayant-droit</u>, lien)\n  - Le champ _matricule_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _EMPLOYÉ_ pour renforcer l'identifiant.\n  - Le champ _nom ayant-droit_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _AYANT-DROIT_.\n  - Le champ _lien_ était déjà un simple attribut de l'entité _AYANT-DROIT_.\n\n- **COMPOSER** (<u>_#réf. pièce composée_</u>, <u>_#réf. pièce composante_</u>, quantité)\n  - Les champs _réf. pièce composée_ et _réf. pièce composante_ constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité _PIÈCE_.\n  - Le champ _quantité_ était déjà un simple attribut de l'association _COMPOSER_.\n\n- **DÉPARTEMENT** (<u>num. département</u>, nom département)\n  - Le champ _num. département_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _DÉPARTEMENT_.\n  - Le champ _nom département_ était déjà un simple attribut de l'entité _DÉPARTEMENT_.\n\n- **EMPLOYÉ** (<u>matricule</u>, nom employé, _#num. département!_)\n  - Le champ _matricule_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _EMPLOYÉ_.\n  - Le champ _nom employé_ était déjà un simple attribut de l'entité _EMPLOYÉ_.\n  - Le champ à saisie obligatoire _num. département_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _EMPLOYER_ à partir de l'entité _DÉPARTEMENT_ en perdant son caractère identifiant.\n\n- **FOURNIR** (<u>_#num. projet_</u>, <u>_#réf. pièce_</u>, <u>_#num. société_</u>, qté fournie)\n  - Le champ _num. projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PROJET_.\n  - Le champ _réf. pièce_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PIÈCE_.\n  - Le champ _num. société_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _SOCIÉTÉ_.\n  - Le champ _qté fournie_ était déjà un simple attribut de l'association _FOURNIR_.\n\n- **PIÈCE** (<u>réf. pièce</u>, libellé pièce)\n  - Le champ _réf. pièce_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PIÈCE_.\n  - Le champ _libellé pièce_ était déjà un simple attribut de l'entité _PIÈCE_.\n\n- **PROJET** (<u>num. projet</u>, nom projet, _#matricule responsable?_)\n  - Le champ _num. projet_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _PROJET_.\n  - Le champ _nom projet_ était déjà un simple attribut de l'entité _PROJET_.\n  - Le champ à saisie facultative _matricule responsable_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _DIRIGER_ à partir de l'entité _EMPLOYÉ_ en perdant son caractère identifiant.\n\n- **REQUÉRIR** (<u>_#num. projet_</u>, <u>_#réf. pièce_</u>, qté requise)\n  - Le champ _num. projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PROJET_.\n  - Le champ _réf. pièce_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PIÈCE_.\n  - Le champ _qté requise_ était déjà un simple attribut de l'association _REQUÉRIR_.\n\n- **SOCIÉTÉ** (<u>num. société</u>, raison sociale, _#num. société mère?_)\n  - Le champ _num. société_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _SOCIÉTÉ_.\n  - Le champ _raison sociale_ était déjà un simple attribut de l'entité _SOCIÉTÉ_.\n  - Le champ à saisie facultative _num. société mère_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _CONTRÔLER_ à partir de l'entité _SOCIÉTÉ_ en perdant son caractère identifiant.\n\n- **TRAVAILLER** (<u>_#matricule_</u>, <u>_#num. projet_</u>)\n  - Le champ _matricule_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _EMPLOYÉ_.\n  - Le champ _num. projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _PROJET_.\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{landing}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{AYANT-DROIT} (\\foreign{\\prim{matricule}}, \\prim{nom ayant-droit}, \\attr{lien})\n  \\begin{itemize}\n    \\item Le champ \\emph{matricule} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{EMPLOYÉ} pour renforcer l'identifiant.\n    \\item Le champ \\emph{nom ayant-droit} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{AYANT-DROIT}.\n    \\item Le champ \\emph{lien} était déjà un simple attribut de l'entité \\emph{AYANT-DROIT}.\n  \\end{itemize}\n\n  \\item \\relat{COMPOSER} (\\foreign{\\prim{réf. pièce composée}}, \\foreign{\\prim{réf. pièce composante}}, \\attr{quantité})\n  \\begin{itemize}\n    \\item Les champs \\emph{réf. pièce composée} et \\emph{réf. pièce composante} constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité \\emph{PIÈCE}.\n    \\item Le champ \\emph{quantité} était déjà un simple attribut de l'association \\emph{COMPOSER}.\n  \\end{itemize}\n\n  \\item \\relat{DÉPARTEMENT} (\\prim{num. département}, \\attr{nom département})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. département} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{DÉPARTEMENT}.\n    \\item Le champ \\emph{nom département} était déjà un simple attribut de l'entité \\emph{DÉPARTEMENT}.\n  \\end{itemize}\n\n  \\item \\relat{EMPLOYÉ} (\\prim{matricule}, \\attr{nom employé}, \\foreign{num. département!})\n  \\begin{itemize}\n    \\item Le champ \\emph{matricule} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{EMPLOYÉ}.\n    \\item Le champ \\emph{nom employé} était déjà un simple attribut de l'entité \\emph{EMPLOYÉ}.\n    \\item Le champ à saisie obligatoire \\emph{num. département} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{EMPLOYER} à partir de l'entité \\emph{DÉPARTEMENT} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{FOURNIR} (\\foreign{\\prim{num. projet}}, \\foreign{\\prim{réf. pièce}}, \\foreign{\\prim{num. société}}, \\attr{qté fournie})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PROJET}.\n    \\item Le champ \\emph{réf. pièce} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PIÈCE}.\n    \\item Le champ \\emph{num. société} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{SOCIÉTÉ}.\n    \\item Le champ \\emph{qté fournie} était déjà un simple attribut de l'association \\emph{FOURNIR}.\n  \\end{itemize}\n\n  \\item \\relat{PIÈCE} (\\prim{réf. pièce}, \\attr{libellé pièce})\n  \\begin{itemize}\n    \\item Le champ \\emph{réf. pièce} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PIÈCE}.\n    \\item Le champ \\emph{libellé pièce} était déjà un simple attribut de l'entité \\emph{PIÈCE}.\n  \\end{itemize}\n\n  \\item \\relat{PROJET} (\\prim{num. projet}, \\attr{nom projet}, \\foreign{matricule responsable?})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. projet} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{PROJET}.\n    \\item Le champ \\emph{nom projet} était déjà un simple attribut de l'entité \\emph{PROJET}.\n    \\item Le champ à saisie facultative \\emph{matricule responsable} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{DIRIGER} à partir de l'entité \\emph{EMPLOYÉ} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{REQUÉRIR} (\\foreign{\\prim{num. projet}}, \\foreign{\\prim{réf. pièce}}, \\attr{qté requise})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PROJET}.\n    \\item Le champ \\emph{réf. pièce} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PIÈCE}.\n    \\item Le champ \\emph{qté requise} était déjà un simple attribut de l'association \\emph{REQUÉRIR}.\n  \\end{itemize}\n\n  \\item \\relat{SOCIÉTÉ} (\\prim{num. société}, \\attr{raison sociale}, \\foreign{num. société mère?})\n  \\begin{itemize}\n    \\item Le champ \\emph{num. société} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{SOCIÉTÉ}.\n    \\item Le champ \\emph{raison sociale} était déjà un simple attribut de l'entité \\emph{SOCIÉTÉ}.\n    \\item Le champ à saisie facultative \\emph{num. société mère} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{CONTRÔLER} à partir de l'entité \\emph{SOCIÉTÉ} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{TRAVAILLER} (\\foreign{\\prim{matricule}}, \\foreign{\\prim{num. projet}})\n  \\begin{itemize}\n    \\item Le champ \\emph{matricule} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{EMPLOYÉ}.\n    \\item Le champ \\emph{num. projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{PROJET}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/landing/mld/landing_mld.txt",
    "content": "- AYANT-DROIT (_#matricule_, _nom ayant-droit_, lien)\n  - Le champ « matricule » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « EMPLOYÉ » pour renforcer l'identifiant.\n  - Le champ « nom ayant-droit » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « AYANT-DROIT ».\n  - Le champ « lien » était déjà un simple attribut de l'entité « AYANT-DROIT ».\n\n- COMPOSER (_#réf. pièce composée_, _#réf. pièce composante_, quantité)\n  - Les champs « réf. pièce composée » et « réf. pièce composante » constituent la clé primaire de la table. Ce sont des clés étrangères qui ont migré directement à partir de l'entité « PIÈCE ».\n  - Le champ « quantité » était déjà un simple attribut de l'association « COMPOSER ».\n\n- DÉPARTEMENT (_num. département_, nom département)\n  - Le champ « num. département » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « DÉPARTEMENT ».\n  - Le champ « nom département » était déjà un simple attribut de l'entité « DÉPARTEMENT ».\n\n- EMPLOYÉ (_matricule_, nom employé, #num. département!)\n  - Le champ « matricule » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « EMPLOYÉ ».\n  - Le champ « nom employé » était déjà un simple attribut de l'entité « EMPLOYÉ ».\n  - Le champ à saisie obligatoire « num. département » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « EMPLOYER » à partir de l'entité « DÉPARTEMENT » en perdant son caractère identifiant.\n\n- FOURNIR (_#num. projet_, _#réf. pièce_, _#num. société_, qté fournie)\n  - Le champ « num. projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PROJET ».\n  - Le champ « réf. pièce » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PIÈCE ».\n  - Le champ « num. société » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « SOCIÉTÉ ».\n  - Le champ « qté fournie » était déjà un simple attribut de l'association « FOURNIR ».\n\n- PIÈCE (_réf. pièce_, libellé pièce)\n  - Le champ « réf. pièce » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PIÈCE ».\n  - Le champ « libellé pièce » était déjà un simple attribut de l'entité « PIÈCE ».\n\n- PROJET (_num. projet_, nom projet, #matricule responsable?)\n  - Le champ « num. projet » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « PROJET ».\n  - Le champ « nom projet » était déjà un simple attribut de l'entité « PROJET ».\n  - Le champ à saisie facultative « matricule responsable » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « DIRIGER » à partir de l'entité « EMPLOYÉ » en perdant son caractère identifiant.\n\n- REQUÉRIR (_#num. projet_, _#réf. pièce_, qté requise)\n  - Le champ « num. projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PROJET ».\n  - Le champ « réf. pièce » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PIÈCE ».\n  - Le champ « qté requise » était déjà un simple attribut de l'association « REQUÉRIR ».\n\n- SOCIÉTÉ (_num. société_, raison sociale, #num. société mère?)\n  - Le champ « num. société » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « SOCIÉTÉ ».\n  - Le champ « raison sociale » était déjà un simple attribut de l'entité « SOCIÉTÉ ».\n  - Le champ à saisie facultative « num. société mère » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « CONTRÔLER » à partir de l'entité « SOCIÉTÉ » en perdant son caractère identifiant.\n\n- TRAVAILLER (_#matricule_, _#num. projet_)\n  - Le champ « matricule » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « EMPLOYÉ ».\n  - Le champ « num. projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « PROJET ».\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_create_df_arrows=across.mcd",
    "content": "AYANT-DROIT: nom ayant-droit, lien\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nPIÈCE: réf. pièce, libellé pièce\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\n\nDF, _11 AYANT-DROIT, 0N> EMPLOYÉ\nEMPLOYÉ: matricule, nom employé\nPROJET: num. projet, nom projet\nFOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N> DÉPARTEMENT\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_drown.mcd",
    "content": "ENTITÉ 01_: at 01 1, at 01 2\nASSOC 07_, 0N [rôle 1] ENTITÉ 03_, 01 ENTITÉ 04_\nASSOC 08_, 1N ENTITÉ 04_, 0N ENTITÉ 02_: at 08 1\nENTITÉ 02_: at 02 1, at 02 2\nASSOC 09_, 0N [rôle 1] ENTITÉ 02_, 0N [rôle 2] ENTITÉ 02_: at 09 1\n\nDF, _11 ENTITÉ 01_, 0N ENTITÉ 03_\nENTITÉ 03_: at 03 1, at 03 2\nENTITÉ 04_: at 04 1, at 04 2\nASSOC 11_, 1N ENTITÉ 04_, 1N ENTITÉ 02_, 1N ENTITÉ 06_: at 11 1\n\nENTITÉ 05_: at 05 1, at 05 2\nASSOC 12_, 11 ENTITÉ 03_, 1N ENTITÉ 05_\nASSOC 13_, 0N ENTITÉ 03_, 1N ENTITÉ 04_\nENTITÉ 06_: at 06 1, at 06 2\nASSOC 14_, 0N< [rôle 1] ENTITÉ 06_, 01 [rôle 2] ENTITÉ 06_\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..ENTITÉ 02_, ->ASSOC 08_, --ASSOC 11_, ENTITÉ 04_\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=2,weak.mcd",
    "content": ":\n:\n:\n:\n:\n:\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\nDÉPARTEMENT: num. département, nom département\nDF, _11 TRAVAILLER, 0N EMPLOYÉ\nTRAVAILLER:\nDF, _11 TRAVAILLER, 1N PROJET\n:\nDF, _11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\n\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nEMPLOYÉ: matricule, nom employé\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nPROJET: num. projet, nom projet\nDF, _11 FOURNIR, 1N PROJET\nFOURNIR: _qté fournie\n:\n\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\n:\nDF, _11 REQUÉRIR, 1N PROJET\nREQUÉRIR: _qté requise\nDF, _11 FOURNIR, 1N PIÈCE\n:\n\n:\nAYANT-DROIT: nom ayant-droit, lien\n:\n:\nDF, _11 REQUÉRIR, 0N PIÈCE\nPIÈCE: réf. pièce, libellé pièce\nDF, _11 COMPOSER, 0N [composée] PIÈCE\n\n:\n:\n:\n:\n:\nDF, _11 COMPOSER, 0N [composante] PIÈCE\nCOMPOSER: _quantité\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=2.5,weak.mcd",
    "content": "COMPOSER: _quantité\nDF, _11 COMPOSER, 0N [composée] PIÈCE\n:\nDF, _11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n:\n\nDF, _11 COMPOSER, 0N [composante] PIÈCE\nPIÈCE: réf. pièce, libellé pièce\nDF, _11 FOURNIR, 1N PIÈCE\nFOURNIR: _qté fournie\n:\n:\n:\n\n:\nDF, _11 REQUÉRIR, 0N PIÈCE\nREQUÉRIR: _qté requise\nDF, _11 FOURNIR, 1N PROJET\n:\n:\n:\n\n:\n:\nDF, _11 REQUÉRIR, 1N PROJET\nPROJET: num. projet, nom projet\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\n:\n:\n\n:\n:\n:\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nEMPLOYÉ: matricule, nom employé\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nDÉPARTEMENT: num. département, nom département\n\n:\n:\n:\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nAYANT-DROIT: nom ayant-droit, lien\n:\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=2.5.mcd",
    "content": "COMPOSER: id. composer, quantité\nDF, 11 COMPOSER, 0N [composée] PIÈCE\n:\nDF, 11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n:\n\nDF, 11 COMPOSER, 0N [composante] PIÈCE\nPIÈCE: réf. pièce, libellé pièce\nDF, 11 FOURNIR, 1N PIÈCE\nFOURNIR: id. fournir, qté fournie\n:\n:\n:\n\n:\nDF, 11 REQUÉRIR, 0N PIÈCE\nREQUÉRIR: id. requérir, qté requise\nDF, 11 FOURNIR, 1N PROJET\n:\n:\n:\n\n:\n:\nDF, 11 REQUÉRIR, 1N PROJET\nPROJET: num. projet, nom projet\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\n:\n:\n\n:\n:\n:\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nEMPLOYÉ: matricule, nom employé\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nDÉPARTEMENT: num. département, nom département\n\n:\n:\n:\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\nAYANT-DROIT: nom ayant-droit, lien\n:\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=2.mcd",
    "content": ":\n:\n:\n:\n:\n:\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\nDÉPARTEMENT: num. département, nom département\nDF, 11 TRAVAILLER, 0N EMPLOYÉ\nTRAVAILLER: id. travailler\nDF, 11 TRAVAILLER, 1N PROJET\n:\nDF, 11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\n\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nEMPLOYÉ: matricule, nom employé\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\nPROJET: num. projet, nom projet\nDF, 11 FOURNIR, 1N PROJET\nFOURNIR: id. fournir, qté fournie\n:\n\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\n:\nDF, 11 REQUÉRIR, 1N PROJET\nREQUÉRIR: id. requérir, qté requise\nDF, 11 FOURNIR, 1N PIÈCE\n:\n\n:\nAYANT-DROIT: nom ayant-droit, lien\n:\n:\nDF, 11 REQUÉRIR, 0N PIÈCE\nPIÈCE: réf. pièce, libellé pièce\nDF, 11 COMPOSER, 0N [composée] PIÈCE\n\n:\n:\n:\n:\n:\nDF, 11 COMPOSER, 0N [composante] PIÈCE\nCOMPOSER: id. composer, quantité\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=3,weak.mcd",
    "content": ":\n:\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\nPIÈCE: réf. pièce, libellé pièce\nDF, _11 FOURNIR, 1N PIÈCE\n:\n:\n\n:\n:\n:\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nFOURNIR: _qté fournie\nDF, _11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\n\n:\n:\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nPROJET: num. projet, nom projet\nDF, _11 FOURNIR, 1N PROJET\n:\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nEMPLOYÉ: matricule, nom employé\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\n:\n:\n:\n\n:\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\n:\n:\n:\n:\n\n:\n:\nAYANT-DROIT: nom ayant-droit, lien\n:\n:\n:\n:\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_explode_arity=3.mcd",
    "content": ":\n:\nCOMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité\nPIÈCE: réf. pièce, libellé pièce\nDF, 11 FOURNIR, 1N PIÈCE\n:\n:\n\n:\n:\n:\nREQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise\nFOURNIR: id. fournir, qté fournie\nDF, 11 FOURNIR, 1N SOCIÉTÉ\nSOCIÉTÉ: num. société, raison sociale\n\n:\n:\nTRAVAILLER, 0N EMPLOYÉ, 1N PROJET\nPROJET: num. projet, nom projet\nDF, 11 FOURNIR, 1N PROJET\n:\nCONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ\n\nDÉPARTEMENT: num. département, nom département\nEMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT\nEMPLOYÉ: matricule, nom employé\nDIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET\n:\n:\n:\n\n:\n:\nDF, _11 AYANT-DROIT, 0N EMPLOYÉ\n:\n:\n:\n:\n\n:\n:\nAYANT-DROIT: nom ayant-droit, lien\n:\n:\n:\n:\n\n  (I) [Les pièces fournies par une société pour un projet font partie de celles qu'il requiert.] ..PIÈCE, ->REQUÉRIR, --FOURNIR, PROJET\n"
  },
  {
    "path": "test/zoo/landing/rewritten/landing_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/_minimal.mcd",
    "content": "A:\n"
  },
  {
    "path": "test/zoo/minimal/ddl/minimal_ddl.d2",
    "content": "\n"
  },
  {
    "path": "test/zoo/minimal/ddl/minimal_ddl.dbml",
    "content": "\n"
  },
  {
    "path": "test/zoo/minimal/ddl/minimal_ddl.sql",
    "content": ""
  },
  {
    "path": "test/zoo/minimal/exported/minimal_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Associative entities\n  1 [label=\"A\",shape=Mdiamond]\n}"
  },
  {
    "path": "test/zoo/minimal/exported/minimal_erd_chen.txt",
    "content": "\n"
  },
  {
    "path": "test/zoo/minimal/exported/minimal_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >A</font>\n            </td>\n        </tr>\n\n    </table>\n>]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n}"
  },
  {
    "path": "test/zoo/minimal/exported/minimal_erd_crow.mmd",
    "content": "erDiagram\n  A {\n  }"
  },
  {
    "path": "test/zoo/minimal/exported/minimal_uml.puml",
    "content": "@startuml \"minimal\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"A\") {\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"minimal_rw_drown.svg\"/></center><figcaption>MCD <i>minimal</i></figcaption></figure>\n<div class=\"mld\">\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>A</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_mld.mcd",
    "content": "%%mocodo\n:\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_mld.md",
    "content": "<br>\n----\n\n\n**NB.** La table _A_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{minimal}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/minimal/mld/minimal_mld.txt",
    "content": "<br>\n--------------------------------------------------------------------------------\n\nNB. La table « A » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_drown.mcd",
    "content": "ENTITÉ 1_:\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/minimal/rewritten/minimal_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/_protected_0.mcd",
    "content": "% source: https://www.developpez.net/forums/d962823/general-developpement/alm/methodes/merise/regles-passage-mcd-mld-associations-binaires/\nAgence: id. agence, nom agence\n+Superviser, 1N Direction régionale, 01 Agence\n+Direction régionale: id. dir., nom dir.\n"
  },
  {
    "path": "test/zoo/protected/ddl/protected_0_ddl.d2",
    "content": "\"Agence\": { shape: sql_table\n  \"id. agence\": VARCHAR(42) {constraint: PK}\n  \"nom agence\": VARCHAR(42) \n}\n\n\"Direction régionale\": { shape: sql_table\n  \"id. dir.\": VARCHAR(42) {constraint: PK}\n  \"nom dir.\": VARCHAR(42) \n}\n\n\"Superviser\": { shape: sql_table\n  \"id. agence\": VARCHAR(42) {constraint: [PK; FK]}\n  \"id. dir.\":   VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Superviser\".\"id. agence\" -> \"Agence\".\"id. agence\"\n\"Superviser\".\"id. dir.\" -> \"Direction régionale\".\"id. dir.\"\n"
  },
  {
    "path": "test/zoo/protected/ddl/protected_0_ddl.dbml",
    "content": "Table \"Agence\" {\n  \"id. agence\" VARCHAR(42) [pk, NOT NULL]\n  \"nom agence\" VARCHAR(42)\n}\n\nTable \"Direction régionale\" {\n  \"id. dir.\" VARCHAR(42) [pk, NOT NULL]\n  \"nom dir.\" VARCHAR(42)\n}\n\nTable \"Superviser\" {\n  \"id. agence\" VARCHAR(42) [pk, NOT NULL]\n  \"id. dir.\"   VARCHAR(42) [NOT NULL]\n}\n\nRef:\"Superviser\".\"id. agence\" > \"Agence\".\"id. agence\"\nRef:\"Superviser\".\"id. dir.\" > \"Direction régionale\".\"id. dir.\"\n"
  },
  {
    "path": "test/zoo/protected/ddl/protected_0_ddl.sql",
    "content": "CREATE TABLE AGENCE (\n  PRIMARY KEY (id_agence),\n  id_agence  VARCHAR(8) NOT NULL,\n  nom_agence VARCHAR(255)\n);\n\nCREATE TABLE DIRECTION_REGIONALE (\n  PRIMARY KEY (id_dir),\n  id_dir  VARCHAR(8) NOT NULL,\n  nom_dir VARCHAR(255)\n);\n\nCREATE TABLE SUPERVISER (\n  PRIMARY KEY (id_agence),\n  id_agence VARCHAR(8) NOT NULL,\n  id_dir    VARCHAR(8) NOT NULL\n);\n\nALTER TABLE SUPERVISER ADD FOREIGN KEY (id_dir) REFERENCES DIRECTION_REGIONALE (id_dir);\nALTER TABLE SUPERVISER ADD FOREIGN KEY (id_agence) REFERENCES AGENCE (id_agence);\n"
  },
  {
    "path": "test/zoo/protected/exported/protected_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Agence\"]\n  5 [label=\"Direction\\nrégionale\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"nom\\nagence\"]\n  7 [label=\"nom dir.\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>id.<br/>agence</u>>]\n  6 [label=<<u>id. dir.</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Superviser\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 6\n  5 -- 7\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  5 -- 4\n  edge [headlabel=N]\n  1 -- 4 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/protected/exported/protected_0_erd_chen.txt",
    "content": "[Agence] --N-- <Superviser>\n[Direction régionale] ==1== <Superviser>\n"
  },
  {
    "path": "test/zoo/protected/exported/protected_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Agence</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">id. agence</td></tr>\n        <tr><td> </td><td align=\"left\">nom agence</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Direction régionale</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">id. dir.</td></tr>\n        <tr><td> </td><td align=\"left\">nom dir.</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"crowtee\" arrowtail=\"teeodot\" label=\"Superviser\"]\n}"
  },
  {
    "path": "test/zoo/protected/exported/protected_0_erd_crow.mmd",
    "content": "erDiagram\n  Agence {\n    TYPE id_agence PK\n    TYPE nom_agence\n  }\n  Direction_regionale {\n    TYPE id_dir PK\n    TYPE nom_dir\n  }\n  Direction_regionale |o--|{ Agence: Superviser"
  },
  {
    "path": "test/zoo/protected/exported/protected_0_uml.puml",
    "content": "@startuml \"protected\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Agence\") {\n    {field} + pk(id. agence)\n    {field} + nom agence\n}\n\n\"Direction régionale\" \"1..*\" --- \"1..*\" \"Agence\": \"Superviser\"\n\nTable(\"Direction régionale\") {\n    {field} + pk(id. dir.)\n    {field} + nom dir.\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAgence\tid. agence\t!\t\tprimary_key\tTrue\t\t\t\t\t\nAgence\tnom agence\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nDirection régionale\tid. dir.\t!\t\tprimary_key\tTrue\t\t\t\t\t\nDirection régionale\tnom dir.\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSuperviser\tid. agence\t!\t\tprimary_foreign_key\tTrue\tAgence\tAgence\tSuperviser\t\t\nSuperviser\tid. dir.\t!\t\tstopped_foreign_key\tFalse\tDirection régionale\tDirection régionale\tSuperviser\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Direction régionale\" -> \"Superviser\"\n  \"Agence\" -> \"Superviser\"\n}\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"protected_0_mld.svg\"/></center><figcaption>MCD <i>protected</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Agence</span> (\n    <span class='primary'>id. agence</span>,\n    <span class='normal'>nom agence</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>id. agence</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Agence</i>.</li>\n    <li>Le champ <i>nom agence</i> était déjà un simple attribut de l'entité <i>Agence</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Direction régionale</span> (\n    <span class='primary'>id. dir.</span>,\n    <span class='normal'>nom dir.</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>id. dir.</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Direction régionale</i>.</li>\n    <li>Le champ <i>nom dir.</i> était déjà un simple attribut de l'entité <i>Direction régionale</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Superviser</span> (\n    <span class='foreign primary'>#id. agence</span>,\n    <span class='foreign'>#id. dir.!</span>\n  )</summary>\n  <ul>\n    <li><strong>Avertissement.</strong> Table résultant de la conversion forcée d'une association DF.</li>\n    <li>Le champ <i>id. agence</i> constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Agence</i>.</li>\n    <li>Le champ à saisie obligatoire <i>id. dir.</i> est une clé étrangère. Il a migré directement à partir de l'entité <i>Direction régionale</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_mld.mcd",
    "content": "%%mocodo\n:\nAgence: id. agence, nom agence\n:\nSuperviser: #id. agence > Agence > id. agence, #id. dir. > Direction régionale > id. dir.\n:\nDirection régionale: id. dir., nom dir.\n:\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_mld.md",
    "content": "- **Agence** (<u>id. agence</u>, nom agence)\n  - Le champ _id. agence_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Agence_.\n  - Le champ _nom agence_ était déjà un simple attribut de l'entité _Agence_.\n\n- **Direction régionale** (<u>id. dir.</u>, nom dir.)\n  - Le champ _id. dir._ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Direction régionale_.\n  - Le champ _nom dir._ était déjà un simple attribut de l'entité _Direction régionale_.\n\n- **Superviser** (<u>_#id. agence_</u>, _#id. dir.!_)\n  - **Avertissement.** Table résultant de la conversion forcée d'une association DF.\n  - Le champ _id. agence_ constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Agence_.\n  - Le champ à saisie obligatoire _id. dir._ est une clé étrangère. Il a migré directement à partir de l'entité _Direction régionale_ en perdant son caractère identifiant.\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{protected}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Agence} (\\prim{id. agence}, \\attr{nom agence})\n  \\begin{itemize}\n    \\item Le champ \\emph{id. agence} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Agence}.\n    \\item Le champ \\emph{nom agence} était déjà un simple attribut de l'entité \\emph{Agence}.\n  \\end{itemize}\n\n  \\item \\relat{Direction régionale} (\\prim{id. dir.}, \\attr{nom dir.})\n  \\begin{itemize}\n    \\item Le champ \\emph{id. dir.} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Direction régionale}.\n    \\item Le champ \\emph{nom dir.} était déjà un simple attribut de l'entité \\emph{Direction régionale}.\n  \\end{itemize}\n\n  \\item \\relat{Superviser} (\\foreign{\\prim{id. agence}}, \\foreign{id. dir.!})\n  \\begin{itemize}\n    \\item \\paragraph{Avertissement.} Table résultant de la conversion forcée d'une association DF.\n    \\item Le champ \\emph{id. agence} constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Agence}.\n    \\item Le champ à saisie obligatoire \\emph{id. dir.} est une clé étrangère. Il a migré directement à partir de l'entité \\emph{Direction régionale} en perdant son caractère identifiant.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/protected/mld/protected_0_mld.txt",
    "content": "- Agence (_id. agence_, nom agence)\n  - Le champ « id. agence » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Agence ».\n  - Le champ « nom agence » était déjà un simple attribut de l'entité « Agence ».\n\n- Direction régionale (_id. dir._, nom dir.)\n  - Le champ « id. dir. » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Direction régionale ».\n  - Le champ « nom dir. » était déjà un simple attribut de l'entité « Direction régionale ».\n\n- Superviser (_#id. agence_, #id. dir.!)\n  - Avertissement. Table résultant de la conversion forcée d'une association DF.\n  - Le champ « id. agence » constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Agence ».\n  - Le champ à saisie obligatoire « id. dir. » est une clé étrangère. Il a migré directement à partir de l'entité « Direction régionale » en perdant son caractère identifiant.\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_drown.mcd",
    "content": "% source: https://www.developpez.net/forums/d962823/general-developpement/alm/methodes/merise/regles-passage-mcd-mld-associations-binaires/\nENTITÉ 1_: at 1 1, at 1 2\n+ASSOC 3_, 1N ENTITÉ 2_, 01 ENTITÉ 1_\n+ENTITÉ 2_: at 2 1, at 2 2\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/protected/rewritten/protected_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/_reflexive_0.mcd",
    "content": "PIÈCE: pièce\nCOMPOSER, 0N [composante] PIÈCE, 0N [composée] PIÈCE\nHOMME: Num. SS, Nom, Prénom\nENGENDRER, 0N [père] HOMME, 01 [fils] HOMME\n"
  },
  {
    "path": "test/zoo/reflexive/ddl/reflexive_0_ddl.d2",
    "content": "\"COMPOSER\": { shape: sql_table\n  \"pièce composante\": VARCHAR(42) {constraint: PK}\n  \"pièce composée\":   VARCHAR(42) {constraint: PK}\n}\n\n\"HOMME\": { shape: sql_table\n  \"Num. SS\":      VARCHAR(42) {constraint: PK}\n  \"Nom\":          VARCHAR(42) \n  \"Prénom\":       VARCHAR(42) \n  \"Num. SS père\": VARCHAR(42) {constraint: [FK; \"NULL\"]}\n}\n\n\"HOMME\".\"Num. SS père\" -> \"HOMME\".\"Num. SS\"\n"
  },
  {
    "path": "test/zoo/reflexive/ddl/reflexive_0_ddl.dbml",
    "content": "Table \"COMPOSER\" {\n  \"pièce composante\" VARCHAR(42) [NOT NULL]\n  \"pièce composée\"   VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"pièce composante\", \"pièce composée\") [pk]\n  }\n}\n\nTable \"HOMME\" {\n  \"Num. SS\"      VARCHAR(42) [pk, NOT NULL]\n  \"Nom\"          VARCHAR(42)\n  \"Prénom\"       VARCHAR(42)\n  \"Num. SS père\" VARCHAR(42) [\"NULL\"]\n}\n\nRef:\"HOMME\".\"Num. SS père\" > \"HOMME\".\"Num. SS\"\n"
  },
  {
    "path": "test/zoo/reflexive/ddl/reflexive_0_ddl.sql",
    "content": "CREATE TABLE COMPOSER (\n  PRIMARY KEY (piece_composante, piece_composee),\n  piece_composante VARCHAR(42) NOT NULL,\n  piece_composee   VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE HOMME (\n  PRIMARY KEY (num_ss),\n  num_ss      VARCHAR(8) NOT NULL,\n  nom         VARCHAR(255),\n  prenom      VARCHAR(255),\n  num_ss_pere VARCHAR(8) NULL\n);\n\nALTER TABLE HOMME ADD FOREIGN KEY (num_ss_pere) REFERENCES HOMME (num_ss);\n"
  },
  {
    "path": "test/zoo/reflexive/exported/reflexive_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"PIÈCE\"]\n  4 [label=\"HOMME\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"Nom\"]\n  7 [label=\"Prénom\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>pièce</u>>]\n  5 [label=<<u>Num. SS</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"COMPOSER\"]\n  8 [label=\"ENGENDRER\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 5\n  4 -- 6\n  4 -- 7\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  4 -- 8 [color=\"#000000\"]\n  edge [headlabel=M]\n  1 -- 3 [color=\"#000000\"]\n  edge [headlabel=N]\n  3 -- 1 [color=\"#000000\"]\n  8 -- 4 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/reflexive/exported/reflexive_0_erd_chen.txt",
    "content": "[HOMME] --1-- <ENGENDRER>\n[HOMME] --N-- <ENGENDRER>\n[PIÈCE] --M-- <COMPOSER>\n[PIÈCE] --N-- <COMPOSER>\n"
  },
  {
    "path": "test/zoo/reflexive/exported/reflexive_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >PIÈCE</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">pièce</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >HOMME</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">Num. SS</td></tr>\n        <tr><td> </td><td align=\"left\">Nom</td></tr>\n        <tr><td> </td><td align=\"left\">Prénom</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 1 [arrowhead=\"crowodot\" arrowtail=\"crowodot\" label=\"COMPOSER\"]\n  2 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teeodot\" label=\"ENGENDRER\"]\n}"
  },
  {
    "path": "test/zoo/reflexive/exported/reflexive_0_erd_crow.mmd",
    "content": "erDiagram\n  PIECE {\n    TYPE piece PK\n  }\n  HOMME {\n    TYPE Num_SS PK\n    TYPE Nom\n    TYPE Prenom\n  }\n  PIECE }o--o{ PIECE: COMPOSER\n  HOMME |o--o{ HOMME: ENGENDRER"
  },
  {
    "path": "test/zoo/reflexive/exported/reflexive_0_uml.puml",
    "content": "@startuml \"reflexive\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"PIÈCE\") {\n    {field} + pk(pièce)\n}\n\n\"PIÈCE\" \"*\" --- \"*\" \"PIÈCE\": \"COMPOSER\"\n\nTable(\"HOMME\") {\n    {field} + pk(Num. SS)\n    {field} + Nom\n    {field} + Prénom\n}\n\n\"HOMME\" \"1..*\" --- \"*\" \"HOMME\": \"ENGENDRER\"\n\n@enduml\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nCOMPOSER\tpièce\t!\t\tprimary_ex_foreign_key\tTrue\tPIÈCE\tPIÈCE\tCOMPOSER\t\tcomposante\nCOMPOSER\tpièce\t!\t\tprimary_ex_foreign_key\tTrue\tPIÈCE\tPIÈCE\tCOMPOSER\t\tcomposée\nHOMME\tNum. SS\t!\t\tprimary_key\tTrue\t\t\t\t\t\nHOMME\tNom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nHOMME\tPrénom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nHOMME\tNum. SS\t?\t\tforeign_key\tFalse\tHOMME\tHOMME\tENGENDRER\t\tpère\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"HOMME\" -> \"HOMME\"\n}\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"reflexive_0_mld.svg\"/></center><figcaption>MCD <i>reflexive</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>COMPOSER</span> (\n    <span class='primary'>pièce composante</span>,\n    <span class='primary'>pièce composée</span>\n  )</summary>\n  <ul>\n    <li>Les champs <i>pièce composante</i> et <i>pièce composée</i> constituent la clé primaire de la table. Leur table d'origine (<i>PIÈCE</i>) ayant été supprimée, ils ne sont pas considérés comme clés étrangères.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>HOMME</span> (\n    <span class='primary'>Num. SS</span>,\n    <span class='normal'>Nom</span>,\n    <span class='normal'>Prénom</span>,\n    <span class='foreign'>#Num. SS père?</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>Num. SS</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>HOMME</i>.</li>\n    <li>Les champs <i>Nom</i> et <i>Prénom</i> étaient déjà de simples attributs de l'entité <i>HOMME</i>.</li>\n    <li>Le champ à saisie facultative <i>Num. SS père</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>ENGENDRER</i> à partir de l'entité <i>HOMME</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>PIÈCE</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_mld.mcd",
    "content": "%%mocodo\n:\nCOMPOSER: pièce composante, _pièce composée\n:\nHOMME: Num. SS, Nom, Prénom, #Num. SS père > HOMME > Num. SS\n:\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_mld.md",
    "content": "- **COMPOSER** (<u>pièce composante</u>, <u>pièce composée</u>)\n  - Les champs _pièce composante_ et _pièce composée_ constituent la clé primaire de la table. Leur table d'origine (_PIÈCE_) ayant été supprimée, ils ne sont pas considérés comme clés étrangères.\n\n- **HOMME** (<u>Num. SS</u>, Nom, Prénom, _#Num. SS père?_)\n  - Le champ _Num. SS_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _HOMME_.\n  - Les champs _Nom_ et _Prénom_ étaient déjà de simples attributs de l'entité _HOMME_.\n  - Le champ à saisie facultative _Num. SS père_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _ENGENDRER_ à partir de l'entité _HOMME_ en perdant son caractère identifiant.\n<br>\n----\n\n\n**NB.** La table _PIÈCE_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{reflexive}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{COMPOSER} (\\prim{pièce composante}, \\prim{pièce composée})\n  \\begin{itemize}\n    \\item Les champs \\emph{pièce composante} et \\emph{pièce composée} constituent la clé primaire de la table. Leur table d'origine (\\emph{PIÈCE}) ayant été supprimée, ils ne sont pas considérés comme clés étrangères.\n  \\end{itemize}\n\n  \\item \\relat{HOMME} (\\prim{Num. SS}, \\attr{Nom}, \\attr{Prénom}, \\foreign{Num. SS père?})\n  \\begin{itemize}\n    \\item Le champ \\emph{Num. SS} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{HOMME}.\n    \\item Les champs \\emph{Nom} et \\emph{Prénom} étaient déjà de simples attributs de l'entité \\emph{HOMME}.\n    \\item Le champ à saisie facultative \\emph{Num. SS père} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{ENGENDRER} à partir de l'entité \\emph{HOMME} en perdant son caractère identifiant.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/reflexive/mld/reflexive_0_mld.txt",
    "content": "- COMPOSER (_pièce composante_, _pièce composée_)\n  - Les champs « pièce composante » et « pièce composée » constituent la clé primaire de la table. Leur table d'origine (« PIÈCE ») ayant été supprimée, ils ne sont pas considérés comme clés étrangères.\n\n- HOMME (_Num. SS_, Nom, Prénom, #Num. SS père?)\n  - Le champ « Num. SS » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « HOMME ».\n  - Les champs « Nom » et « Prénom » étaient déjà de simples attributs de l'entité « HOMME ».\n  - Le champ à saisie facultative « Num. SS père » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « ENGENDRER » à partir de l'entité « HOMME » en perdant son caractère identifiant.\n<br>\n--------------------------------------------------------------------------------\n\nNB. La table « PIÈCE » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nASSOC 3_, 0N [rôle 1] ENTITÉ 1_, 0N [rôle 2] ENTITÉ 1_\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\nASSOC 4_, 0N [rôle 1] ENTITÉ 2_, 01 [rôle 2] ENTITÉ 2_\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=2,weak.mcd",
    "content": "PIÈCE: pièce\nDF, _11 COMPOSER, 0N [composée] PIÈCE\nENGENDRER, 0N [père] HOMME, 01 [fils] HOMME\n\nDF, _11 COMPOSER, 0N [composante] PIÈCE\nCOMPOSER:\nHOMME: Num. SS, Nom, Prénom\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=2.mcd",
    "content": "PIÈCE: pièce\nDF, 11 COMPOSER, 0N [composée] PIÈCE\nENGENDRER, 0N [père] HOMME, 01 [fils] HOMME\n\nDF, 11 COMPOSER, 0N [composante] PIÈCE\nCOMPOSER: id. composer\nHOMME: Num. SS, Nom, Prénom\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/reflexive/rewritten/reflexive_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/_split.mcd",
    "content": "Bataille: nom bataille, lieu, date\nRécolter, 0N Villageois, 0N Bataille, 11 Trophée\nVillageois: nom villageois, adresse, fonction\n\nTrophée: numéro, type, état\n"
  },
  {
    "path": "test/zoo/split/ddl/split_ddl.d2",
    "content": "\"Bataille\": { shape: sql_table\n  \"nom bataille\": VARCHAR(42) {constraint: PK}\n  \"lieu\":         VARCHAR(42) \n  \"date\":         VARCHAR(42) \n}\n\n\"Trophée\": { shape: sql_table\n  \"numéro\":         VARCHAR(42) {constraint: PK}\n  \"type\":           VARCHAR(42) \n  \"état\":           VARCHAR(42) \n  \"nom villageois\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"nom bataille\":   VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Villageois\": { shape: sql_table\n  \"nom villageois\": VARCHAR(42) {constraint: PK}\n  \"adresse\":        VARCHAR(42) \n  \"fonction\":       VARCHAR(42) \n}\n\n\"Trophée\".\"nom villageois\" -> \"Villageois\".\"nom villageois\"\n\"Trophée\".\"nom bataille\" -> \"Bataille\".\"nom bataille\"\n"
  },
  {
    "path": "test/zoo/split/ddl/split_ddl.dbml",
    "content": "Table \"Bataille\" {\n  \"nom bataille\" VARCHAR(42) [pk, NOT NULL]\n  \"lieu\"         VARCHAR(42)\n  \"date\"         VARCHAR(42)\n}\n\nTable \"Trophée\" {\n  \"numéro\"         VARCHAR(42) [pk, NOT NULL]\n  \"type\"           VARCHAR(42)\n  \"état\"           VARCHAR(42)\n  \"nom villageois\" VARCHAR(42) [NOT NULL]\n  \"nom bataille\"   VARCHAR(42) [NOT NULL]\n}\n\nTable \"Villageois\" {\n  \"nom villageois\" VARCHAR(42) [pk, NOT NULL]\n  \"adresse\"        VARCHAR(42)\n  \"fonction\"       VARCHAR(42)\n}\n\nRef:\"Trophée\".\"nom villageois\" > \"Villageois\".\"nom villageois\"\nRef:\"Trophée\".\"nom bataille\" > \"Bataille\".\"nom bataille\"\n"
  },
  {
    "path": "test/zoo/split/ddl/split_ddl.sql",
    "content": "CREATE TABLE BATAILLE (\n  PRIMARY KEY (nom_bataille),\n  nom_bataille VARCHAR(255) NOT NULL,\n  lieu         VARCHAR(42),\n  date         DATE\n);\n\nCREATE TABLE TROPHEE (\n  PRIMARY KEY (numero),\n  numero         VARCHAR(8) NOT NULL,\n  type           VARCHAR(42),\n  etat           VARCHAR(42),\n  nom_villageois VARCHAR(255) NOT NULL,\n  nom_bataille   VARCHAR(255) NOT NULL\n);\n\nCREATE TABLE VILLAGEOIS (\n  PRIMARY KEY (nom_villageois),\n  nom_villageois VARCHAR(255) NOT NULL,\n  adresse        VARCHAR(30),\n  fonction       VARCHAR(42)\n);\n\nALTER TABLE TROPHEE ADD FOREIGN KEY (nom_bataille) REFERENCES BATAILLE (nom_bataille);\nALTER TABLE TROPHEE ADD FOREIGN KEY (nom_villageois) REFERENCES VILLAGEOIS (nom_villageois);\n"
  },
  {
    "path": "test/zoo/split/exported/split_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Bataille\"]\n  7 [label=\"Villageois\"]\n  6 [label=\"Trophée\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"lieu\"]\n  4 [label=\"date\"]\n  10 [label=\"adresse\"]\n  11 [label=\"fonction\"]\n  13 [label=\"type\"]\n  14 [label=\"état\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>nom<br/>bataille</u>>]\n  9 [label=<<u>nom<br/>villageois</u>>]\n  12 [label=<<u>numéro</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"Récolter\"]\n  8 [label=\"Récolter\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  1 -- 4\n  6 -- 12\n  6 -- 13\n  6 -- 14\n  7 -- 9\n  7 -- 10\n  7 -- 11\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 8 [color=\"#000000\"]\n  7 -- 5 [color=\"#000000\"]\n  edge [headlabel=N]\n  6 -- 5\n  6 -- 8\n}"
  },
  {
    "path": "test/zoo/split/exported/split_erd_chen.txt",
    "content": "[Bataille] --1-- <Récolter>\n[Trophée] ==N== <Récolter>\n[Trophée] ==N== <Récolter>\n[Villageois] --1-- <Récolter>\n"
  },
  {
    "path": "test/zoo/split/exported/split_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Bataille</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">nom bataille</td></tr>\n        <tr><td> </td><td align=\"left\">lieu</td></tr>\n        <tr><td> </td><td align=\"left\">date</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Villageois</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">nom villageois</td></tr>\n        <tr><td> </td><td align=\"left\">adresse</td></tr>\n        <tr><td> </td><td align=\"left\">fonction</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Trophée</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">numéro</td></tr>\n        <tr><td> </td><td align=\"left\">type</td></tr>\n        <tr><td> </td><td align=\"left\">état</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  3 -> 2 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"Récolter\"]\n  3 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowodot\" label=\"Récolter\"]\n}"
  },
  {
    "path": "test/zoo/split/exported/split_erd_crow.mmd",
    "content": "erDiagram\n  Bataille {\n    TYPE nom_bataille PK\n    TYPE lieu\n    TYPE date\n  }\n  Villageois {\n    TYPE nom_villageois PK\n    TYPE adresse\n    TYPE fonction\n  }\n  Trophee {\n    TYPE numero PK\n    TYPE type\n    TYPE etat\n  }\n  Trophee }o--|| Villageois: Recolter\n  Trophee }o--|| Bataille: Recolter"
  },
  {
    "path": "test/zoo/split/exported/split_uml.puml",
    "content": "@startuml \"split\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Bataille\") {\n    {field} + pk(nom bataille)\n    {field} + lieu\n    {field} + date\n}\n\n\"Trophée\" \"*\" --- \"1\" \"Villageois\": \"Récolter0\"\n\n\"Trophée\" \"*\" --- \"1\" \"Bataille\": \"Récolter1\"\n\nTable(\"Villageois\") {\n    {field} + pk(nom villageois)\n    {field} + adresse\n    {field} + fonction\n}\n\nTable(\"Trophée\") {\n    {field} + pk(numéro)\n    {field} + type\n    {field} + état\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/split/mld/split_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nBataille\tnom bataille\t!\t\tprimary_key\tTrue\t\t\t\t\t\nBataille\tlieu\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nBataille\tdate\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTrophée\tnuméro\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTrophée\ttype\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTrophée\tétat\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTrophée\tnom villageois\t!\t\tforeign_key\tFalse\tVillageois\tVillageois\tRécolter\t\t\nTrophée\tnom bataille\t!\t\tforeign_key\tFalse\tBataille\tBataille\tRécolter\t\t\nVillageois\tnom villageois\t!\t\tprimary_key\tTrue\t\t\t\t\t\nVillageois\tadresse\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nVillageois\tfonction\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/split/mld/split_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Bataille\" -> \"Trophée\"\n  \"Villageois\" -> \"Trophée\"\n}\n"
  },
  {
    "path": "test/zoo/split/mld/split_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"split_mld.svg\"/></center><figcaption>MCD <i>split</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Bataille</span> (\n    <span class='primary'>nom bataille</span>,\n    <span class='normal'>lieu</span>,\n    <span class='normal'>date</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>nom bataille</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Bataille</i>.</li>\n    <li>Les champs <i>lieu</i> et <i>date</i> étaient déjà de simples attributs de l'entité <i>Bataille</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Trophée</span> (\n    <span class='primary'>numéro</span>,\n    <span class='normal'>type</span>,\n    <span class='normal'>état</span>,\n    <span class='foreign'>#nom villageois!</span>,\n    <span class='foreign'>#nom bataille!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>numéro</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Trophée</i>.</li>\n    <li>Les champs <i>type</i> et <i>état</i> étaient déjà de simples attributs de l'entité <i>Trophée</i>.</li>\n    <li>Le champ à saisie obligatoire <i>nom villageois</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Récolter</i> à partir de l'entité <i>Villageois</i> en perdant son caractère identifiant.</li>\n    <li>Le champ à saisie obligatoire <i>nom bataille</i> est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle <i>Récolter</i> à partir de l'entité <i>Bataille</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Villageois</span> (\n    <span class='primary'>nom villageois</span>,\n    <span class='normal'>adresse</span>,\n    <span class='normal'>fonction</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>nom villageois</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Villageois</i>.</li>\n    <li>Les champs <i>adresse</i> et <i>fonction</i> étaient déjà de simples attributs de l'entité <i>Villageois</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/split/mld/split_mld.mcd",
    "content": "%%mocodo\n:\nBataille: nom bataille, lieu, date\n:::\nVillageois: nom villageois, adresse, fonction\n:\n\n\n:::\nTrophée: numéro, type, état, #nom villageois > Villageois > nom villageois, #nom bataille > Bataille > nom bataille\n:::\n"
  },
  {
    "path": "test/zoo/split/mld/split_mld.md",
    "content": "- **Bataille** (<u>nom bataille</u>, lieu, date)\n  - Le champ _nom bataille_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Bataille_.\n  - Les champs _lieu_ et _date_ étaient déjà de simples attributs de l'entité _Bataille_.\n\n- **Trophée** (<u>numéro</u>, type, état, _#nom villageois!_, _#nom bataille!_)\n  - Le champ _numéro_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Trophée_.\n  - Les champs _type_ et _état_ étaient déjà de simples attributs de l'entité _Trophée_.\n  - Le champ à saisie obligatoire _nom villageois_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Récolter_ à partir de l'entité _Villageois_ en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire _nom bataille_ est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle _Récolter_ à partir de l'entité _Bataille_ en perdant son caractère identifiant.\n\n- **Villageois** (<u>nom villageois</u>, adresse, fonction)\n  - Le champ _nom villageois_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Villageois_.\n  - Les champs _adresse_ et _fonction_ étaient déjà de simples attributs de l'entité _Villageois_.\n"
  },
  {
    "path": "test/zoo/split/mld/split_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{split}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Bataille} (\\prim{nom bataille}, \\attr{lieu}, \\attr{date})\n  \\begin{itemize}\n    \\item Le champ \\emph{nom bataille} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Bataille}.\n    \\item Les champs \\emph{lieu} et \\emph{date} étaient déjà de simples attributs de l'entité \\emph{Bataille}.\n  \\end{itemize}\n\n  \\item \\relat{Trophée} (\\prim{numéro}, \\attr{type}, \\attr{état}, \\foreign{nom villageois!}, \\foreign{nom bataille!})\n  \\begin{itemize}\n    \\item Le champ \\emph{numéro} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Trophée}.\n    \\item Les champs \\emph{type} et \\emph{état} étaient déjà de simples attributs de l'entité \\emph{Trophée}.\n    \\item Le champ à saisie obligatoire \\emph{nom villageois} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Récolter} à partir de l'entité \\emph{Villageois} en perdant son caractère identifiant.\n    \\item Le champ à saisie obligatoire \\emph{nom bataille} est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle \\emph{Récolter} à partir de l'entité \\emph{Bataille} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{Villageois} (\\prim{nom villageois}, \\attr{adresse}, \\attr{fonction})\n  \\begin{itemize}\n    \\item Le champ \\emph{nom villageois} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Villageois}.\n    \\item Les champs \\emph{adresse} et \\emph{fonction} étaient déjà de simples attributs de l'entité \\emph{Villageois}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/split/mld/split_mld.txt",
    "content": "- Bataille (_nom bataille_, lieu, date)\n  - Le champ « nom bataille » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Bataille ».\n  - Les champs « lieu » et « date » étaient déjà de simples attributs de l'entité « Bataille ».\n\n- Trophée (_numéro_, type, état, #nom villageois!, #nom bataille!)\n  - Le champ « numéro » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Trophée ».\n  - Les champs « type » et « état » étaient déjà de simples attributs de l'entité « Trophée ».\n  - Le champ à saisie obligatoire « nom villageois » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Récolter » à partir de l'entité « Villageois » en perdant son caractère identifiant.\n  - Le champ à saisie obligatoire « nom bataille » est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle « Récolter » à partir de l'entité « Bataille » en perdant son caractère identifiant.\n\n- Villageois (_nom villageois_, adresse, fonction)\n  - Le champ « nom villageois » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Villageois ».\n  - Les champs « adresse » et « fonction » étaient déjà de simples attributs de l'entité « Villageois ».\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_create_df_arrows=across.mcd",
    "content": "Bataille: nom bataille, lieu, date\nRécolter, 0N> Villageois, 0N> Bataille, 11 Trophée\nVillageois: nom villageois, adresse, fonction\n\nTrophée: numéro, type, état\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2, at 1 3\nASSOC 4_, 0N ENTITÉ 2_, 0N ENTITÉ 1_, 11 ENTITÉ 3_\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\n\nENTITÉ 3_: at 3 1, at 3 2, at 3 3\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/split/rewritten/split_rw_split.mcd",
    "content": "Bataille: nom bataille, lieu, date\nRécolter1, 11 Trophée, 0N Bataille\n:\n\n:\nTrophée: numéro, type, état\nRécolter0, 11 Trophée, 0N Villageois\n\n:\n:\nVillageois: nom villageois, adresse, fonction\n"
  },
  {
    "path": "test/zoo/ternary_unicity/_ternary_unicity_0.mcd",
    "content": "Voilier: voilier\nDF, _11 Disponibilité, 1N Voilier\nDisponibilité:\nDF, _11 Disponibilité, 1N Semaine\nSemaine: semaine, 1_date début\n\nDF, 11 Réservation, 01 Disponibilité\n    \nRéservation: id résa, 1_num résa, arrhes, date réservation\n"
  },
  {
    "path": "test/zoo/ternary_unicity/ddl/ternary_unicity_0_ddl.d2",
    "content": "\"Disponibilité\": { shape: sql_table\n  \"semaine\": VARCHAR(42) {constraint: [PK; FK]}\n  \"voilier\": VARCHAR(42) {constraint: PK}\n}\n\n\"Réservation\": { shape: sql_table\n  \"id résa\":          VARCHAR(42) {constraint: PK}\n  \"num résa\":         VARCHAR(42) {constraint: UNQ1}\n  \"arrhes\":           VARCHAR(42) \n  \"date réservation\": VARCHAR(42) \n  \"semaine\":          VARCHAR(42) {constraint: [FK; NOT NULL]}\n  \"voilier\":          VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Semaine\": { shape: sql_table\n  \"semaine\":    VARCHAR(42) {constraint: PK}\n  \"date début\": VARCHAR(42) {constraint: UNQ1}\n}\n\n\"Disponibilité\".\"semaine\" -> \"Semaine\".\"semaine\"\n\"Réservation\".\"semaine\" -> \"Disponibilité\".\"semaine\"\n\"Réservation\".\"voilier\" -> \"Disponibilité\".\"voilier\"\n"
  },
  {
    "path": "test/zoo/ternary_unicity/ddl/ternary_unicity_0_ddl.dbml",
    "content": "Table \"Disponibilité\" {\n  \"semaine\" VARCHAR(42) [NOT NULL]\n  \"voilier\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"semaine\", \"voilier\") [pk]\n  }\n}\n\nTable \"Réservation\" {\n  \"id résa\"          VARCHAR(42) [pk, NOT NULL]\n  \"num résa\"         VARCHAR(42)\n  \"arrhes\"           VARCHAR(42)\n  \"date réservation\" VARCHAR(42)\n  \"semaine\"          VARCHAR(42) [NOT NULL]\n  \"voilier\"          VARCHAR(42) [NOT NULL]\n  Indexes {\n    \"num résa\" [unique]\n    (\"semaine\", \"voilier\") [unique]\n  }\n}\n\nTable \"Semaine\" {\n  \"semaine\"    VARCHAR(42) [pk, NOT NULL]\n  \"date début\" VARCHAR(42)\n  Indexes {\n    \"date début\" [unique]\n  }\n}\n\nRef:\"Disponibilité\".\"semaine\" > \"Semaine\".\"semaine\"\nRef:\"Réservation\".(\"semaine\", \"voilier\") > \"Disponibilité\".(\"semaine\", \"voilier\")\n"
  },
  {
    "path": "test/zoo/ternary_unicity/ddl/ternary_unicity_0_ddl.sql",
    "content": "CREATE TABLE DISPONIBILITE (\n  PRIMARY KEY (semaine, voilier),\n  semaine VARCHAR(42) NOT NULL,\n  voilier VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE RESERVATION (\n  PRIMARY KEY (id_resa),\n  id_resa          VARCHAR(8) NOT NULL,\n  num_resa         VARCHAR(8),\n  arrhes           VARCHAR(42),\n  date_reservation DATE,\n  semaine          VARCHAR(42) NOT NULL,\n  voilier          VARCHAR(42) NOT NULL,\n  UNIQUE (num_resa),\n  UNIQUE (semaine, voilier)\n);\n\nCREATE TABLE SEMAINE (\n  PRIMARY KEY (semaine),\n  semaine    VARCHAR(42) NOT NULL,\n  date_debut DATE,\n  UNIQUE (date_debut)\n);\n\nALTER TABLE DISPONIBILITE ADD FOREIGN KEY (semaine) REFERENCES SEMAINE (semaine);\n\nALTER TABLE RESERVATION ADD FOREIGN KEY (semaine, voilier) REFERENCES DISPONIBILITE (semaine, voilier);\n"
  },
  {
    "path": "test/zoo/ternary_unicity/exported/ternary_unicity_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Voilier\"]\n  4 [label=\"Disponibilité\",peripheries=2]\n  6 [label=\"Semaine\"]\n  10 [label=\"Réservation\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  8 [label=\"date\\ndébut\"]\n  12 [label=\"num résa\"]\n  13 [label=\"arrhes\"]\n  14 [label=\"date\\nréservation\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>voilier</u>>]\n  7 [label=<<u>semaine</u>>]\n  11 [label=<<u>id résa</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"DF\",peripheries=2]\n  5 [label=\"DF\",peripheries=2]\n  9 [label=\"DF\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  6 -- 7\n  6 -- 8\n  10 -- 11\n  10 -- 12\n  10 -- 13\n  10 -- 14\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 3\n  6 -- 5\n  10 -- 9\n  4 -- 9 [color=\"#000000\"]\n  edge [headlabel=N]\n  4 -- 3\n  4 -- 5\n}"
  },
  {
    "path": "test/zoo/ternary_unicity/exported/ternary_unicity_0_erd_chen.txt",
    "content": "[Réservation] ==1== <DF>\n[Semaine] ==1== <<DF>>\n[Voilier] ==1== <<DF>>\n[[Disponibilité]] --1-- <DF>\n[[Disponibilité]] ==N== <<DF>>\n[[Disponibilité]] ==N== <<DF>>\n"
  },
  {
    "path": "test/zoo/ternary_unicity/exported/ternary_unicity_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Disponibilité</font>\n            </td>\n        </tr>\n\n    </table>\n>]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Voilier</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">voilier</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Semaine</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">semaine</td></tr>\n        <tr><td> </td><td align=\"left\">date début</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Réservation</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">id résa</td></tr>\n        <tr><td> </td><td align=\"left\">num résa</td></tr>\n        <tr><td> </td><td align=\"left\">arrhes</td></tr>\n        <tr><td> </td><td align=\"left\">date réservation</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"teetee\" arrowtail=\"crowtee\" style=dotted]\n  2 -> 3 [arrowhead=\"teetee\" arrowtail=\"crowtee\" style=dotted]\n  4 -> 2 [arrowhead=\"teetee\" arrowtail=\"teeodot\"]\n}"
  },
  {
    "path": "test/zoo/ternary_unicity/exported/ternary_unicity_0_erd_crow.mmd",
    "content": "erDiagram\n  Voilier {\n    TYPE voilier PK\n  }\n  Disponibilite {\n  }\n  Semaine {\n    TYPE semaine PK\n    TYPE date_debut\n  }\n  Reservation {\n    TYPE id_resa PK\n    TYPE num_resa\n    TYPE arrhes\n    TYPE date_reservation\n  }\n  Disponibilite }|..|| Voilier: DF\n  Disponibilite }|..|| Semaine: DF\n  Reservation |o--|| Disponibilite: DF"
  },
  {
    "path": "test/zoo/ternary_unicity/exported/ternary_unicity_0_uml.puml",
    "content": "@startuml \"ternary_unicity\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Voilier\") {\n    {field} + pk(voilier)\n}\n\n\"Disponibilité\" \"1..*\" --* \"1\" \"Voilier\"\n\nTable(\"Disponibilité\") {\n}\n\n\"Disponibilité\" \"1..*\" --* \"1\" \"Semaine\"\n\nTable(\"Semaine\") {\n    {field} + pk(semaine)\n    {field} + date début\n}\n\n\"Réservation\" \"1..*\" --- \"1\" \"Disponibilité\"\n\nTable(\"Réservation\") {\n    {field} + pk(id résa)\n    {field} + num résa\n    {field} + arrhes\n    {field} + date réservation\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nDisponibilité\tsemaine\t!\t\tstrengthening_primary_foreign_key\tTrue\tSemaine\tSemaine\tDF\t\t\nDisponibilité\tvoilier\t!\t\tstrengthening_primary_ex_foreign_key\tTrue\tVoilier\tVoilier\tDF\t\t\nRéservation\tid résa\t!\t\tprimary_key\tTrue\t\t\t\t\t\nRéservation\tnum résa\t\t1\tnormal_attribute\tFalse\t\t\t\t\t\nRéservation\tarrhes\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nRéservation\tdate réservation\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nRéservation\tsemaine\t!\t2\tforeign_key\tFalse\tDisponibilité\tDisponibilité\tDF\t\t\nRéservation\tvoilier\t!\t2\tforeign_key\tFalse\tDisponibilité\tDisponibilité\tDF\t\t\nSemaine\tsemaine\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSemaine\tdate début\t\t1\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Semaine\" -> \"Disponibilité\"\n  \"Disponibilité\" -> \"Réservation\"\n}\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"ternary_unicity_0_mld.svg\"/></center><figcaption>MCD <i>ternary_unicity</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Disponibilité</span> (\n    <span class='foreign primary'>#semaine</span>,\n    <span class='primary'>voilier</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>semaine</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Semaine</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>voilier</i> fait partie de la clé primaire de la table. Il a migré à partir de l'entité <i>Voilier</i> pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Réservation</span> (\n    <span class='primary'>id résa</span>,\n    <span class='normal'>num résa</span> <sup>u1</sup>,\n    <span class='normal'>arrhes</span>,\n    <span class='normal'>date réservation</span>,\n    <span class='foreign'>#semaine</span> <sup>u2</sup>,\n    <span class='foreign'>#voilier</span> <sup>u2</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>id résa</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Réservation</i>.</li>\n    <li>Le champ <i>num résa</i> était déjà un simple attribut de l'entité <i>Réservation</i>. Il obéit à la contrainte d'unicité 1.</li>\n    <li>Les champs <i>arrhes</i> et <i>date réservation</i> étaient déjà de simples attributs de l'entité <i>Réservation</i>.</li>\n    <li>Les champs <i>semaine</i> et <i>voilier</i> sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle <i>DF</i> à partir de l'entité <i>Disponibilité</i> en perdant leur caractère identifiant. Ils obéissent en outre à la contrainte d'unicité 2.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Semaine</span> (\n    <span class='primary'>semaine</span>,\n    <span class='normal'>date début</span> <sup>u1</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>semaine</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Semaine</i>.</li>\n    <li>Le champ <i>date début</i> était déjà un simple attribut de l'entité <i>Semaine</i>. Il obéit à la contrainte d'unicité 1.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>Voilier</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_mld.mcd",
    "content": "%%mocodo\n:\nDisponibilité: #semaine > Semaine > semaine, _voilier\n:\nSemaine: semaine, date début\n:\n\n\n\n:\nRéservation: id résa, num résa, arrhes, date réservation, #semaine > Disponibilité > semaine, #voilier > Disponibilité > voilier\n:::\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_mld.md",
    "content": "- **Disponibilité** (<u>_#semaine_</u>, <u>voilier</u>)\n  - Le champ _semaine_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Semaine_ pour renforcer l'identifiant.\n  - Le champ _voilier_ fait partie de la clé primaire de la table. Il a migré à partir de l'entité _Voilier_ pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n\n- **Réservation** (<u>id résa</u>, num résa <sup>u1</sup>, arrhes, date réservation, _#semaine_ <sup>u2</sup>, _#voilier_ <sup>u2</sup>)\n  - Le champ _id résa_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Réservation_.\n  - Le champ _num résa_ était déjà un simple attribut de l'entité _Réservation_. Il obéit à la contrainte d'unicité 1.\n  - Les champs _arrhes_ et _date réservation_ étaient déjà de simples attributs de l'entité _Réservation_.\n  - Les champs _semaine_ et _voilier_ sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle _DF_ à partir de l'entité _Disponibilité_ en perdant leur caractère identifiant. Ils obéissent en outre à la contrainte d'unicité 2.\n\n- **Semaine** (<u>semaine</u>, date début <sup>u1</sup>)\n  - Le champ _semaine_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Semaine_.\n  - Le champ _date début_ était déjà un simple attribut de l'entité _Semaine_. Il obéit à la contrainte d'unicité 1.\n<br>\n----\n\n\n**NB.** La table _Voilier_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{ternary\\_unicity}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Disponibilité} (\\foreign{\\prim{semaine}}, \\prim{voilier})\n  \\begin{itemize}\n    \\item Le champ \\emph{semaine} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Semaine} pour renforcer l'identifiant.\n    \\item Le champ \\emph{voilier} fait partie de la clé primaire de la table. Il a migré à partir de l'entité \\emph{Voilier} pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  \\end{itemize}\n\n  \\item \\relat{Réservation} (\\prim{id résa}, \\attr{num résa}$^{u\\_1}$, \\attr{arrhes}, \\attr{date réservation}, \\foreign{semaine}$^{u\\_2}$, \\foreign{voilier}$^{u\\_2}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{id résa} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Réservation}.\n    \\item Le champ \\emph{num résa} était déjà un simple attribut de l'entité \\emph{Réservation}. Il obéit à la contrainte d'unicité 1.\n    \\item Les champs \\emph{arrhes} et \\emph{date réservation} étaient déjà de simples attributs de l'entité \\emph{Réservation}.\n    \\item Les champs \\emph{semaine} et \\emph{voilier} sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle \\emph{DF} à partir de l'entité \\emph{Disponibilité} en perdant leur caractère identifiant. Ils obéissent en outre à la contrainte d'unicité 2.\n  \\end{itemize}\n\n  \\item \\relat{Semaine} (\\prim{semaine}, \\attr{date début}$^{u\\_1}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{semaine} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Semaine}.\n    \\item Le champ \\emph{date début} était déjà un simple attribut de l'entité \\emph{Semaine}. Il obéit à la contrainte d'unicité 1.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/ternary_unicity/mld/ternary_unicity_0_mld.txt",
    "content": "- Disponibilité (_#semaine_, _voilier_)\n  - Le champ « semaine » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Semaine » pour renforcer l'identifiant.\n  - Le champ « voilier » fait partie de la clé primaire de la table. Il a migré à partir de l'entité « Voilier » pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n\n- Réservation (_id résa_, num résa¹, arrhes, date réservation, #semaine², #voilier²)\n  - Le champ « id résa » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Réservation ».\n  - Le champ « num résa » était déjà un simple attribut de l'entité « Réservation ». Il obéit à la contrainte d'unicité 1.\n  - Les champs « arrhes » et « date réservation » étaient déjà de simples attributs de l'entité « Réservation ».\n  - Les champs « semaine » et « voilier » sont des clés étrangères. Ils ont migré par l'association de dépendance fonctionnelle « DF » à partir de l'entité « Disponibilité » en perdant leur caractère identifiant. Ils obéissent en outre à la contrainte d'unicité 2.\n\n- Semaine (_semaine_, date début¹)\n  - Le champ « semaine » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Semaine ».\n  - Le champ « date début » était déjà un simple attribut de l'entité « Semaine ». Il obéit à la contrainte d'unicité 1.\n<br>\n--------------------------------------------------------------------------------\n\nNB. La table « Voilier » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_create_df_arrows=across.mcd",
    "content": "Voilier: voilier\nDF, _11 Disponibilité, 1N> Voilier\nDisponibilité:\nDF, _11 Disponibilité, 1N> Semaine\nSemaine: semaine, 1_date début\n\nDF, 11 Réservation, 01> Disponibilité\n    \nRéservation: id résa, 1_num résa, arrhes, date réservation\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 1_\nENTITÉ 2_:\nDF, _11 ENTITÉ 2_, 1N ENTITÉ 3_\nENTITÉ 3_: at 3 1, 1_at 3 2\n\nDF, 11 ENTITÉ 4_, 01 ENTITÉ 2_\n    \nENTITÉ 4_: at 4 1, 1_at 4 2, at 4 3, at 4 4\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/ternary_unicity/rewritten/ternary_unicity_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/_triple_111_0.mcd",
    "content": "% Non-orthogonal cluster: not implemented\nTechnicien: technicien\n::\n\n:\nUtiliser, /1N Technicien, /1N Carnet, /1N Projet\nProjet: projet\n\n:    \nCarnet: carnet\n"
  },
  {
    "path": "test/zoo/triple_111/_triple_111_1.mcd",
    "content": "Technicien: technicien, nom technicien\nUtiliser, /1N Technicien, /1N Carnet, /1N Projet\nProjet: projet, libellé\n    \nCarnet: carnet\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_0_ddl.d2",
    "content": "\"Utiliser\": { shape: sql_table\n  \"carnet\":     VARCHAR(42) {constraint: [PK; UNQ1]}\n  \"projet\":     VARCHAR(42) {constraint: [PK; UNQ2]}\n  \"technicien\": VARCHAR(42) {constraint: [NOT NULL; UNQ1; UNQ2]}\n}\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_0_ddl.dbml",
    "content": "Table \"Utiliser\" {\n  \"carnet\"     VARCHAR(42) [NOT NULL]\n  \"projet\"     VARCHAR(42) [NOT NULL]\n  \"technicien\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"carnet\", \"projet\") [pk]\n    (\"technicien\", \"projet\") [unique]\n    (\"carnet\", \"technicien\") [unique]\n  }\n}\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_0_ddl.sql",
    "content": "CREATE TABLE UTILISER (\n  PRIMARY KEY (carnet, projet),\n  carnet     VARCHAR(42) NOT NULL,\n  projet     VARCHAR(42) NOT NULL,\n  technicien VARCHAR(42) NOT NULL,\n  UNIQUE (carnet, technicien),\n  UNIQUE (projet, technicien)\n);\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_1_ddl.d2",
    "content": "\"Projet\": { shape: sql_table\n  \"projet\":  VARCHAR(42) {constraint: PK}\n  \"libellé\": VARCHAR(42) \n}\n\n\"Technicien\": { shape: sql_table\n  \"technicien\":     VARCHAR(42) {constraint: PK}\n  \"nom technicien\": VARCHAR(42) \n}\n\n\"Utiliser\": { shape: sql_table\n  \"carnet\":     VARCHAR(42) {constraint: [PK; UNQ1]}\n  \"projet\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"technicien\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Utiliser\".\"projet\" -> \"Projet\".\"projet\"\n\"Utiliser\".\"technicien\" -> \"Technicien\".\"technicien\"\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_1_ddl.dbml",
    "content": "Table \"Projet\" {\n  \"projet\"  VARCHAR(42) [pk, NOT NULL]\n  \"libellé\" VARCHAR(42)\n}\n\nTable \"Technicien\" {\n  \"technicien\"     VARCHAR(42) [pk, NOT NULL]\n  \"nom technicien\" VARCHAR(42)\n}\n\nTable \"Utiliser\" {\n  \"carnet\"     VARCHAR(42) [NOT NULL]\n  \"projet\"     VARCHAR(42) [NOT NULL]\n  \"technicien\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"carnet\", \"projet\") [pk]\n    (\"technicien\", \"projet\") [unique]\n    (\"carnet\", \"technicien\") [unique]\n  }\n}\n\nRef:\"Utiliser\".\"projet\" > \"Projet\".\"projet\"\nRef:\"Utiliser\".\"technicien\" > \"Technicien\".\"technicien\"\n"
  },
  {
    "path": "test/zoo/triple_111/ddl/triple_111_1_ddl.sql",
    "content": "CREATE TABLE PROJET (\n  PRIMARY KEY (projet),\n  projet  VARCHAR(42) NOT NULL,\n  libelle VARCHAR(50)\n);\n\nCREATE TABLE TECHNICIEN (\n  PRIMARY KEY (technicien),\n  technicien     VARCHAR(42) NOT NULL,\n  nom_technicien VARCHAR(255)\n);\n\nCREATE TABLE UTILISER (\n  PRIMARY KEY (carnet, projet),\n  carnet     VARCHAR(42) NOT NULL,\n  projet     VARCHAR(42) NOT NULL,\n  technicien VARCHAR(42) NOT NULL,\n  UNIQUE (carnet, technicien),\n  UNIQUE (projet, technicien)\n);\n\nALTER TABLE UTILISER ADD FOREIGN KEY (technicien) REFERENCES TECHNICIEN (technicien);\nALTER TABLE UTILISER ADD FOREIGN KEY (projet) REFERENCES PROJET (projet);\n"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Technicien\"]\n  5 [label=\"Projet\"]\n  4 [label=\"Carnet\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>technicien</u>>]\n  6 [label=<<u>projet</u>>]\n  7 [label=<<u>carnet</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Utiliser\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 7\n  5 -- 6\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 3\n  4 -- 3\n  5 -- 3\n}"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_0_erd_chen.txt",
    "content": "[Carnet] ==1== <Utiliser>\n[Projet] ==1== <Utiliser>\n[Technicien] ==1== <Utiliser>\n"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_0_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_0_uml.puml",
    "content": "@startuml \"triple_111\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Technicien\") {\n    {field} + pk(technicien)\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Technicien\"\nN_ARY_0 -- \"1\" \"Carnet\"\nN_ARY_0 -- \"1\" \"Projet\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n}\n\nTable(\"Carnet\") {\n    {field} + pk(carnet)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Technicien\"]\n  6 [label=\"Projet\"]\n  5 [label=\"Carnet\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"nom\\ntechnicien\"]\n  8 [label=\"libellé\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>technicien</u>>]\n  7 [label=<<u>projet</u>>]\n  9 [label=<<u>carnet</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Utiliser\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 9\n  6 -- 7\n  6 -- 8\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 4\n  5 -- 4\n  6 -- 4\n}"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_1_erd_chen.txt",
    "content": "[Carnet] ==1== <Utiliser>\n[Projet] ==1== <Utiliser>\n[Technicien] ==1== <Utiliser>\n"
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_1_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_111/exported/triple_111_1_uml.puml",
    "content": "@startuml \"triple_111\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Technicien\") {\n    {field} + pk(technicien)\n    {field} + nom technicien\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Technicien\"\nN_ARY_0 -- \"1\" \"Carnet\"\nN_ARY_0 -- \"1\" \"Projet\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n    {field} + libellé\n}\n\nTable(\"Carnet\") {\n    {field} + pk(carnet)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nUtiliser\tcarnet\t!\t1\tprimary_ex_foreign_key\tTrue\tCarnet\tCarnet\tUtiliser\t\t\nUtiliser\tprojet\t!\t2\tprimary_ex_foreign_key\tTrue\tProjet\tProjet\tUtiliser\t\t\nUtiliser\ttechnicien\t!\t12\tstopped_ex_foreign_key\tFalse\tTechnicien\tTechnicien\tUtiliser\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_111_0_mld.svg\"/></center><figcaption>MCD <i>triple_111</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Utiliser</span> (\n    <span class='primary'>carnet</span> <sup>u1</sup>,\n    <span class='primary'>projet</span> <sup>u2</sup>,\n    <span class='normal'>technicien</span> <sup>u1 u2</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>carnet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Carnet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Projet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 2.</li>\n    <li>Le champ <i>technicien</i> est un simple attribut. Il a migré directement à partir de l'entité <i>Technicien</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre aux contraintes d'unicité 1 et 2.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>Carnet</i>, <i>Projet</i> et <i>Technicien</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_mld.mcd",
    "content": ":\nUtiliser: carnet, _projet, technicien\n:\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_mld.md",
    "content": "- **Utiliser** (<u>carnet</u> <sup>u1</sup>, <u>projet</u> <sup>u2</sup>, technicien <sup>u1 u2</sup>)\n  - Le champ _carnet_ fait partie de la clé primaire de la table. Sa table d'origine (_Carnet_) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ _projet_ fait partie de la clé primaire de la table. Sa table d'origine (_Projet_) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 2.\n  - Le champ _technicien_ est un simple attribut. Il a migré directement à partir de l'entité _Technicien_ en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre aux contraintes d'unicité 1 et 2.\n<br>\n----\n\n\n**NB.** Les tables _Carnet_, _Projet_ et _Technicien_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_111}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Utiliser} (\\prim{carnet}$^{u\\_1}$, \\prim{projet}$^{u\\_2}$, \\attr{technicien}$^{u\\_1 u\\_2}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{carnet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Carnet}) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Projet}) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 2.\n    \\item Le champ \\emph{technicien} est un simple attribut. Il a migré directement à partir de l'entité \\emph{Technicien} en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre aux contraintes d'unicité 1 et 2.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_0_mld.txt",
    "content": "- Utiliser (_carnet_¹, _projet_², technicien¹²)\n  - Le champ « carnet » fait partie de la clé primaire de la table. Sa table d'origine (« Carnet ») ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ « projet » fait partie de la clé primaire de la table. Sa table d'origine (« Projet ») ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 2.\n  - Le champ « technicien » est un simple attribut. Il a migré directement à partir de l'entité « Technicien » en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre aux contraintes d'unicité 1 et 2.\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « Carnet », « Projet » et « Technicien » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nProjet\tprojet\t!\t\tprimary_key\tTrue\t\t\t\t\t\nProjet\tlibellé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nTechnicien\ttechnicien\t!\t\tprimary_key\tTrue\t\t\t\t\t\nTechnicien\tnom technicien\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nUtiliser\tcarnet\t!\t1\tprimary_ex_foreign_key\tTrue\tCarnet\tCarnet\tUtiliser\t\t\nUtiliser\tprojet\t!\t2\tprimary_foreign_key\tTrue\tProjet\tProjet\tUtiliser\t\t\nUtiliser\ttechnicien\t!\t12\tstopped_foreign_key\tFalse\tTechnicien\tTechnicien\tUtiliser\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Technicien\" -> \"Utiliser\"\n  \"Projet\" -> \"Utiliser\"\n}\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_111_1_mld.svg\"/></center><figcaption>MCD <i>triple_111</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Projet</span> (\n    <span class='primary'>projet</span>,\n    <span class='normal'>libellé</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Projet</i>.</li>\n    <li>Le champ <i>libellé</i> était déjà un simple attribut de l'entité <i>Projet</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Technicien</span> (\n    <span class='primary'>technicien</span>,\n    <span class='normal'>nom technicien</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>technicien</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Technicien</i>.</li>\n    <li>Le champ <i>nom technicien</i> était déjà un simple attribut de l'entité <i>Technicien</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Utiliser</span> (\n    <span class='primary'>carnet</span> <sup>u1</sup>,\n    <span class='foreign primary'>#projet</span> <sup>u2</sup>,\n    <span class='foreign'>#technicien</span> <sup>u1 u2</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>carnet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Carnet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Projet</i>. Il obéit en outre à la contrainte d'unicité 2.</li>\n    <li>Le champ <i>technicien</i> est une clé étrangère. Il a migré directement à partir de l'entité <i>Technicien</i> en perdant son caractère identifiant. Il obéit en outre aux contraintes d'unicité 1 et 2.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>Carnet</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_mld.mcd",
    "content": "%%mocodo\n:\nTechnicien: technicien, nom technicien\n:\nUtiliser: carnet, _#projet > Projet > projet, #technicien > Technicien > technicien\n:\nProjet: projet, libellé\n:\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_mld.md",
    "content": "- **Projet** (<u>projet</u>, libellé)\n  - Le champ _projet_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Projet_.\n  - Le champ _libellé_ était déjà un simple attribut de l'entité _Projet_.\n\n- **Technicien** (<u>technicien</u>, nom technicien)\n  - Le champ _technicien_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Technicien_.\n  - Le champ _nom technicien_ était déjà un simple attribut de l'entité _Technicien_.\n\n- **Utiliser** (<u>carnet</u> <sup>u1</sup>, <u>_#projet_</u> <sup>u2</sup>, _#technicien_ <sup>u1 u2</sup>)\n  - Le champ _carnet_ fait partie de la clé primaire de la table. Sa table d'origine (_Carnet_) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ _projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Projet_. Il obéit en outre à la contrainte d'unicité 2.\n  - Le champ _technicien_ est une clé étrangère. Il a migré directement à partir de l'entité _Technicien_ en perdant son caractère identifiant. Il obéit en outre aux contraintes d'unicité 1 et 2.\n<br>\n----\n\n\n**NB.** La table _Carnet_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_111}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Projet} (\\prim{projet}, \\attr{libellé})\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Projet}.\n    \\item Le champ \\emph{libellé} était déjà un simple attribut de l'entité \\emph{Projet}.\n  \\end{itemize}\n\n  \\item \\relat{Technicien} (\\prim{technicien}, \\attr{nom technicien})\n  \\begin{itemize}\n    \\item Le champ \\emph{technicien} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Technicien}.\n    \\item Le champ \\emph{nom technicien} était déjà un simple attribut de l'entité \\emph{Technicien}.\n  \\end{itemize}\n\n  \\item \\relat{Utiliser} (\\prim{carnet}$^{u\\_1}$, \\foreign{\\prim{projet}}$^{u\\_2}$, \\foreign{technicien}$^{u\\_1 u\\_2}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{carnet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Carnet}) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Projet}. Il obéit en outre à la contrainte d'unicité 2.\n    \\item Le champ \\emph{technicien} est une clé étrangère. Il a migré directement à partir de l'entité \\emph{Technicien} en perdant son caractère identifiant. Il obéit en outre aux contraintes d'unicité 1 et 2.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_111/mld/triple_111_1_mld.txt",
    "content": "- Projet (_projet_, libellé)\n  - Le champ « projet » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Projet ».\n  - Le champ « libellé » était déjà un simple attribut de l'entité « Projet ».\n\n- Technicien (_technicien_, nom technicien)\n  - Le champ « technicien » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Technicien ».\n  - Le champ « nom technicien » était déjà un simple attribut de l'entité « Technicien ».\n\n- Utiliser (_carnet_¹, _#projet_², #technicien¹²)\n  - Le champ « carnet » fait partie de la clé primaire de la table. Sa table d'origine (« Carnet ») ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ « projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Projet ». Il obéit en outre à la contrainte d'unicité 2.\n  - Le champ « technicien » est une clé étrangère. Il a migré directement à partir de l'entité « Technicien » en perdant son caractère identifiant. Il obéit en outre aux contraintes d'unicité 1 et 2.\n<br>\n--------------------------------------------------------------------------------\n\nNB. La table « Carnet » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_drown.mcd",
    "content": "% Non-orthogonal cluster: not implemented\nENTITÉ 1_: at 1 1\n::\n\n:\nASSOC 4_, /1N ENTITÉ 1_, /1N ENTITÉ 3_, /1N ENTITÉ 2_\nENTITÉ 2_: at 2 1\n\n:    \nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 4_, /1N ENTITÉ 1_, /1N ENTITÉ 3_, /1N ENTITÉ 2_\nENTITÉ 2_: at 2 1, at 2 2\n    \nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_111/rewritten/triple_111_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/_triple_N11_0.mcd",
    "content": "Projet: projet\nAffecter, /1N Site, /1N Projet, 0N Employé\nSite: site\n\nEmployé: employé\n"
  },
  {
    "path": "test/zoo/triple_N11/_triple_N11_1.mcd",
    "content": "Projet: projet, libellé\nAffecter, /1N Site, /1N Projet, 0N Employé\nSite: site, position\n\nEmployé: employé, nom employé\n\n(CIF) --Projet, --Employé, ..Affecter, ->Site: Projet, Employé\n(CIF) ..Affecter, ->Projet, Employé, Site: Site, Employé\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_0_ddl.d2",
    "content": "\"Affecter\": { shape: sql_table\n  \"projet\":  VARCHAR(42) {constraint: PK}\n  \"employé\": VARCHAR(42) {constraint: [PK; UNQ1]}\n  \"site\":    VARCHAR(42) {constraint: [NOT NULL; UNQ1]}\n}\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_0_ddl.dbml",
    "content": "Table \"Affecter\" {\n  \"projet\"  VARCHAR(42) [NOT NULL]\n  \"employé\" VARCHAR(42) [NOT NULL]\n  \"site\"    VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"projet\", \"employé\") [pk]\n    (\"employé\", \"site\") [unique]\n  }\n}\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_0_ddl.sql",
    "content": "CREATE TABLE AFFECTER (\n  PRIMARY KEY (projet, employe),\n  projet  VARCHAR(42) NOT NULL,\n  employe VARCHAR(42) NOT NULL,\n  site    VARCHAR(42) NOT NULL,\n  UNIQUE (employe, site)\n);\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_1_ddl.d2",
    "content": "\"Affecter\": { shape: sql_table\n  \"projet\":  VARCHAR(42) {constraint: [PK; FK]}\n  \"employé\": VARCHAR(42) {constraint: [PK; FK]}\n  \"site\":    VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Employé\": { shape: sql_table\n  \"employé\":     VARCHAR(42) {constraint: PK}\n  \"nom employé\": VARCHAR(42) \n}\n\n\"Projet\": { shape: sql_table\n  \"projet\":  VARCHAR(42) {constraint: PK}\n  \"libellé\": VARCHAR(42) \n}\n\n\"Site\": { shape: sql_table\n  \"site\":     VARCHAR(42) {constraint: PK}\n  \"position\": VARCHAR(42) \n}\n\n\"Affecter\".\"projet\" -> \"Projet\".\"projet\"\n\"Affecter\".\"employé\" -> \"Employé\".\"employé\"\n\"Affecter\".\"site\" -> \"Site\".\"site\"\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_1_ddl.dbml",
    "content": "Table \"Affecter\" {\n  \"projet\"  VARCHAR(42) [NOT NULL]\n  \"employé\" VARCHAR(42) [NOT NULL]\n  \"site\"    VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"projet\", \"employé\") [pk]\n    (\"employé\", \"site\") [unique]\n  }\n}\n\nTable \"Employé\" {\n  \"employé\"     VARCHAR(42) [pk, NOT NULL]\n  \"nom employé\" VARCHAR(42)\n}\n\nTable \"Projet\" {\n  \"projet\"  VARCHAR(42) [pk, NOT NULL]\n  \"libellé\" VARCHAR(42)\n}\n\nTable \"Site\" {\n  \"site\"     VARCHAR(42) [pk, NOT NULL]\n  \"position\" VARCHAR(42)\n}\n\nRef:\"Affecter\".\"projet\" > \"Projet\".\"projet\"\nRef:\"Affecter\".\"employé\" > \"Employé\".\"employé\"\nRef:\"Affecter\".\"site\" > \"Site\".\"site\"\n"
  },
  {
    "path": "test/zoo/triple_N11/ddl/triple_N11_1_ddl.sql",
    "content": "CREATE TABLE AFFECTER (\n  PRIMARY KEY (projet, employe),\n  projet  VARCHAR(42) NOT NULL,\n  employe VARCHAR(42) NOT NULL,\n  site    VARCHAR(42) NOT NULL,\n  UNIQUE (employe, site)\n);\n\nCREATE TABLE EMPLOYE (\n  PRIMARY KEY (employe),\n  employe     VARCHAR(42) NOT NULL,\n  nom_employe VARCHAR(255)\n);\n\nCREATE TABLE PROJET (\n  PRIMARY KEY (projet),\n  projet  VARCHAR(42) NOT NULL,\n  libelle VARCHAR(50)\n);\n\nCREATE TABLE SITE (\n  PRIMARY KEY (site),\n  site     VARCHAR(42) NOT NULL,\n  position POINT\n);\n\nALTER TABLE AFFECTER ADD FOREIGN KEY (site) REFERENCES SITE (site);\nALTER TABLE AFFECTER ADD FOREIGN KEY (employe) REFERENCES EMPLOYE (employe);\nALTER TABLE AFFECTER ADD FOREIGN KEY (projet) REFERENCES PROJET (projet);\n"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Projet\"]\n  4 [label=\"Site\"]\n  5 [label=\"Employé\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>projet</u>>]\n  6 [label=<<u>site</u>>]\n  7 [label=<<u>employé</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Affecter\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 6\n  5 -- 7\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 3\n  4 -- 3\n  edge [headlabel=N]\n  5 -- 3 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_0_erd_chen.txt",
    "content": "[Employé] --N-- <Affecter>\n[Projet] ==1== <Affecter>\n[Site] ==1== <Affecter>\n"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_0_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_0_uml.puml",
    "content": "@startuml \"triple_N11\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Site\"\nN_ARY_0 -- \"1\" \"Projet\"\nN_ARY_0 -- \"*\" \"Employé\"\n\nTable(\"Site\") {\n    {field} + pk(site)\n}\n\nTable(\"Employé\") {\n    {field} + pk(employé)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Projet\"]\n  5 [label=\"Site\"]\n  6 [label=\"Employé\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"libellé\"]\n  8 [label=\"position\"]\n  10 [label=\"nom\\nemployé\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>projet</u>>]\n  7 [label=<<u>site</u>>]\n  9 [label=<<u>employé</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Affecter\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 7\n  5 -- 8\n  6 -- 9\n  6 -- 10\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 4\n  5 -- 4\n  edge [headlabel=N]\n  6 -- 4 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_1_erd_chen.txt",
    "content": "[Employé] --N-- <Affecter>\n[Projet] ==1== <Affecter>\n[Site] ==1== <Affecter>\n"
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_1_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_N11/exported/triple_N11_1_uml.puml",
    "content": "@startuml \"triple_N11\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n    {field} + libellé\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Site\"\nN_ARY_0 -- \"1\" \"Projet\"\nN_ARY_0 -- \"*\" \"Employé\"\n\nTable(\"Site\") {\n    {field} + pk(site)\n    {field} + position\n}\n\nTable(\"Employé\") {\n    {field} + pk(employé)\n    {field} + nom employé\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAffecter\tprojet\t!\t\tprimary_ex_foreign_key\tTrue\tProjet\tProjet\tAffecter\t\t\nAffecter\temployé\t!\t1\tprimary_ex_foreign_key\tTrue\tEmployé\tEmployé\tAffecter\t\t\nAffecter\tsite\t!\t1\tstopped_ex_foreign_key\tFalse\tSite\tSite\tAffecter\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_N11_0_mld.svg\"/></center><figcaption>MCD <i>triple_N11</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Affecter</span> (\n    <span class='primary'>projet</span>,\n    <span class='primary'>employé</span> <sup>u1</sup>,\n    <span class='normal'>site</span> <sup>u1</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Projet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>employé</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Employé</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>site</i> est un simple attribut. Il a migré directement à partir de l'entité <i>Site</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>Employé</i>, <i>Projet</i> et <i>Site</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_mld.mcd",
    "content": "%%mocodo\n:\nAffecter: projet, _employé, site\n:\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_mld.md",
    "content": "- **Affecter** (<u>projet</u>, <u>employé</u> <sup>u1</sup>, site <sup>u1</sup>)\n  - Le champ _projet_ fait partie de la clé primaire de la table. Sa table d'origine (_Projet_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _employé_ fait partie de la clé primaire de la table. Sa table d'origine (_Employé_) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ _site_ est un simple attribut. Il a migré directement à partir de l'entité _Site_ en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n<br>\n----\n\n\n**NB.** Les tables _Employé_, _Projet_ et _Site_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_N11}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Affecter} (\\prim{projet}, \\prim{employé}$^{u\\_1}$, \\attr{site}$^{u\\_1}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Projet}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{employé} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Employé}) ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{site} est un simple attribut. Il a migré directement à partir de l'entité \\emph{Site} en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_0_mld.txt",
    "content": "- Affecter (_projet_, _employé_¹, site¹)\n  - Le champ « projet » fait partie de la clé primaire de la table. Sa table d'origine (« Projet ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « employé » fait partie de la clé primaire de la table. Sa table d'origine (« Employé ») ayant été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n  - Le champ « site » est un simple attribut. Il a migré directement à partir de l'entité « Site » en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère. Il obéit par contre à la contrainte d'unicité 1.\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « Employé », « Projet » et « Site » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAffecter\tprojet\t!\t\tprimary_foreign_key\tTrue\tProjet\tProjet\tAffecter\t\t\nAffecter\temployé\t!\t1\tprimary_foreign_key\tTrue\tEmployé\tEmployé\tAffecter\t\t\nAffecter\tsite\t!\t1\tstopped_foreign_key\tFalse\tSite\tSite\tAffecter\t\t\nEmployé\temployé\t!\t\tprimary_key\tTrue\t\t\t\t\t\nEmployé\tnom employé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nProjet\tprojet\t!\t\tprimary_key\tTrue\t\t\t\t\t\nProjet\tlibellé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nSite\tsite\t!\t\tprimary_key\tTrue\t\t\t\t\t\nSite\tposition\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Site\" -> \"Affecter\"\n  \"Employé\" -> \"Affecter\"\n  \"Projet\" -> \"Affecter\"\n}\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_N11_1_mld.svg\"/></center><figcaption>MCD <i>triple_N11</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Affecter</span> (\n    <span class='foreign primary'>#projet</span>,\n    <span class='foreign primary'>#employé</span> <sup>u1</sup>,\n    <span class='foreign'>#site</span> <sup>u1</sup>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Projet</i>.</li>\n    <li>Le champ <i>employé</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Employé</i>. Il obéit en outre à la contrainte d'unicité 1.</li>\n    <li>Le champ <i>site</i> est une clé étrangère. Il a migré directement à partir de l'entité <i>Site</i> en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Employé</span> (\n    <span class='primary'>employé</span>,\n    <span class='normal'>nom employé</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>employé</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Employé</i>.</li>\n    <li>Le champ <i>nom employé</i> était déjà un simple attribut de l'entité <i>Employé</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Projet</span> (\n    <span class='primary'>projet</span>,\n    <span class='normal'>libellé</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Projet</i>.</li>\n    <li>Le champ <i>libellé</i> était déjà un simple attribut de l'entité <i>Projet</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Site</span> (\n    <span class='primary'>site</span>,\n    <span class='normal'>position</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>site</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Site</i>.</li>\n    <li>Le champ <i>position</i> était déjà un simple attribut de l'entité <i>Site</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_mld.mcd",
    "content": "%%mocodo\n:\nProjet: projet, libellé\n:\nAffecter: #projet > Projet > projet, _#employé > Employé > employé, #site > Site > site\n:\nSite: site, position\n:\n\n\n:::\nEmployé: employé, nom employé\n:::\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_mld.md",
    "content": "- **Affecter** (<u>_#projet_</u>, <u>_#employé_</u> <sup>u1</sup>, _#site_ <sup>u1</sup>)\n  - Le champ _projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Projet_.\n  - Le champ _employé_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Employé_. Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ _site_ est une clé étrangère. Il a migré directement à partir de l'entité _Site_ en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n\n- **Employé** (<u>employé</u>, nom employé)\n  - Le champ _employé_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Employé_.\n  - Le champ _nom employé_ était déjà un simple attribut de l'entité _Employé_.\n\n- **Projet** (<u>projet</u>, libellé)\n  - Le champ _projet_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Projet_.\n  - Le champ _libellé_ était déjà un simple attribut de l'entité _Projet_.\n\n- **Site** (<u>site</u>, position)\n  - Le champ _site_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Site_.\n  - Le champ _position_ était déjà un simple attribut de l'entité _Site_.\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_N11}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Affecter} (\\foreign{\\prim{projet}}, \\foreign{\\prim{employé}}$^{u\\_1}$, \\foreign{site}$^{u\\_1}$)\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Projet}.\n    \\item Le champ \\emph{employé} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Employé}. Il obéit en outre à la contrainte d'unicité 1.\n    \\item Le champ \\emph{site} est une clé étrangère. Il a migré directement à partir de l'entité \\emph{Site} en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n  \\end{itemize}\n\n  \\item \\relat{Employé} (\\prim{employé}, \\attr{nom employé})\n  \\begin{itemize}\n    \\item Le champ \\emph{employé} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Employé}.\n    \\item Le champ \\emph{nom employé} était déjà un simple attribut de l'entité \\emph{Employé}.\n  \\end{itemize}\n\n  \\item \\relat{Projet} (\\prim{projet}, \\attr{libellé})\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Projet}.\n    \\item Le champ \\emph{libellé} était déjà un simple attribut de l'entité \\emph{Projet}.\n  \\end{itemize}\n\n  \\item \\relat{Site} (\\prim{site}, \\attr{position})\n  \\begin{itemize}\n    \\item Le champ \\emph{site} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Site}.\n    \\item Le champ \\emph{position} était déjà un simple attribut de l'entité \\emph{Site}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_N11/mld/triple_N11_1_mld.txt",
    "content": "- Affecter (_#projet_, _#employé_¹, #site¹)\n  - Le champ « projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Projet ».\n  - Le champ « employé » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Employé ». Il obéit en outre à la contrainte d'unicité 1.\n  - Le champ « site » est une clé étrangère. Il a migré directement à partir de l'entité « Site » en perdant son caractère identifiant. Il obéit en outre à la contrainte d'unicité 1.\n\n- Employé (_employé_, nom employé)\n  - Le champ « employé » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Employé ».\n  - Le champ « nom employé » était déjà un simple attribut de l'entité « Employé ».\n\n- Projet (_projet_, libellé)\n  - Le champ « projet » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Projet ».\n  - Le champ « libellé » était déjà un simple attribut de l'entité « Projet ».\n\n- Site (_site_, position)\n  - Le champ « site » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Site ».\n  - Le champ « position » était déjà un simple attribut de l'entité « Site ».\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_create_cifs.mcd",
    "content": "Projet: projet\nAffecter, /1N Site, /1N Projet, 0N Employé\nSite: site\n\nEmployé: employé\n\n-INVISIBLE_1, XX Projet, XX Projet\n-INVISIBLE_2, XX Site, XX Site\n\n(CIF) ..Affecter, ->Projet, --Employé, --Site: INVISIBLE_1, INVISIBLE_1\n(CIF) ..Affecter, ->Site, --Employé, --Projet: INVISIBLE_2, INVISIBLE_2\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nASSOC 4_, /1N ENTITÉ 2_, /1N ENTITÉ 1_, 0N ENTITÉ 3_\nENTITÉ 2_: at 2 1\n\nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_create_cifs.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 4_, /1N ENTITÉ 2_, /1N ENTITÉ 1_, 0N ENTITÉ 3_\nENTITÉ 2_: at 2 1, at 2 2\n\nENTITÉ 3_: at 3 1, at 3 2\n\n(CIF) --ENTITÉ 1_, --ENTITÉ 3_, ..ASSOC 4_, ->ENTITÉ 2_: ENTITÉ 1_, ENTITÉ 3_\n(CIF) ..ASSOC 4_, ->ENTITÉ 1_, ENTITÉ 3_, ENTITÉ 2_: ENTITÉ 2_, ENTITÉ 3_\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_N11/rewritten/triple_N11_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/_triple_NN1_0.mcd",
    "content": "Ingénieur: ingénieur\nGérer, /1N Responsable, 1N Ingénieur, 1N Projet\nProjet: projet\n\nResponsable: responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/_triple_NN1_1.mcd",
    "content": "Ingénieur: ingénieur, nom ingénieur\nGérer, /1N Responsable, 1N Ingénieur, 1N Projet\nProjet: projet, libellé projet\n\nResponsable: responsable, nom responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_0_ddl.d2",
    "content": "\"Gérer\": { shape: sql_table\n  \"ingénieur\":   VARCHAR(42) {constraint: PK}\n  \"projet\":      VARCHAR(42) {constraint: PK}\n  \"responsable\": VARCHAR(42) {constraint: NOT NULL}\n}\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_0_ddl.dbml",
    "content": "Table \"Gérer\" {\n  \"ingénieur\"   VARCHAR(42) [NOT NULL]\n  \"projet\"      VARCHAR(42) [NOT NULL]\n  \"responsable\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"ingénieur\", \"projet\") [pk]\n  }\n}\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_0_ddl.sql",
    "content": "CREATE TABLE GERER (\n  PRIMARY KEY (ingenieur, projet),\n  ingenieur   VARCHAR(42) NOT NULL,\n  projet      VARCHAR(42) NOT NULL,\n  responsable VARCHAR(42) NOT NULL\n);\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_1_ddl.d2",
    "content": "\"Gérer\": { shape: sql_table\n  \"ingénieur\":   VARCHAR(42) {constraint: [PK; FK]}\n  \"projet\":      VARCHAR(42) {constraint: [PK; FK]}\n  \"responsable\": VARCHAR(42) {constraint: [FK; NOT NULL]}\n}\n\n\"Ingénieur\": { shape: sql_table\n  \"ingénieur\":     VARCHAR(42) {constraint: PK}\n  \"nom ingénieur\": VARCHAR(42) \n}\n\n\"Projet\": { shape: sql_table\n  \"projet\":         VARCHAR(42) {constraint: PK}\n  \"libellé projet\": VARCHAR(42) \n}\n\n\"Responsable\": { shape: sql_table\n  \"responsable\":     VARCHAR(42) {constraint: PK}\n  \"nom responsable\": VARCHAR(42) \n}\n\n\"Gérer\".\"ingénieur\" -> \"Ingénieur\".\"ingénieur\"\n\"Gérer\".\"projet\" -> \"Projet\".\"projet\"\n\"Gérer\".\"responsable\" -> \"Responsable\".\"responsable\"\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_1_ddl.dbml",
    "content": "Table \"Gérer\" {\n  \"ingénieur\"   VARCHAR(42) [NOT NULL]\n  \"projet\"      VARCHAR(42) [NOT NULL]\n  \"responsable\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"ingénieur\", \"projet\") [pk]\n  }\n}\n\nTable \"Ingénieur\" {\n  \"ingénieur\"     VARCHAR(42) [pk, NOT NULL]\n  \"nom ingénieur\" VARCHAR(42)\n}\n\nTable \"Projet\" {\n  \"projet\"         VARCHAR(42) [pk, NOT NULL]\n  \"libellé projet\" VARCHAR(42)\n}\n\nTable \"Responsable\" {\n  \"responsable\"     VARCHAR(42) [pk, NOT NULL]\n  \"nom responsable\" VARCHAR(42)\n}\n\nRef:\"Gérer\".\"ingénieur\" > \"Ingénieur\".\"ingénieur\"\nRef:\"Gérer\".\"projet\" > \"Projet\".\"projet\"\nRef:\"Gérer\".\"responsable\" > \"Responsable\".\"responsable\"\n"
  },
  {
    "path": "test/zoo/triple_NN1/ddl/triple_NN1_1_ddl.sql",
    "content": "CREATE TABLE GERER (\n  PRIMARY KEY (ingenieur, projet),\n  ingenieur   VARCHAR(42) NOT NULL,\n  projet      VARCHAR(42) NOT NULL,\n  responsable VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE INGENIEUR (\n  PRIMARY KEY (ingenieur),\n  ingenieur     VARCHAR(42) NOT NULL,\n  nom_ingenieur VARCHAR(255)\n);\n\nCREATE TABLE PROJET (\n  PRIMARY KEY (projet),\n  projet         VARCHAR(42) NOT NULL,\n  libelle_projet VARCHAR(42)\n);\n\nCREATE TABLE RESPONSABLE (\n  PRIMARY KEY (responsable),\n  responsable     VARCHAR(42) NOT NULL,\n  nom_responsable VARCHAR(255)\n);\n\nALTER TABLE GERER ADD FOREIGN KEY (responsable) REFERENCES RESPONSABLE (responsable);\nALTER TABLE GERER ADD FOREIGN KEY (projet) REFERENCES PROJET (projet);\nALTER TABLE GERER ADD FOREIGN KEY (ingenieur) REFERENCES INGENIEUR (ingenieur);\n"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Ingénieur\"]\n  5 [label=\"Projet\"]\n  4 [label=\"Responsable\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>ingénieur</u>>]\n  6 [label=<<u>projet</u>>]\n  7 [label=<<u>responsable</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Gérer\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 7\n  5 -- 6\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  4 -- 3\n  edge [headlabel=N]\n  1 -- 3\n  5 -- 3\n}"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_0_erd_chen.txt",
    "content": "[Ingénieur] ==N== <Gérer>\n[Projet] ==N== <Gérer>\n[Responsable] ==1== <Gérer>\n"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_0_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_0_uml.puml",
    "content": "@startuml \"triple_NN1\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Ingénieur\") {\n    {field} + pk(ingénieur)\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Responsable\"\nN_ARY_0 -- \"1..*\" \"Ingénieur\"\nN_ARY_0 -- \"1..*\" \"Projet\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n}\n\nTable(\"Responsable\") {\n    {field} + pk(responsable)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Ingénieur\"]\n  6 [label=\"Projet\"]\n  5 [label=\"Responsable\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"nom\\ningénieur\"]\n  8 [label=\"libellé\\nprojet\"]\n  10 [label=\"nom\\nresponsable\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>ingénieur</u>>]\n  7 [label=<<u>projet</u>>]\n  9 [label=<<u>responsable</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Gérer\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 9\n  5 -- 10\n  6 -- 7\n  6 -- 8\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  5 -- 4\n  edge [headlabel=N]\n  1 -- 4\n  6 -- 4\n}"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_1_erd_chen.txt",
    "content": "[Ingénieur] ==N== <Gérer>\n[Projet] ==N== <Gérer>\n[Responsable] ==1== <Gérer>\n"
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_1_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_NN1/exported/triple_NN1_1_uml.puml",
    "content": "@startuml \"triple_NN1\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Ingénieur\") {\n    {field} + pk(ingénieur)\n    {field} + nom ingénieur\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"1\" \"Responsable\"\nN_ARY_0 -- \"1..*\" \"Ingénieur\"\nN_ARY_0 -- \"1..*\" \"Projet\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n    {field} + libellé projet\n}\n\nTable(\"Responsable\") {\n    {field} + pk(responsable)\n    {field} + nom responsable\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nGérer\tingénieur\t!\t\tprimary_ex_foreign_key\tTrue\tIngénieur\tIngénieur\tGérer\t\t\nGérer\tprojet\t!\t\tprimary_ex_foreign_key\tTrue\tProjet\tProjet\tGérer\t\t\nGérer\tresponsable\t!\t\tstopped_ex_foreign_key\tFalse\tResponsable\tResponsable\tGérer\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_NN1_0_mld.svg\"/></center><figcaption>MCD <i>triple_NN1</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Gérer</span> (\n    <span class='primary'>ingénieur</span>,\n    <span class='primary'>projet</span>,\n    <span class='normal'>responsable!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>ingénieur</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Ingénieur</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Projet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ à saisie obligatoire <i>responsable</i> est un simple attribut. Il a migré directement à partir de l'entité <i>Responsable</i> en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>Ingénieur</i>, <i>Projet</i> et <i>Responsable</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_mld.mcd",
    "content": "%%mocodo\n:\nGérer: ingénieur, _projet, responsable\n:\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_mld.md",
    "content": "- **Gérer** (<u>ingénieur</u>, <u>projet</u>, responsable!)\n  - Le champ _ingénieur_ fait partie de la clé primaire de la table. Sa table d'origine (_Ingénieur_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _projet_ fait partie de la clé primaire de la table. Sa table d'origine (_Projet_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ à saisie obligatoire _responsable_ est un simple attribut. Il a migré directement à partir de l'entité _Responsable_ en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n<br>\n----\n\n\n**NB.** Les tables _Ingénieur_, _Projet_ et _Responsable_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_NN1}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Gérer} (\\prim{ingénieur}, \\prim{projet}, \\attr{responsable!})\n  \\begin{itemize}\n    \\item Le champ \\emph{ingénieur} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Ingénieur}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Projet}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ à saisie obligatoire \\emph{responsable} est un simple attribut. Il a migré directement à partir de l'entité \\emph{Responsable} en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_0_mld.txt",
    "content": "- Gérer (_ingénieur_, _projet_, responsable!)\n  - Le champ « ingénieur » fait partie de la clé primaire de la table. Sa table d'origine (« Ingénieur ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « projet » fait partie de la clé primaire de la table. Sa table d'origine (« Projet ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ à saisie obligatoire « responsable » est un simple attribut. Il a migré directement à partir de l'entité « Responsable » en perdant son caractère identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « Ingénieur », « Projet » et « Responsable » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nGérer\tingénieur\t!\t\tprimary_foreign_key\tTrue\tIngénieur\tIngénieur\tGérer\t\t\nGérer\tprojet\t!\t\tprimary_foreign_key\tTrue\tProjet\tProjet\tGérer\t\t\nGérer\tresponsable\t!\t\tstopped_foreign_key\tFalse\tResponsable\tResponsable\tGérer\t\t\nIngénieur\tingénieur\t!\t\tprimary_key\tTrue\t\t\t\t\t\nIngénieur\tnom ingénieur\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nProjet\tprojet\t!\t\tprimary_key\tTrue\t\t\t\t\t\nProjet\tlibellé projet\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nResponsable\tresponsable\t!\t\tprimary_key\tTrue\t\t\t\t\t\nResponsable\tnom responsable\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Responsable\" -> \"Gérer\"\n  \"Projet\" -> \"Gérer\"\n  \"Ingénieur\" -> \"Gérer\"\n}\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_NN1_1_mld.svg\"/></center><figcaption>MCD <i>triple_NN1</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Gérer</span> (\n    <span class='foreign primary'>#ingénieur</span>,\n    <span class='foreign primary'>#projet</span>,\n    <span class='foreign'>#responsable!</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>ingénieur</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Ingénieur</i>.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Projet</i>.</li>\n    <li>Le champ à saisie obligatoire <i>responsable</i> est une clé étrangère. Il a migré directement à partir de l'entité <i>Responsable</i> en perdant son caractère identifiant.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Ingénieur</span> (\n    <span class='primary'>ingénieur</span>,\n    <span class='normal'>nom ingénieur</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>ingénieur</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Ingénieur</i>.</li>\n    <li>Le champ <i>nom ingénieur</i> était déjà un simple attribut de l'entité <i>Ingénieur</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Projet</span> (\n    <span class='primary'>projet</span>,\n    <span class='normal'>libellé projet</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Projet</i>.</li>\n    <li>Le champ <i>libellé projet</i> était déjà un simple attribut de l'entité <i>Projet</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Responsable</span> (\n    <span class='primary'>responsable</span>,\n    <span class='normal'>nom responsable</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>responsable</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Responsable</i>.</li>\n    <li>Le champ <i>nom responsable</i> était déjà un simple attribut de l'entité <i>Responsable</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_mld.mcd",
    "content": "%%mocodo\n:\nIngénieur: ingénieur, nom ingénieur\n:\nGérer: #ingénieur > Ingénieur > ingénieur, _#projet > Projet > projet, #responsable > Responsable > responsable\n:\nProjet: projet, libellé projet\n:\n\n\n:::\nResponsable: responsable, nom responsable\n:::\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_mld.md",
    "content": "- **Gérer** (<u>_#ingénieur_</u>, <u>_#projet_</u>, _#responsable!_)\n  - Le champ _ingénieur_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Ingénieur_.\n  - Le champ _projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Projet_.\n  - Le champ à saisie obligatoire _responsable_ est une clé étrangère. Il a migré directement à partir de l'entité _Responsable_ en perdant son caractère identifiant.\n\n- **Ingénieur** (<u>ingénieur</u>, nom ingénieur)\n  - Le champ _ingénieur_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Ingénieur_.\n  - Le champ _nom ingénieur_ était déjà un simple attribut de l'entité _Ingénieur_.\n\n- **Projet** (<u>projet</u>, libellé projet)\n  - Le champ _projet_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Projet_.\n  - Le champ _libellé projet_ était déjà un simple attribut de l'entité _Projet_.\n\n- **Responsable** (<u>responsable</u>, nom responsable)\n  - Le champ _responsable_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Responsable_.\n  - Le champ _nom responsable_ était déjà un simple attribut de l'entité _Responsable_.\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_NN1}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Gérer} (\\foreign{\\prim{ingénieur}}, \\foreign{\\prim{projet}}, \\foreign{responsable!})\n  \\begin{itemize}\n    \\item Le champ \\emph{ingénieur} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Ingénieur}.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Projet}.\n    \\item Le champ à saisie obligatoire \\emph{responsable} est une clé étrangère. Il a migré directement à partir de l'entité \\emph{Responsable} en perdant son caractère identifiant.\n  \\end{itemize}\n\n  \\item \\relat{Ingénieur} (\\prim{ingénieur}, \\attr{nom ingénieur})\n  \\begin{itemize}\n    \\item Le champ \\emph{ingénieur} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Ingénieur}.\n    \\item Le champ \\emph{nom ingénieur} était déjà un simple attribut de l'entité \\emph{Ingénieur}.\n  \\end{itemize}\n\n  \\item \\relat{Projet} (\\prim{projet}, \\attr{libellé projet})\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Projet}.\n    \\item Le champ \\emph{libellé projet} était déjà un simple attribut de l'entité \\emph{Projet}.\n  \\end{itemize}\n\n  \\item \\relat{Responsable} (\\prim{responsable}, \\attr{nom responsable})\n  \\begin{itemize}\n    \\item Le champ \\emph{responsable} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Responsable}.\n    \\item Le champ \\emph{nom responsable} était déjà un simple attribut de l'entité \\emph{Responsable}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_NN1/mld/triple_NN1_1_mld.txt",
    "content": "- Gérer (_#ingénieur_, _#projet_, #responsable!)\n  - Le champ « ingénieur » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Ingénieur ».\n  - Le champ « projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Projet ».\n  - Le champ à saisie obligatoire « responsable » est une clé étrangère. Il a migré directement à partir de l'entité « Responsable » en perdant son caractère identifiant.\n\n- Ingénieur (_ingénieur_, nom ingénieur)\n  - Le champ « ingénieur » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Ingénieur ».\n  - Le champ « nom ingénieur » était déjà un simple attribut de l'entité « Ingénieur ».\n\n- Projet (_projet_, libellé projet)\n  - Le champ « projet » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Projet ».\n  - Le champ « libellé projet » était déjà un simple attribut de l'entité « Projet ».\n\n- Responsable (_responsable_, nom responsable)\n  - Le champ « responsable » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Responsable ».\n  - Le champ « nom responsable » était déjà un simple attribut de l'entité « Responsable ».\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nASSOC 4_, /1N ENTITÉ 3_, 1N ENTITÉ 1_, 1N ENTITÉ 2_\nENTITÉ 2_: at 2 1\n\nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=2,weak.mcd",
    "content": "Projet: projet\nDF, _11 Gérer, 1N Projet\nGérer:\nDF, 11 Gérer, 1N Responsable\n\n:\nIngénieur: ingénieur\nDF, _11 Gérer, 1N Ingénieur\nResponsable: responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=3,weak.mcd",
    "content": "Projet: projet\nDF, _11 Gérer, 1N Projet\nGérer:\nDF, 11 Gérer, 1N Responsable\n\n:\nIngénieur: ingénieur\nDF, _11 Gérer, 1N Ingénieur\nResponsable: responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 4_, /1N ENTITÉ 3_, 1N ENTITÉ 1_, 1N ENTITÉ 2_\nENTITÉ 2_: at 2 1, at 2 2\n\nENTITÉ 3_: at 3 1, at 3 2\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=2,weak.mcd",
    "content": "Projet: projet, libellé projet\nDF, _11 Gérer, 1N Projet\nGérer:\nDF, 11 Gérer, 1N Responsable\n\n:\nIngénieur: ingénieur, nom ingénieur\nDF, _11 Gérer, 1N Ingénieur\nResponsable: responsable, nom responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=3,weak.mcd",
    "content": "Projet: projet, libellé projet\nDF, _11 Gérer, 1N Projet\nGérer:\nDF, 11 Gérer, 1N Responsable\n\n:\nIngénieur: ingénieur, nom ingénieur\nDF, _11 Gérer, 1N Ingénieur\nResponsable: responsable, nom responsable\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NN1/rewritten/triple_NN1_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/_triple_NNN_0.mcd",
    "content": "Employé: employé\nAppliquer, 0N Employé, 1N Projet, 1N Compétence\nProjet: projet\n\nCompétence: compétence\n"
  },
  {
    "path": "test/zoo/triple_NNN/_triple_NNN_1.mcd",
    "content": "Employé: employé, nom\nAppliquer, 0N Employé, 1N Projet, 1N Compétence\nProjet: projet, date début, date fin\n\nCompétence: compétence, libellé\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_0_ddl.d2",
    "content": "\"Appliquer\": { shape: sql_table\n  \"employé\":    VARCHAR(42) {constraint: PK}\n  \"projet\":     VARCHAR(42) {constraint: PK}\n  \"compétence\": VARCHAR(42) {constraint: PK}\n}\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_0_ddl.dbml",
    "content": "Table \"Appliquer\" {\n  \"employé\"    VARCHAR(42) [NOT NULL]\n  \"projet\"     VARCHAR(42) [NOT NULL]\n  \"compétence\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"employé\", \"projet\", \"compétence\") [pk]\n  }\n}\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_0_ddl.sql",
    "content": "CREATE TABLE APPLIQUER (\n  PRIMARY KEY (employe, projet, competence),\n  employe    VARCHAR(42) NOT NULL,\n  projet     VARCHAR(42) NOT NULL,\n  competence VARCHAR(42) NOT NULL\n);\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_1_ddl.d2",
    "content": "\"Appliquer\": { shape: sql_table\n  \"employé\":    VARCHAR(42) {constraint: [PK; FK]}\n  \"projet\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"compétence\": VARCHAR(42) {constraint: [PK; FK]}\n}\n\n\"Compétence\": { shape: sql_table\n  \"compétence\": VARCHAR(42) {constraint: PK}\n  \"libellé\":    VARCHAR(42) \n}\n\n\"Employé\": { shape: sql_table\n  \"employé\": VARCHAR(42) {constraint: PK}\n  \"nom\":     VARCHAR(42) \n}\n\n\"Projet\": { shape: sql_table\n  \"projet\":     VARCHAR(42) {constraint: PK}\n  \"date début\": VARCHAR(42) \n  \"date fin\":   VARCHAR(42) \n}\n\n\"Appliquer\".\"employé\" -> \"Employé\".\"employé\"\n\"Appliquer\".\"projet\" -> \"Projet\".\"projet\"\n\"Appliquer\".\"compétence\" -> \"Compétence\".\"compétence\"\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_1_ddl.dbml",
    "content": "Table \"Appliquer\" {\n  \"employé\"    VARCHAR(42) [NOT NULL]\n  \"projet\"     VARCHAR(42) [NOT NULL]\n  \"compétence\" VARCHAR(42) [NOT NULL]\n  Indexes {\n    (\"employé\", \"projet\", \"compétence\") [pk]\n  }\n}\n\nTable \"Compétence\" {\n  \"compétence\" VARCHAR(42) [pk, NOT NULL]\n  \"libellé\"    VARCHAR(42)\n}\n\nTable \"Employé\" {\n  \"employé\" VARCHAR(42) [pk, NOT NULL]\n  \"nom\"     VARCHAR(42)\n}\n\nTable \"Projet\" {\n  \"projet\"     VARCHAR(42) [pk, NOT NULL]\n  \"date début\" VARCHAR(42)\n  \"date fin\"   VARCHAR(42)\n}\n\nRef:\"Appliquer\".\"employé\" > \"Employé\".\"employé\"\nRef:\"Appliquer\".\"projet\" > \"Projet\".\"projet\"\nRef:\"Appliquer\".\"compétence\" > \"Compétence\".\"compétence\"\n"
  },
  {
    "path": "test/zoo/triple_NNN/ddl/triple_NNN_1_ddl.sql",
    "content": "CREATE TABLE APPLIQUER (\n  PRIMARY KEY (employe, projet, competence),\n  employe    VARCHAR(42) NOT NULL,\n  projet     VARCHAR(42) NOT NULL,\n  competence VARCHAR(42) NOT NULL\n);\n\nCREATE TABLE COMPETENCE (\n  PRIMARY KEY (competence),\n  competence VARCHAR(42) NOT NULL,\n  libelle    VARCHAR(50)\n);\n\nCREATE TABLE EMPLOYE (\n  PRIMARY KEY (employe),\n  employe VARCHAR(42) NOT NULL,\n  nom     VARCHAR(255)\n);\n\nCREATE TABLE PROJET (\n  PRIMARY KEY (projet),\n  projet     VARCHAR(42) NOT NULL,\n  date_debut DATE,\n  date_fin   DATE\n);\n\nALTER TABLE APPLIQUER ADD FOREIGN KEY (competence) REFERENCES COMPETENCE (competence);\nALTER TABLE APPLIQUER ADD FOREIGN KEY (projet) REFERENCES PROJET (projet);\nALTER TABLE APPLIQUER ADD FOREIGN KEY (employe) REFERENCES EMPLOYE (employe);\n"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Employé\"]\n  4 [label=\"Projet\"]\n  5 [label=\"Compétence\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>employé</u>>]\n  6 [label=<<u>projet</u>>]\n  7 [label=<<u>compétence</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"Appliquer\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 6\n  5 -- 7\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  edge [headlabel=N]\n  4 -- 3\n  5 -- 3\n  1 -- 3 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_0_erd_chen.txt",
    "content": "[Compétence] ==N== <Appliquer>\n[Employé] --N-- <Appliquer>\n[Projet] ==N== <Appliquer>\n"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_0_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_0_uml.puml",
    "content": "@startuml \"triple_NNN\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Employé\") {\n    {field} + pk(employé)\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"*\" \"Employé\"\nN_ARY_0 -- \"1..*\" \"Projet\"\nN_ARY_0 -- \"1..*\" \"Compétence\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n}\n\nTable(\"Compétence\") {\n    {field} + pk(compétence)\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Employé\"]\n  5 [label=\"Projet\"]\n  6 [label=\"Compétence\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"nom\"]\n  8 [label=\"date\\ndébut\"]\n  9 [label=\"date fin\"]\n  11 [label=\"libellé\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>employé</u>>]\n  7 [label=<<u>projet</u>>]\n  10 [label=<<u>compétence</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Appliquer\"]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 7\n  5 -- 8\n  5 -- 9\n  6 -- 10\n  6 -- 11\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  edge [headlabel=N]\n  5 -- 4\n  6 -- 4\n  1 -- 4 [color=\"#000000\"]\n}"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_1_erd_chen.txt",
    "content": "[Compétence] ==N== <Appliquer>\n[Employé] --N-- <Appliquer>\n[Projet] ==N== <Appliquer>\n"
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_1_erd_crow.mmd",
    "content": "Not implemented for n-ary associations."
  },
  {
    "path": "test/zoo/triple_NNN/exported/triple_NNN_1_uml.puml",
    "content": "@startuml \"triple_NNN\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Employé\") {\n    {field} + pk(employé)\n    {field} + nom\n}\n\ndiamond N_ARY_0\nN_ARY_0 -- \"*\" \"Employé\"\nN_ARY_0 -- \"1..*\" \"Projet\"\nN_ARY_0 -- \"1..*\" \"Compétence\"\n\nTable(\"Projet\") {\n    {field} + pk(projet)\n    {field} + date début\n    {field} + date fin\n}\n\nTable(\"Compétence\") {\n    {field} + pk(compétence)\n    {field} + libellé\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAppliquer\temployé\t!\t\tprimary_ex_foreign_key\tTrue\tEmployé\tEmployé\tAppliquer\t\t\nAppliquer\tprojet\t!\t\tprimary_ex_foreign_key\tTrue\tProjet\tProjet\tAppliquer\t\t\nAppliquer\tcompétence\t!\t\tprimary_ex_foreign_key\tTrue\tCompétence\tCompétence\tAppliquer\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_NNN_0_mld.svg\"/></center><figcaption>MCD <i>triple_NNN</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Appliquer</span> (\n    <span class='primary'>employé</span>,\n    <span class='primary'>projet</span>,\n    <span class='primary'>compétence</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>employé</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Employé</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Projet</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>compétence</i> fait partie de la clé primaire de la table. Sa table d'origine (<i>Compétence</i>) ayant été supprimée, il n'est pas considéré comme clé étrangère.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> Les tables <i>Compétence</i>, <i>Employé</i> et <i>Projet</i> ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_mld.mcd",
    "content": "%%mocodo\n:\nAppliquer: employé, _projet, _compétence\n:\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_mld.md",
    "content": "- **Appliquer** (<u>employé</u>, <u>projet</u>, <u>compétence</u>)\n  - Le champ _employé_ fait partie de la clé primaire de la table. Sa table d'origine (_Employé_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _projet_ fait partie de la clé primaire de la table. Sa table d'origine (_Projet_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _compétence_ fait partie de la clé primaire de la table. Sa table d'origine (_Compétence_) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n<br>\n----\n\n\n**NB.** Les tables _Compétence_, _Employé_ et _Projet_ ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_NNN}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Appliquer} (\\prim{employé}, \\prim{projet}, \\prim{compétence})\n  \\begin{itemize}\n    \\item Le champ \\emph{employé} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Employé}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Projet}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{compétence} fait partie de la clé primaire de la table. Sa table d'origine (\\emph{Compétence}) ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_0_mld.txt",
    "content": "- Appliquer (_employé_, _projet_, _compétence_)\n  - Le champ « employé » fait partie de la clé primaire de la table. Sa table d'origine (« Employé ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « projet » fait partie de la clé primaire de la table. Sa table d'origine (« Projet ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « compétence » fait partie de la clé primaire de la table. Sa table d'origine (« Compétence ») ayant été supprimée, il n'est pas considéré comme clé étrangère.\n<br>\n--------------------------------------------------------------------------------\n\nNB. Les tables « Compétence », « Employé » et « Projet » ont été supprimées car elles étaient réduites à la clé primaire de leur entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAppliquer\temployé\t!\t\tprimary_foreign_key\tTrue\tEmployé\tEmployé\tAppliquer\t\t\nAppliquer\tprojet\t!\t\tprimary_foreign_key\tTrue\tProjet\tProjet\tAppliquer\t\t\nAppliquer\tcompétence\t!\t\tprimary_foreign_key\tTrue\tCompétence\tCompétence\tAppliquer\t\t\nCompétence\tcompétence\t!\t\tprimary_key\tTrue\t\t\t\t\t\nCompétence\tlibellé\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nEmployé\temployé\t!\t\tprimary_key\tTrue\t\t\t\t\t\nEmployé\tnom\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nProjet\tprojet\t!\t\tprimary_key\tTrue\t\t\t\t\t\nProjet\tdate début\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nProjet\tdate fin\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Compétence\" -> \"Appliquer\"\n  \"Projet\" -> \"Appliquer\"\n  \"Employé\" -> \"Appliquer\"\n}\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"triple_NNN_1_mld.svg\"/></center><figcaption>MCD <i>triple_NNN</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Appliquer</span> (\n    <span class='foreign primary'>#employé</span>,\n    <span class='foreign primary'>#projet</span>,\n    <span class='foreign primary'>#compétence</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>employé</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Employé</i>.</li>\n    <li>Le champ <i>projet</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Projet</i>.</li>\n    <li>Le champ <i>compétence</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité <i>Compétence</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Compétence</span> (\n    <span class='primary'>compétence</span>,\n    <span class='normal'>libellé</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>compétence</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Compétence</i>.</li>\n    <li>Le champ <i>libellé</i> était déjà un simple attribut de l'entité <i>Compétence</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Employé</span> (\n    <span class='primary'>employé</span>,\n    <span class='normal'>nom</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>employé</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Employé</i>.</li>\n    <li>Le champ <i>nom</i> était déjà un simple attribut de l'entité <i>Employé</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Projet</span> (\n    <span class='primary'>projet</span>,\n    <span class='normal'>date début</span>,\n    <span class='normal'>date fin</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>projet</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Projet</i>.</li>\n    <li>Les champs <i>date début</i> et <i>date fin</i> étaient déjà de simples attributs de l'entité <i>Projet</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_mld.mcd",
    "content": "%%mocodo\n:\nEmployé: employé, nom\n:\nAppliquer: #employé > Employé > employé, _#projet > Projet > projet, _#compétence > Compétence > compétence\n:\nProjet: projet, date début, date fin\n:\n\n\n:::\nCompétence: compétence, libellé\n:::\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_mld.md",
    "content": "- **Appliquer** (<u>_#employé_</u>, <u>_#projet_</u>, <u>_#compétence_</u>)\n  - Le champ _employé_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Employé_.\n  - Le champ _projet_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Projet_.\n  - Le champ _compétence_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité _Compétence_.\n\n- **Compétence** (<u>compétence</u>, libellé)\n  - Le champ _compétence_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Compétence_.\n  - Le champ _libellé_ était déjà un simple attribut de l'entité _Compétence_.\n\n- **Employé** (<u>employé</u>, nom)\n  - Le champ _employé_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Employé_.\n  - Le champ _nom_ était déjà un simple attribut de l'entité _Employé_.\n\n- **Projet** (<u>projet</u>, date début, date fin)\n  - Le champ _projet_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Projet_.\n  - Les champs _date début_ et _date fin_ étaient déjà de simples attributs de l'entité _Projet_.\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{triple\\_NNN}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Appliquer} (\\foreign{\\prim{employé}}, \\foreign{\\prim{projet}}, \\foreign{\\prim{compétence}})\n  \\begin{itemize}\n    \\item Le champ \\emph{employé} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Employé}.\n    \\item Le champ \\emph{projet} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Projet}.\n    \\item Le champ \\emph{compétence} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité \\emph{Compétence}.\n  \\end{itemize}\n\n  \\item \\relat{Compétence} (\\prim{compétence}, \\attr{libellé})\n  \\begin{itemize}\n    \\item Le champ \\emph{compétence} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Compétence}.\n    \\item Le champ \\emph{libellé} était déjà un simple attribut de l'entité \\emph{Compétence}.\n  \\end{itemize}\n\n  \\item \\relat{Employé} (\\prim{employé}, \\attr{nom})\n  \\begin{itemize}\n    \\item Le champ \\emph{employé} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Employé}.\n    \\item Le champ \\emph{nom} était déjà un simple attribut de l'entité \\emph{Employé}.\n  \\end{itemize}\n\n  \\item \\relat{Projet} (\\prim{projet}, \\attr{date début}, \\attr{date fin})\n  \\begin{itemize}\n    \\item Le champ \\emph{projet} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Projet}.\n    \\item Les champs \\emph{date début} et \\emph{date fin} étaient déjà de simples attributs de l'entité \\emph{Projet}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/triple_NNN/mld/triple_NNN_1_mld.txt",
    "content": "- Appliquer (_#employé_, _#projet_, _#compétence_)\n  - Le champ « employé » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Employé ».\n  - Le champ « projet » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Projet ».\n  - Le champ « compétence » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité « Compétence ».\n\n- Compétence (_compétence_, libellé)\n  - Le champ « compétence » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Compétence ».\n  - Le champ « libellé » était déjà un simple attribut de l'entité « Compétence ».\n\n- Employé (_employé_, nom)\n  - Le champ « employé » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Employé ».\n  - Le champ « nom » était déjà un simple attribut de l'entité « Employé ».\n\n- Projet (_projet_, date début, date fin)\n  - Le champ « projet » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Projet ».\n  - Les champs « date début » et « date fin » étaient déjà de simples attributs de l'entité « Projet ».\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nASSOC 4_, 0N ENTITÉ 1_, 1N ENTITÉ 2_, 1N ENTITÉ 3_\nENTITÉ 2_: at 2 1\n\nENTITÉ 3_: at 3 1\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=2,weak.mcd",
    "content": "Projet: projet\nDF, _11 Appliquer, 1N Projet\nAppliquer:\nDF, _11 Appliquer, 0N Employé\n\n:\nCompétence: compétence\nDF, _11 Appliquer, 1N Compétence\nEmployé: employé\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=2.mcd",
    "content": "Projet: projet\nDF, 11 Appliquer, 1N Projet\nAppliquer: id. appliquer\nDF, 11 Appliquer, 0N Employé\n\n:\nCompétence: compétence\nDF, 11 Appliquer, 1N Compétence\nEmployé: employé\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=3,weak.mcd",
    "content": "Projet: projet\nDF, _11 Appliquer, 1N Projet\nAppliquer:\nDF, _11 Appliquer, 0N Employé\n\n:\nCompétence: compétence\nDF, _11 Appliquer, 1N Compétence\nEmployé: employé\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_explode_arity=3.mcd",
    "content": "Projet: projet\nDF, 11 Appliquer, 1N Projet\nAppliquer: id. appliquer\nDF, 11 Appliquer, 0N Employé\n\n:\nCompétence: compétence\nDF, 11 Appliquer, 1N Compétence\nEmployé: employé\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_create_df_arrows=across.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 4_, 0N ENTITÉ 1_, 1N ENTITÉ 2_, 1N ENTITÉ 3_\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\n\nENTITÉ 3_: at 3 1, at 3 2\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=2,weak.mcd",
    "content": "Projet: projet, date début, date fin\nDF, _11 Appliquer, 1N Projet\nAppliquer:\nDF, _11 Appliquer, 0N Employé\n\n:\nCompétence: compétence, libellé\nDF, _11 Appliquer, 1N Compétence\nEmployé: employé, nom\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=2.mcd",
    "content": "Projet: projet, date début, date fin\nDF, 11 Appliquer, 1N Projet\nAppliquer: id. appliquer\nDF, 11 Appliquer, 0N Employé\n\n:\nCompétence: compétence, libellé\nDF, 11 Appliquer, 1N Compétence\nEmployé: employé, nom\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=3,weak.mcd",
    "content": "Projet: projet, date début, date fin\nDF, _11 Appliquer, 1N Projet\nAppliquer:\nDF, _11 Appliquer, 0N Employé\n\n:\nCompétence: compétence, libellé\nDF, _11 Appliquer, 1N Compétence\nEmployé: employé, nom\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_explode_arity=3.mcd",
    "content": "Projet: projet, date début, date fin\nDF, 11 Appliquer, 1N Projet\nAppliquer: id. appliquer\nDF, 11 Appliquer, 0N Employé\n\n:\nCompétence: compétence, libellé\nDF, 11 Appliquer, 1N Compétence\nEmployé: employé, nom\n"
  },
  {
    "path": "test/zoo/triple_NNN/rewritten/triple_NNN_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/_weak_0.mcd",
    "content": "Œuvre: œuvre\nDF, 0N Œuvre, _11 Exemplaire: foobar\nExemplaire: exemplaire\n"
  },
  {
    "path": "test/zoo/weak/_weak_1.mcd",
    "content": "Œuvre: œuvre, auteur\nDF, 0N Œuvre, _11 Exemplaire: foobar\nExemplaire: exemplaire, nb pages, date achat\n"
  },
  {
    "path": "test/zoo/weak/_weak_2.mcd",
    "content": "Appartement: num appart., nb pièces\nComposer, 0N Étage, _11 Appartement\nÉtage: num étage, nb appartements\nAppartenir, 1N Immeuble, _11 Étage\nImmeuble: num immeuble, nb étages\nSe situer, 0N Rue, _11 Immeuble\nRue: code rue, nom rue\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_0_ddl.d2",
    "content": "\"Exemplaire\": { shape: sql_table\n  \"œuvre\":      VARCHAR(42) {constraint: PK}\n  \"exemplaire\": VARCHAR(42) {constraint: PK}\n  \"foobar\":     VARCHAR(42) \n}\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_0_ddl.dbml",
    "content": "Table \"Exemplaire\" {\n  \"œuvre\"      VARCHAR(42) [NOT NULL]\n  \"exemplaire\" VARCHAR(42) [NOT NULL]\n  \"foobar\"     VARCHAR(42)\n  Indexes {\n    (\"œuvre\", \"exemplaire\") [pk]\n  }\n}\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_0_ddl.sql",
    "content": "CREATE TABLE EXEMPLAIRE (\n  PRIMARY KEY (oeuvre, exemplaire),\n  oeuvre     VARCHAR(42) NOT NULL,\n  exemplaire VARCHAR(42) NOT NULL,\n  foobar     VARCHAR(42)\n);\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_1_ddl.d2",
    "content": "\"Exemplaire\": { shape: sql_table\n  \"œuvre\":      VARCHAR(42) {constraint: [PK; FK]}\n  \"exemplaire\": VARCHAR(42) {constraint: PK}\n  \"nb pages\":   VARCHAR(42) \n  \"date achat\": VARCHAR(42) \n  \"foobar\":     VARCHAR(42) \n}\n\n\"Œuvre\": { shape: sql_table\n  \"œuvre\":  VARCHAR(42) {constraint: PK}\n  \"auteur\": VARCHAR(42) \n}\n\n\"Exemplaire\".\"œuvre\" -> \"Œuvre\".\"œuvre\"\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_1_ddl.dbml",
    "content": "Table \"Exemplaire\" {\n  \"œuvre\"      VARCHAR(42) [NOT NULL]\n  \"exemplaire\" VARCHAR(42) [NOT NULL]\n  \"nb pages\"   VARCHAR(42)\n  \"date achat\" VARCHAR(42)\n  \"foobar\"     VARCHAR(42)\n  Indexes {\n    (\"œuvre\", \"exemplaire\") [pk]\n  }\n}\n\nTable \"Œuvre\" {\n  \"œuvre\"  VARCHAR(42) [pk, NOT NULL]\n  \"auteur\" VARCHAR(42)\n}\n\nRef:\"Exemplaire\".\"œuvre\" > \"Œuvre\".\"œuvre\"\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_1_ddl.sql",
    "content": "CREATE TABLE EXEMPLAIRE (\n  PRIMARY KEY (oeuvre, exemplaire),\n  oeuvre     VARCHAR(42) NOT NULL,\n  exemplaire VARCHAR(42) NOT NULL,\n  nb_pages   INTEGER,\n  date_achat DATE,\n  foobar     VARCHAR(42)\n);\n\nCREATE TABLE OEUVRE (\n  PRIMARY KEY (oeuvre),\n  oeuvre VARCHAR(42) NOT NULL,\n  auteur VARCHAR(42)\n);\n\nALTER TABLE EXEMPLAIRE ADD FOREIGN KEY (oeuvre) REFERENCES OEUVRE (oeuvre);\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_2_ddl.d2",
    "content": "\"Appartement\": { shape: sql_table\n  \"code rue\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"num immeuble\": VARCHAR(42) {constraint: [PK; FK]}\n  \"num étage\":    VARCHAR(42) {constraint: [PK; FK]}\n  \"num appart.\":  VARCHAR(42) {constraint: PK}\n  \"nb pièces\":    VARCHAR(42) \n}\n\n\"Étage\": { shape: sql_table\n  \"code rue\":        VARCHAR(42) {constraint: [PK; FK]}\n  \"num immeuble\":    VARCHAR(42) {constraint: [PK; FK]}\n  \"num étage\":       VARCHAR(42) {constraint: PK}\n  \"nb appartements\": VARCHAR(42) \n}\n\n\"Immeuble\": { shape: sql_table\n  \"code rue\":     VARCHAR(42) {constraint: [PK; FK]}\n  \"num immeuble\": VARCHAR(42) {constraint: PK}\n  \"nb étages\":    VARCHAR(42) \n}\n\n\"Rue\": { shape: sql_table\n  \"code rue\": VARCHAR(42) {constraint: PK}\n  \"nom rue\":  VARCHAR(42) \n}\n\n\"Appartement\".\"code rue\" -> \"Étage\".\"code rue\"\n\"Appartement\".\"num immeuble\" -> \"Étage\".\"num immeuble\"\n\"Appartement\".\"num étage\" -> \"Étage\".\"num étage\"\n\"Étage\".\"code rue\" -> \"Immeuble\".\"code rue\"\n\"Étage\".\"num immeuble\" -> \"Immeuble\".\"num immeuble\"\n\"Immeuble\".\"code rue\" -> \"Rue\".\"code rue\"\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_2_ddl.dbml",
    "content": "Table \"Appartement\" {\n  \"code rue\"     VARCHAR(42) [NOT NULL]\n  \"num immeuble\" VARCHAR(42) [NOT NULL]\n  \"num étage\"    VARCHAR(42) [NOT NULL]\n  \"num appart.\"  VARCHAR(42) [NOT NULL]\n  \"nb pièces\"    VARCHAR(42)\n  Indexes {\n    (\"code rue\", \"num immeuble\", \"num étage\", \"num appart.\") [pk]\n  }\n}\n\nTable \"Étage\" {\n  \"code rue\"        VARCHAR(42) [NOT NULL]\n  \"num immeuble\"    VARCHAR(42) [NOT NULL]\n  \"num étage\"       VARCHAR(42) [NOT NULL]\n  \"nb appartements\" VARCHAR(42)\n  Indexes {\n    (\"code rue\", \"num immeuble\", \"num étage\") [pk]\n  }\n}\n\nTable \"Immeuble\" {\n  \"code rue\"     VARCHAR(42) [NOT NULL]\n  \"num immeuble\" VARCHAR(42) [NOT NULL]\n  \"nb étages\"    VARCHAR(42)\n  Indexes {\n    (\"code rue\", \"num immeuble\") [pk]\n  }\n}\n\nTable \"Rue\" {\n  \"code rue\" VARCHAR(42) [pk, NOT NULL]\n  \"nom rue\"  VARCHAR(42)\n}\n\nRef:\"Appartement\".(\"code rue\", \"num étage\", \"num immeuble\") > \"Étage\".(\"code rue\", \"num étage\", \"num immeuble\")\nRef:\"Étage\".(\"code rue\", \"num immeuble\") > \"Immeuble\".(\"code rue\", \"num immeuble\")\nRef:\"Immeuble\".\"code rue\" > \"Rue\".\"code rue\"\n"
  },
  {
    "path": "test/zoo/weak/ddl/weak_2_ddl.sql",
    "content": "CREATE TABLE APPARTEMENT (\n  PRIMARY KEY (code_rue, num_immeuble, num_etage, num_appart),\n  code_rue     VARCHAR(8) NOT NULL,\n  num_immeuble VARCHAR(8) NOT NULL,\n  num_etage    VARCHAR(8) NOT NULL,\n  num_appart   VARCHAR(8) NOT NULL,\n  nb_pieces    INTEGER\n);\n\nCREATE TABLE ETAGE (\n  PRIMARY KEY (code_rue, num_immeuble, num_etage),\n  code_rue        VARCHAR(8) NOT NULL,\n  num_immeuble    VARCHAR(8) NOT NULL,\n  num_etage       VARCHAR(8) NOT NULL,\n  nb_appartements INTEGER\n);\n\nCREATE TABLE IMMEUBLE (\n  PRIMARY KEY (code_rue, num_immeuble),\n  code_rue     VARCHAR(8) NOT NULL,\n  num_immeuble VARCHAR(8) NOT NULL,\n  nb_etages    INTEGER\n);\n\nCREATE TABLE RUE (\n  PRIMARY KEY (code_rue),\n  code_rue VARCHAR(8) NOT NULL,\n  nom_rue  VARCHAR(255)\n);\n\nALTER TABLE APPARTEMENT ADD FOREIGN KEY (code_rue, num_immeuble, num_etage) REFERENCES ETAGE (code_rue, num_immeuble, num_etage);\n\nALTER TABLE ETAGE ADD FOREIGN KEY (code_rue, num_immeuble) REFERENCES IMMEUBLE (code_rue, num_immeuble);\n\nALTER TABLE IMMEUBLE ADD FOREIGN KEY (code_rue) REFERENCES RUE (code_rue);\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_0_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Œuvre\"]\n  4 [label=\"Exemplaire\",peripheries=2]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>œuvre</u>>]\n  6 [label=<<u>exemplaire</u>> style=\"dashed,filled\"]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  5 [label=\"foobar\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  4 -- 6\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  3 -- 5\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 3 [color=\"#000000\"]\n  edge [headlabel=N]\n  4 -- 3\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_0_erd_chen.txt",
    "content": "[[Exemplaire]] ==N== <<DF>>\n[Œuvre] --1-- <<DF>>\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_0_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Œuvre</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">œuvre</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Exemplaire</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">exemplaire</td></tr>\n        <tr><td> </td><td align=\"left\">foobar</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_0_erd_crow.mmd",
    "content": "erDiagram\n  OEuvre {\n    TYPE oeuvre PK\n  }\n  Exemplaire {\n    TYPE exemplaire PK\n    TYPE foobar\n  }\n  OEuvre ||..o{ Exemplaire: DF"
  },
  {
    "path": "test/zoo/weak/exported/weak_0_uml.puml",
    "content": "@startuml \"weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Œuvre\") {\n    {field} + pk(œuvre)\n}\n\n\"Œuvre\" \"1\" *-- \"*\" \"Exemplaire\"\n\nTable(\"Exemplaire\") {\n    {field} + pk(exemplaire)\n    {field} + foobar\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_1_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Œuvre\"]\n  5 [label=\"Exemplaire\",peripheries=2]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"auteur\"]\n  8 [label=\"nb\\npages\"]\n  9 [label=\"date\\nachat\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>œuvre</u>>]\n  7 [label=<<u>exemplaire</u>> style=\"dashed,filled\"]\n\n  // Relationship attributes\n  node [\n    fillcolor=\"#FFFFFF\"\n  ]\n  6 [label=\"foobar\"]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"DF\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 7\n  5 -- 8\n  5 -- 9\n\n  // Edges between relationships and attributes\n  edge [color=\"#000000\"]\n  4 -- 6\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  1 -- 4 [color=\"#000000\"]\n  edge [headlabel=N]\n  5 -- 4\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_1_erd_chen.txt",
    "content": "[[Exemplaire]] ==N== <<DF>>\n[Œuvre] --1-- <<DF>>\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_1_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Œuvre</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">œuvre</td></tr>\n        <tr><td> </td><td align=\"left\">auteur</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Exemplaire</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">exemplaire</td></tr>\n        <tr><td> </td><td align=\"left\">nb pages</td></tr>\n        <tr><td> </td><td align=\"left\">date achat</td></tr>\n        <tr><td> </td><td align=\"left\">foobar</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  1 -> 2 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"DF\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_1_erd_crow.mmd",
    "content": "erDiagram\n  OEuvre {\n    TYPE oeuvre PK\n    TYPE auteur\n  }\n  Exemplaire {\n    TYPE exemplaire PK\n    TYPE nb_pages\n    TYPE date_achat\n    TYPE foobar\n  }\n  OEuvre ||..o{ Exemplaire: DF"
  },
  {
    "path": "test/zoo/weak/exported/weak_1_uml.puml",
    "content": "@startuml \"weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Œuvre\") {\n    {field} + pk(œuvre)\n    {field} + auteur\n}\n\n\"Œuvre\" \"1\" *-- \"*\" \"Exemplaire\"\n\nTable(\"Exemplaire\") {\n    {field} + pk(exemplaire)\n    {field} + nb pages\n    {field} + date achat\n    {field} + foobar\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_2_erd_chen.gv",
    "content": "graph{\n  start=42\n\n  // Entities\n  node [\n    shape=box\n    style=filled\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  1 [label=\"Appartement\",peripheries=2]\n  5 [label=\"Étage\",peripheries=2]\n  9 [label=\"Immeuble\",peripheries=2]\n  13 [label=\"Rue\"]\n\n  // Normal entity attributes\n  node [\n    shape=oval\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  3 [label=\"nb\\npièces\"]\n  7 [label=\"nb\\nappartements\"]\n  11 [label=\"nb\\nétages\"]\n  15 [label=\"nom rue\"]\n\n  // Weak and strong entity attributes\n  2 [label=<<u>num<br/>appart.</u>> style=\"dashed,filled\"]\n  6 [label=<<u>num<br/>étage</u>> style=\"dashed,filled\"]\n  10 [label=<<u>num<br/>immeuble</u>> style=\"dashed,filled\"]\n  14 [label=<<u>code rue</u>>]\n\n  // Relationships\n  node [\n    shape=diamond\n    height=0.7\n    penwidth=1.5\n    fillcolor=\"#FFFFFF\"\n  ]\n  4 [label=\"Composer\",peripheries=2]\n  8 [label=\"Appartenir\",peripheries=2]\n  12 [label=\"Se\\nsituer\",peripheries=2]\n\n  // Edges between entities and attributes\n  edge [\n    penwidth=1.5\n  ]\n  1 -- 2\n  1 -- 3\n  5 -- 6\n  5 -- 7\n  9 -- 10\n  9 -- 11\n  13 -- 14\n  13 -- 15\n\n  // Edges between entities and relationships\n  edge [\n    penwidth=1\n    color=\"#000000:#000000\"\n    labeldistance=2\n    headlabel=1\n  ]\n  9 -- 8\n  5 -- 4 [color=\"#000000\"]\n  13 -- 12 [color=\"#000000\"]\n  edge [headlabel=N]\n  1 -- 4\n  5 -- 8\n  9 -- 12\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_2_erd_chen.txt",
    "content": "[Rue] --1-- <<Se situer>>\n[[Appartement]] ==N== <<Composer>>\n[[Immeuble]] ==1== <<Appartenir>>\n[[Immeuble]] ==N== <<Se situer>>\n[[Étage]] --1-- <<Composer>>\n[[Étage]] ==N== <<Appartenir>>\n"
  },
  {
    "path": "test/zoo/weak/exported/weak_2_erd_crow.gv",
    "content": "digraph{\n  layout=dot\n  bgcolor=\"#FFFFFF\"\n  nodesep=0.5\n\n  // Nodes\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  node [\n      shape=none\n      fontcolor=\"#000000\"\n      fontsize=15\n      fontname=\"Helvetica\"\n]\n  1 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Appartement</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num appart.</td></tr>\n        <tr><td> </td><td align=\"left\">nb pièces</td></tr>\n    </table>\n>]\n  2 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Étage</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num étage</td></tr>\n        <tr><td> </td><td align=\"left\">nb appartements</td></tr>\n    </table>\n>]\n  3 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Immeuble</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">num immeuble</td></tr>\n        <tr><td> </td><td align=\"left\">nb étages</td></tr>\n    </table>\n>]\n  4 [label=<<table\n        border=\"0\"\n        cellborder=\"1\"\n        cellspacing=\"0\"\n        bgcolor=\"#FFFFFF\"\n        color=\"#000000\"\n        cellpadding=\"4\"\n    >\n        <tr>\n            <td bgcolor=\"#FFFFFF\" colspan=\"2\">\n                <font\n                    color=\"#000000\"\n                    point-size=\"18\"\n                >Rue</font>\n            </td>\n        </tr>\n        <tr><td>PK</td><td align=\"left\">code rue</td></tr>\n        <tr><td> </td><td align=\"left\">nom rue</td></tr>\n    </table>\n>]\n\n  // Edges\n  edge [\n    penwidth=1\n    color=\"#000000\"\n    fontcolor=\"#000000\"\n    fontname=\"Futura\"\n    fontsize=11\n    dir=both\n  ]\n  2 -> 1 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"Composer\" style=dotted]\n  3 -> 2 [arrowhead=\"crowtee\" arrowtail=\"teetee\" label=\"Appartenir\" style=dotted]\n  4 -> 3 [arrowhead=\"crowodot\" arrowtail=\"teetee\" label=\"Se situer\" style=dotted]\n}"
  },
  {
    "path": "test/zoo/weak/exported/weak_2_erd_crow.mmd",
    "content": "erDiagram\n  Appartement {\n    TYPE num_appart PK\n    TYPE nb_pieces\n  }\n  Etage {\n    TYPE num_etage PK\n    TYPE nb_appartements\n  }\n  Immeuble {\n    TYPE num_immeuble PK\n    TYPE nb_etages\n  }\n  Rue {\n    TYPE code_rue PK\n    TYPE nom_rue\n  }\n  Etage ||..o{ Appartement: Composer\n  Immeuble ||..|{ Etage: Appartenir\n  Rue ||..o{ Immeuble: Se_situer"
  },
  {
    "path": "test/zoo/weak/exported/weak_2_uml.puml",
    "content": "@startuml \"weak\"\n\n!define Table(x) class \"x\" << (T,#FFFFFF) >>\n!define pk(x) <b>x</b>\n\nTable(\"Appartement\") {\n    {field} + pk(num appart.)\n    {field} + nb pièces\n}\n\n\"Étage\" \"1\" *-- \"*\" \"Appartement\": \"Composer\"\n\nTable(\"Étage\") {\n    {field} + pk(num étage)\n    {field} + nb appartements\n}\n\n\"Immeuble\" \"1\" *-- \"1..*\" \"Étage\": \"Appartenir\"\n\nTable(\"Immeuble\") {\n    {field} + pk(num immeuble)\n    {field} + nb étages\n}\n\n\"Rue\" \"1\" *-- \"*\" \"Immeuble\": \"Se situer\"\n\nTable(\"Rue\") {\n    {field} + pk(code rue)\n    {field} + nom rue\n}\n\n@enduml\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nExemplaire\tœuvre\t!\t\tstrengthening_primary_ex_foreign_key\tTrue\tŒuvre\tŒuvre\tDF\t\t\nExemplaire\texemplaire\t!\t\tprimary_key\tTrue\t\t\t\t\t\nExemplaire\tfoobar\t\t\touter_attribute\tFalse\t\t\tDF\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"weak_0_mld.svg\"/></center><figcaption>MCD <i>weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Exemplaire</span> (\n    <span class='primary'>œuvre</span>,\n    <span class='primary'>exemplaire</span>,\n    <span class='normal'>foobar</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>œuvre</i> fait partie de la clé primaire de la table. Il a migré à partir de l'entité <i>Œuvre</i> pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.</li>\n    <li>Le champ <i>exemplaire</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Exemplaire</i>.</li>\n    <li>Le champ <i>foobar</i> a migré à partir de l'association de dépendance fonctionnelle <i>DF</i>.</li>\n  </ul></details>\n</div>\n<br><hr>\n\n<div>\n  <span><strong>NB.</strong> La table <i>Œuvre</i> a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.</span>\n</div>\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_mld.mcd",
    "content": "%%mocodo\n:\nExemplaire: œuvre, _exemplaire, foobar\n:\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_mld.md",
    "content": "- **Exemplaire** (<u>œuvre</u>, <u>exemplaire</u>, foobar)\n  - Le champ _œuvre_ fait partie de la clé primaire de la table. Il a migré à partir de l'entité _Œuvre_ pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ _exemplaire_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _Exemplaire_.\n  - Le champ _foobar_ a migré à partir de l'association de dépendance fonctionnelle _DF_.\n<br>\n----\n\n\n**NB.** La table _Œuvre_ a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Exemplaire} (\\prim{œuvre}, \\prim{exemplaire}, \\attr{foobar})\n  \\begin{itemize}\n    \\item Le champ \\emph{œuvre} fait partie de la clé primaire de la table. Il a migré à partir de l'entité \\emph{Œuvre} pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n    \\item Le champ \\emph{exemplaire} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Exemplaire}.\n    \\item Le champ \\emph{foobar} a migré à partir de l'association de dépendance fonctionnelle \\emph{DF}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_0_mld.txt",
    "content": "- Exemplaire (_œuvre_, _exemplaire_, foobar)\n  - Le champ « œuvre » fait partie de la clé primaire de la table. Il a migré à partir de l'entité « Œuvre » pour renforcer l'identifiant. Cependant, comme la table créée à partir de cette entité a été supprimée, il n'est pas considéré comme clé étrangère.\n  - Le champ « exemplaire » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « Exemplaire ».\n  - Le champ « foobar » a migré à partir de l'association de dépendance fonctionnelle « DF ».\n<br>\n--------------------------------------------------------------------------------\n\nNB. La table « Œuvre » a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nExemplaire\tœuvre\t!\t\tstrengthening_primary_foreign_key\tTrue\tŒuvre\tŒuvre\tDF\t\t\nExemplaire\texemplaire\t!\t\tprimary_key\tTrue\t\t\t\t\t\nExemplaire\tnb pages\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nExemplaire\tdate achat\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nExemplaire\tfoobar\t\t\touter_attribute\tFalse\t\t\tDF\t\t\nŒuvre\tœuvre\t!\t\tprimary_key\tTrue\t\t\t\t\t\nŒuvre\tauteur\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Œuvre\" -> \"Exemplaire\"\n}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"weak_1_mld.svg\"/></center><figcaption>MCD <i>weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Exemplaire</span> (\n    <span class='foreign primary'>#œuvre</span>,\n    <span class='primary'>exemplaire</span>,\n    <span class='normal'>nb pages</span>,\n    <span class='normal'>date achat</span>,\n    <span class='normal'>foobar</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>œuvre</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Œuvre</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>exemplaire</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Exemplaire</i>.</li>\n    <li>Les champs <i>nb pages</i> et <i>date achat</i> étaient déjà de simples attributs de l'entité <i>Exemplaire</i>.</li>\n    <li>Le champ <i>foobar</i> a migré à partir de l'association de dépendance fonctionnelle <i>DF</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Œuvre</span> (\n    <span class='primary'>œuvre</span>,\n    <span class='normal'>auteur</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>œuvre</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Œuvre</i>.</li>\n    <li>Le champ <i>auteur</i> était déjà un simple attribut de l'entité <i>Œuvre</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_mld.mcd",
    "content": "%%mocodo\n:\nŒuvre: œuvre, auteur\n:\nExemplaire: #œuvre > Œuvre > œuvre, _exemplaire, nb pages, date achat, foobar\n:\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_mld.md",
    "content": "- **Exemplaire** (<u>_#œuvre_</u>, <u>exemplaire</u>, nb pages, date achat, foobar)\n  - Le champ _œuvre_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Œuvre_ pour renforcer l'identifiant.\n  - Le champ _exemplaire_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _Exemplaire_.\n  - Les champs _nb pages_ et _date achat_ étaient déjà de simples attributs de l'entité _Exemplaire_.\n  - Le champ _foobar_ a migré à partir de l'association de dépendance fonctionnelle _DF_.\n\n- **Œuvre** (<u>œuvre</u>, auteur)\n  - Le champ _œuvre_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Œuvre_.\n  - Le champ _auteur_ était déjà un simple attribut de l'entité _Œuvre_.\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Exemplaire} (\\foreign{\\prim{œuvre}}, \\prim{exemplaire}, \\attr{nb pages}, \\attr{date achat}, \\attr{foobar})\n  \\begin{itemize}\n    \\item Le champ \\emph{œuvre} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Œuvre} pour renforcer l'identifiant.\n    \\item Le champ \\emph{exemplaire} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Exemplaire}.\n    \\item Les champs \\emph{nb pages} et \\emph{date achat} étaient déjà de simples attributs de l'entité \\emph{Exemplaire}.\n    \\item Le champ \\emph{foobar} a migré à partir de l'association de dépendance fonctionnelle \\emph{DF}.\n  \\end{itemize}\n\n  \\item \\relat{Œuvre} (\\prim{œuvre}, \\attr{auteur})\n  \\begin{itemize}\n    \\item Le champ \\emph{œuvre} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Œuvre}.\n    \\item Le champ \\emph{auteur} était déjà un simple attribut de l'entité \\emph{Œuvre}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_1_mld.txt",
    "content": "- Exemplaire (_#œuvre_, _exemplaire_, nb pages, date achat, foobar)\n  - Le champ « œuvre » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Œuvre » pour renforcer l'identifiant.\n  - Le champ « exemplaire » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « Exemplaire ».\n  - Les champs « nb pages » et « date achat » étaient déjà de simples attributs de l'entité « Exemplaire ».\n  - Le champ « foobar » a migré à partir de l'association de dépendance fonctionnelle « DF ».\n\n- Œuvre (_œuvre_, auteur)\n  - Le champ « œuvre » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Œuvre ».\n  - Le champ « auteur » était déjà un simple attribut de l'entité « Œuvre ».\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_debug.tsv",
    "content": "this relation name\tattribute\toptionality\tunicities\tnature\tis primary\tadjacent source\touter source\tassociation name\tdatatype\tleg note\nAppartement\tcode rue\t!\t\tstrengthening_primary_foreign_key\tTrue\tÉtage\tÉtage\tComposer\t\t\nAppartement\tnum immeuble\t!\t\tstrengthening_primary_foreign_key\tTrue\tÉtage\tÉtage\tComposer\t\t\nAppartement\tnum étage\t!\t\tstrengthening_primary_foreign_key\tTrue\tÉtage\tÉtage\tComposer\t\t\nAppartement\tnum appart.\t!\t\tprimary_key\tTrue\t\t\t\t\t\nAppartement\tnb pièces\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nÉtage\tcode rue\t!\t\tstrengthening_primary_foreign_key\tTrue\tImmeuble\tImmeuble\tAppartenir\t\t\nÉtage\tnum immeuble\t!\t\tstrengthening_primary_foreign_key\tTrue\tImmeuble\tImmeuble\tAppartenir\t\t\nÉtage\tnum étage\t!\t\tprimary_key\tTrue\t\t\t\t\t\nÉtage\tnb appartements\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nImmeuble\tcode rue\t!\t\tstrengthening_primary_foreign_key\tTrue\tRue\tRue\tSe situer\t\t\nImmeuble\tnum immeuble\t!\t\tprimary_key\tTrue\t\t\t\t\t\nImmeuble\tnb étages\t\t\tnormal_attribute\tFalse\t\t\t\t\t\nRue\tcode rue\t!\t\tprimary_key\tTrue\t\t\t\t\t\nRue\tnom rue\t\t\tnormal_attribute\tFalse\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_dependencies.gv",
    "content": "digraph {\n  node [shape=box]\n  \"Étage\" -> \"Appartement\"\n  \"Immeuble\" -> \"Étage\"\n  \"Rue\" -> \"Immeuble\"\n}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_mld.html",
    "content": "<html>\n<head>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\">\n<meta charset=\"utf-8\">\n<style>\n  .mld .relation { font-variant: small-caps; font-weight: bold }\n  .mld .primary { text-decoration: underline }\n  .mld .foreign { font-style: oblique }\n  .mld strong { font-weight: bold }\n  .mld i { font-style: italic }\n  .mld ul { list-style-type:square; margin: 0 0 1em 2em }\n</style>\n</head>\n<body>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><header><h1>Conversion en relationnel</h1><p>Générée par <a href=\"https://github.com/laowantong/mocodo\">Mocodo</a></p></header>\n<main>\n<!-- TO_BE_DELETED_BY_MOCODO_MAGIC --><figure><center><img src=\"weak_2_mld.svg\"/></center><figcaption>MCD <i>weak</i></figcaption></figure>\n<div class=\"mld\">\n<div>\n  <details><summary><span class='relation'>Appartement</span> (\n    <span class='foreign primary'>#code rue</span>,\n    <span class='foreign primary'>#num immeuble</span>,\n    <span class='foreign primary'>#num étage</span>,\n    <span class='primary'>num appart.</span>,\n    <span class='normal'>nb pièces</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code rue</i>, <i>num immeuble</i>, <i>num étage</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Étage</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>num appart.</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Appartement</i>.</li>\n    <li>Le champ <i>nb pièces</i> était déjà un simple attribut de l'entité <i>Appartement</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Étage</span> (\n    <span class='foreign primary'>#code rue</span>,\n    <span class='foreign primary'>#num immeuble</span>,\n    <span class='primary'>num étage</span>,\n    <span class='normal'>nb appartements</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code rue</i>, <i>num immeuble</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Immeuble</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>num étage</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Étage</i>.</li>\n    <li>Le champ <i>nb appartements</i> était déjà un simple attribut de l'entité <i>Étage</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Immeuble</span> (\n    <span class='foreign primary'>#code rue</span>,\n    <span class='primary'>num immeuble</span>,\n    <span class='normal'>nb étages</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code rue</i> fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité <i>Rue</i> pour renforcer l'identifiant.</li>\n    <li>Le champ <i>num immeuble</i> fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Immeuble</i>.</li>\n    <li>Le champ <i>nb étages</i> était déjà un simple attribut de l'entité <i>Immeuble</i>.</li>\n  </ul></details>\n</div>\n\n<div>\n  <details><summary><span class='relation'>Rue</span> (\n    <span class='primary'>code rue</span>,\n    <span class='normal'>nom rue</span>\n  )</summary>\n  <ul>\n    <li>Le champ <i>code rue</i> constitue la clé primaire de la table. C'était déjà un identifiant de l'entité <i>Rue</i>.</li>\n    <li>Le champ <i>nom rue</i> était déjà un simple attribut de l'entité <i>Rue</i>.</li>\n  </ul></details>\n</div>\n\n</div>\n</main>\n</body>\n</html>\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_mld.mcd",
    "content": "%%mocodo\n:\nAppartement: #code rue > Étage > code rue, _#num immeuble > Étage > num immeuble, _#num étage > Étage > num étage, _num appart., nb pièces\n:\nÉtage: #code rue > Immeuble > code rue, _#num immeuble > Immeuble > num immeuble, _num étage, nb appartements\n:\nImmeuble: #code rue > Rue > code rue, _num immeuble, nb étages\n:\nRue: code rue, nom rue\n:\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_mld.md",
    "content": "- **Appartement** (<u>_#code rue_</u>, <u>_#num immeuble_</u>, <u>_#num étage_</u>, <u>num appart.</u>, nb pièces)\n  - Le champ _code rue_, _num immeuble_, _num étage_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Étage_ pour renforcer l'identifiant.\n  - Le champ _num appart._ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _Appartement_.\n  - Le champ _nb pièces_ était déjà un simple attribut de l'entité _Appartement_.\n\n- **Étage** (<u>_#code rue_</u>, <u>_#num immeuble_</u>, <u>num étage</u>, nb appartements)\n  - Le champ _code rue_, _num immeuble_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Immeuble_ pour renforcer l'identifiant.\n  - Le champ _num étage_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _Étage_.\n  - Le champ _nb appartements_ était déjà un simple attribut de l'entité _Étage_.\n\n- **Immeuble** (<u>_#code rue_</u>, <u>num immeuble</u>, nb étages)\n  - Le champ _code rue_ fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité _Rue_ pour renforcer l'identifiant.\n  - Le champ _num immeuble_ fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité _Immeuble_.\n  - Le champ _nb étages_ était déjà un simple attribut de l'entité _Immeuble_.\n\n- **Rue** (<u>code rue</u>, nom rue)\n  - Le champ _code rue_ constitue la clé primaire de la table. C'était déjà un identifiant de l'entité _Rue_.\n  - Le champ _nom rue_ était déjà un simple attribut de l'entité _Rue_.\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_mld.tex",
    "content": "\\documentclass[a4paper]{article}\n\\usepackage[normalem]{ulem}\n\\usepackage[T1]{fontenc}\n\\usepackage[french]{babel}\n\\frenchsetup{StandardLayout=true}\n\n\\newcommand{\\relat}[1]{\\textsc{#1}}\n\\newcommand{\\attr}[1]{#1}\n\\newcommand{\\prim}[1]{\\uline{#1}}\n\\newcommand{\\foreign}[1]{\\#\\textsl{#1}}\n\n\\title{Conversion en relationnel\\\\du MCD \\emph{weak}}\n\\author{\\emph{Généré par Mocodo}}\n\n\\begin{document}\n\\maketitle\n\n\\begin{itemize}\n  \\item \\relat{Appartement} (\\foreign{\\prim{code rue}}, \\foreign{\\prim{num immeuble}}, \\foreign{\\prim{num étage}}, \\prim{num appart.}, \\attr{nb pièces})\n  \\begin{itemize}\n    \\item Le champ \\emph{code rue}, \\emph{num immeuble}, \\emph{num étage} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Étage} pour renforcer l'identifiant.\n    \\item Le champ \\emph{num appart.} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Appartement}.\n    \\item Le champ \\emph{nb pièces} était déjà un simple attribut de l'entité \\emph{Appartement}.\n  \\end{itemize}\n\n  \\item \\relat{Étage} (\\foreign{\\prim{code rue}}, \\foreign{\\prim{num immeuble}}, \\prim{num étage}, \\attr{nb appartements})\n  \\begin{itemize}\n    \\item Le champ \\emph{code rue}, \\emph{num immeuble} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Immeuble} pour renforcer l'identifiant.\n    \\item Le champ \\emph{num étage} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Étage}.\n    \\item Le champ \\emph{nb appartements} était déjà un simple attribut de l'entité \\emph{Étage}.\n  \\end{itemize}\n\n  \\item \\relat{Immeuble} (\\foreign{\\prim{code rue}}, \\prim{num immeuble}, \\attr{nb étages})\n  \\begin{itemize}\n    \\item Le champ \\emph{code rue} fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité \\emph{Rue} pour renforcer l'identifiant.\n    \\item Le champ \\emph{num immeuble} fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Immeuble}.\n    \\item Le champ \\emph{nb étages} était déjà un simple attribut de l'entité \\emph{Immeuble}.\n  \\end{itemize}\n\n  \\item \\relat{Rue} (\\prim{code rue}, \\attr{nom rue})\n  \\begin{itemize}\n    \\item Le champ \\emph{code rue} constitue la clé primaire de la table. C'était déjà un identifiant de l'entité \\emph{Rue}.\n    \\item Le champ \\emph{nom rue} était déjà un simple attribut de l'entité \\emph{Rue}.\n  \\end{itemize}\n\n\\end{itemize}\n\n\\end{document}\n"
  },
  {
    "path": "test/zoo/weak/mld/weak_2_mld.txt",
    "content": "- Appartement (_#code rue_, _#num immeuble_, _#num étage_, _num appart._, nb pièces)\n  - Le champ « code rue », « num immeuble », « num étage » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Étage » pour renforcer l'identifiant.\n  - Le champ « num appart. » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « Appartement ».\n  - Le champ « nb pièces » était déjà un simple attribut de l'entité « Appartement ».\n\n- Étage (_#code rue_, _#num immeuble_, _num étage_, nb appartements)\n  - Le champ « code rue », « num immeuble » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Immeuble » pour renforcer l'identifiant.\n  - Le champ « num étage » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « Étage ».\n  - Le champ « nb appartements » était déjà un simple attribut de l'entité « Étage ».\n\n- Immeuble (_#code rue_, _num immeuble_, nb étages)\n  - Le champ « code rue » fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré à partir de l'entité « Rue » pour renforcer l'identifiant.\n  - Le champ « num immeuble » fait partie de la clé primaire de la table. C'était déjà un identifiant de l'entité « Immeuble ».\n  - Le champ « nb étages » était déjà un simple attribut de l'entité « Immeuble ».\n\n- Rue (_code rue_, nom rue)\n  - Le champ « code rue » constitue la clé primaire de la table. C'était déjà un identifiant de l'entité « Rue ».\n  - Le champ « nom rue » était déjà un simple attribut de l'entité « Rue ».\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_create_df_arrows=across.mcd",
    "content": "Œuvre: œuvre\nDF, 0N> Œuvre, _11 Exemplaire: foobar\nExemplaire: exemplaire\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_drain.mcd",
    "content": "Œuvre: œuvre\nDF, 0N Œuvre, _11 Exemplaire\nExemplaire: exemplaire, foobar\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1\nDF, 0N ENTITÉ 1_, _11 ENTITÉ 2_: at 3 1\nENTITÉ 2_: at 2 1\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_0_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_create_df_arrows=across.mcd",
    "content": "Œuvre: œuvre, auteur\nDF, 0N> Œuvre, _11 Exemplaire: foobar\nExemplaire: exemplaire, nb pages, date achat\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_drain.mcd",
    "content": "Œuvre: œuvre, auteur\nDF, 0N Œuvre, _11 Exemplaire\nExemplaire: exemplaire, nb pages, date achat, foobar\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nDF, 0N ENTITÉ 1_, _11 ENTITÉ 2_: at 3 1\nENTITÉ 2_: at 2 1, at 2 2, at 2 3\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_1_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_create_df_arrows=across.mcd",
    "content": "Appartement: num appart., nb pièces\nComposer, 0N> Étage, _11 Appartement\nÉtage: num étage, nb appartements\nAppartenir, 1N> Immeuble, _11 Étage\nImmeuble: num immeuble, nb étages\nSe situer, 0N> Rue, _11 Immeuble\nRue: code rue, nom rue\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_drain.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_drown.mcd",
    "content": "ENTITÉ 1_: at 1 1, at 1 2\nASSOC 5_, 0N ENTITÉ 2_, _11 ENTITÉ 1_\nENTITÉ 2_: at 2 1, at 2 2\nASSOC 6_, 1N ENTITÉ 3_, _11 ENTITÉ 2_\nENTITÉ 3_: at 3 1, at 3 2\nASSOC 7_, 0N ENTITÉ 4_, _11 ENTITÉ 3_\nENTITÉ 4_: at 4 1, at 4 2\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=2,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=2.5,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=2.5.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=2.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=3,weak.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_explode_arity=3.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "test/zoo/weak/rewritten/weak_2_rw_split.mcd",
    "content": "% same as the source file\n"
  },
  {
    "path": "web/ace-builds/ace.js",
    "content": "(function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE=\"\",e=function(){return this}();!e&&typeof window!=\"undefined\"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!=\"undefined\")return;var t=function(e,n,r){if(typeof e!=\"string\"){t.original?t.original.apply(this,arguments):(console.error(\"dropping module because define wasn't a string.\"),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t==\"string\"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)===\"[object Array]\"){var o=[];for(var u=0,a=t.length;u<a;++u){var f=s(e,t[u]);if(f==undefined&&r.original)return;o.push(f)}return n&&n.apply(null,o)||!0}},r=function(e,t){var i=n(\"\",e,t);return i==undefined&&r.original?r.original.apply(this,arguments):i},i=function(e,t){if(t.indexOf(\"!\")!==-1){var n=t.split(\"!\");return i(e,n[0])+\"!\"+i(e,n[1])}if(t.charAt(0)==\".\"){var r=e.split(\"/\").slice(0,-1).join(\"/\");t=r+\"/\"+t;while(t.indexOf(\".\")!==-1&&s!=t){var s=t;t=t.replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return t},s=function(e,r){r=i(e,r);var s=t.modules[r];if(!s){s=t.payloads[r];if(typeof s==\"function\"){var o={},u={id:r,uri:\"\",exports:o,packaged:!0},a=function(e,t){return n(r,e,t)},f=s(a,o,u);o=f||u.exports,t.modules[r]=o,delete t.payloads[r]}s=t.modules[r]=o||s}return s};o(ACE_NAMESPACE)})(),define(\"ace/lib/es6-shim\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!1,writable:!0,configurable:!0})}String.prototype.startsWith||r(String.prototype,\"startsWith\",function(e,t){return t=t||0,this.lastIndexOf(e,t)===t}),String.prototype.endsWith||r(String.prototype,\"endsWith\",function(e,t){var n=this;if(t===undefined||t>n.length)t=n.length;t-=e.length;var r=n.indexOf(e,t);return r!==-1&&r===t}),String.prototype.repeat||r(String.prototype,\"repeat\",function(e){var t=\"\",n=this;while(e>0){e&1&&(t+=n);if(e>>=1)n+=n}return t}),String.prototype.includes||r(String.prototype,\"includes\",function(e,t){return this.indexOf(e,t)!=-1}),Object.assign||(Object.assign=function(e){if(e===undefined||e===null)throw new TypeError(\"Cannot convert undefined or null to object\");var t=Object(e);for(var n=1;n<arguments.length;n++){var r=arguments[n];r!==undefined&&r!==null&&Object.keys(r).forEach(function(e){t[e]=r[e]})}return t}),Object.values||(Object.values=function(e){return Object.keys(e).map(function(t){return e[t]})}),Array.prototype.find||r(Array.prototype,\"find\",function(e){var t=this.length,n=arguments[1];for(var r=0;r<t;r++){var i=this[r];if(e.call(n,i,r,this))return i}}),Array.prototype.findIndex||r(Array.prototype,\"findIndex\",function(e){var t=this.length,n=arguments[1];for(var r=0;r<t;r++){var i=this[r];if(e.call(n,i,r,this))return r}}),Array.prototype.includes||r(Array.prototype,\"includes\",function(e,t){return this.indexOf(e,t)!=-1}),Array.prototype.fill||r(Array.prototype,\"fill\",function(e){var t=this,n=t.length>>>0,r=arguments[1],i=r>>0,s=i<0?Math.max(n+i,0):Math.min(i,n),o=arguments[2],u=o===undefined?n:o>>0,a=u<0?Math.max(n+u,0):Math.min(u,n);while(s<a)t[s]=e,s++;return t}),Array.of||r(Array,\"of\",function(){return Array.prototype.slice.call(arguments)})}),define(\"ace/lib/fixoldbrowsers\",[\"require\",\"exports\",\"module\",\"ace/lib/es6-shim\"],function(e,t,n){\"use strict\";e(\"./es6-shim\")}),define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split(\"\").reverse().join(\"\")},t.stringRepeat=function(e,t){var n=\"\";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\\s\\s*/,i=/\\s\\s*$/;t.stringTrimLeft=function(e){return e.replace(r,\"\")},t.stringTrimRight=function(e){return e.replace(i,\"\")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]==\"object\"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function s(e){if(typeof e!=\"object\"||!e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n<e.length;n++)t[n]=s(e[n]);return t}if(Object.prototype.toString.call(e)!==\"[object Object]\")return e;t={};for(var n in e)t[n]=s(e[n]);return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},t.escapeHTML=function(e){return(\"\"+e).replace(/&/g,\"&#38;\").replace(/\"/g,\"&#34;\").replace(/'/g,\"&#39;\").replace(/</g,\"&#60;\")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r.isPending=function(){return t},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n==null&&(n=setTimeout(r,e||t))};return i.delay=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)},i.schedule=i,i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define(\"ace/lib/useragent\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.OS={LINUX:\"LINUX\",MAC:\"MAC\",WINDOWS:\"WINDOWS\"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};var r=typeof navigator==\"object\"?navigator:{},i=(/mac|win|linux/i.exec(r.platform)||[\"other\"])[0].toLowerCase(),s=r.userAgent||\"\",o=r.appName||\"\";t.isWin=i==\"win\",t.isMac=i==\"mac\",t.isLinux=i==\"linux\",t.isIE=o==\"Microsoft Internet Explorer\"||o.indexOf(\"MSAppHost\")>=0?parseFloat((s.match(/(?:MSIE |Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]):parseFloat((s.match(/(?:Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=s.match(/ Gecko\\/\\d+/),t.isOpera=typeof opera==\"object\"&&Object.prototype.toString.call(window.opera)==\"[object Opera]\",t.isWebKit=parseFloat(s.split(\"WebKit/\")[1])||undefined,t.isChrome=parseFloat(s.split(\" Chrome/\")[1])||undefined,t.isEdge=parseFloat(s.split(\" Edge/\")[1])||undefined,t.isAIR=s.indexOf(\"AdobeAIR\")>=0,t.isAndroid=s.indexOf(\"Android\")>=0,t.isChromeOS=s.indexOf(\" CrOS \")>=0,t.isIOS=/iPad|iPhone|iPod/.test(s)&&!window.MSStream,t.isIOS&&(t.isMac=!0),t.isMobile=t.isIOS||t.isAndroid}),define(\"ace/lib/dom\",[\"require\",\"exports\",\"module\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function u(){var e=o;o=null,e&&e.forEach(function(e){a(e[0],e[1])})}function a(e,n,r){if(typeof document==\"undefined\")return;if(o)if(r)u();else if(r===!1)return o.push([e,n]);if(s)return;var i=r;if(!r||!r.getRootNode)i=document;else{i=r.getRootNode();if(!i||i==r)i=document}var a=i.ownerDocument||i;if(n&&t.hasCssString(n,i))return null;n&&(e+=\"\\n/*# sourceURL=ace/css/\"+n+\" */\");var f=t.createElement(\"style\");f.appendChild(a.createTextNode(e)),n&&(f.id=n),i==a&&(i=t.getDocumentHead(a)),i.insertBefore(f,i.firstChild)}var r=e(\"./useragent\"),i=\"http://www.w3.org/1999/xhtml\";t.buildDom=function l(e,t,n){if(typeof e==\"string\"&&e){var r=document.createTextNode(e);return t&&t.appendChild(r),r}if(!Array.isArray(e))return e&&e.appendChild&&t&&t.appendChild(e),e;if(typeof e[0]!=\"string\"||!e[0]){var i=[];for(var s=0;s<e.length;s++){var o=l(e[s],t,n);o&&i.push(o)}return i}var u=document.createElement(e[0]),a=e[1],f=1;a&&typeof a==\"object\"&&!Array.isArray(a)&&(f=2);for(var s=f;s<e.length;s++)l(e[s],u,n);return f==2&&Object.keys(a).forEach(function(e){var t=a[e];e===\"class\"?u.className=Array.isArray(t)?t.join(\" \"):t:typeof t==\"function\"||e==\"value\"||e[0]==\"$\"?u[e]=t:e===\"ref\"?n&&(n[t]=u):e===\"style\"?typeof t==\"string\"&&(u.style.cssText=t):t!=null&&u.setAttribute(e,t)}),t&&t.appendChild(u),u},t.getDocumentHead=function(e){return e||(e=document),e.head||e.getElementsByTagName(\"head\")[0]||e.documentElement},t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||i,e):document.createElement(e)},t.removeChildren=function(e){e.innerHTML=\"\"},t.createTextNode=function(e,t){var n=t?t.ownerDocument:document;return n.createTextNode(e)},t.createFragment=function(e){var t=e?e.ownerDocument:document;return t.createDocumentFragment()},t.hasCssClass=function(e,t){var n=(e.className+\"\").split(/\\s+/g);return n.indexOf(t)!==-1},t.addCssClass=function(e,n){t.hasCssClass(e,n)||(e.className+=\" \"+n)},t.removeCssClass=function(e,t){var n=e.className.split(/\\s+/g);for(;;){var r=n.indexOf(t);if(r==-1)break;n.splice(r,1)}e.className=n.join(\" \")},t.toggleCssClass=function(e,t){var n=e.className.split(/\\s+/g),r=!0;for(;;){var i=n.indexOf(t);if(i==-1)break;r=!1,n.splice(i,1)}return r&&n.push(t),e.className=n.join(\" \"),r},t.setCssClass=function(e,n,r){r?t.addCssClass(e,n):t.removeCssClass(e,n)},t.hasCssString=function(e,t){var n=0,r;t=t||document;if(r=t.querySelectorAll(\"style\"))while(n<r.length)if(r[n++].id===e)return!0},t.removeElementById=function(e,t){t=t||document,t.getElementById(e)&&t.getElementById(e).remove()};var s,o=[];t.useStrictCSP=function(e){s=e,e==0?u():o||(o=[])},t.importCssString=a,t.importCssStylsheet=function(e,n){t.buildDom([\"link\",{rel:\"stylesheet\",href:e}],t.getDocumentHead(n))},t.scrollbarWidth=function(e){var n=t.createElement(\"ace_inner\");n.style.width=\"100%\",n.style.minWidth=\"0px\",n.style.height=\"200px\",n.style.display=\"block\";var r=t.createElement(\"ace_outer\"),i=r.style;i.position=\"absolute\",i.left=\"-10000px\",i.overflow=\"hidden\",i.width=\"200px\",i.minWidth=\"0px\",i.height=\"150px\",i.display=\"block\",r.appendChild(n);var s=e&&e.documentElement||document&&document.documentElement;if(!s)return 0;s.appendChild(r);var o=n.offsetWidth;i.overflow=\"scroll\";var u=n.offsetWidth;return o===u&&(u=r.clientWidth),s.removeChild(r),o-u},t.computedStyle=function(e,t){return window.getComputedStyle(e,\"\")||{}},t.setStyle=function(e,t,n){e[t]!==n&&(e[t]=n)},t.HAS_CSS_ANIMATION=!1,t.HAS_CSS_TRANSFORMS=!1,t.HI_DPI=r.isWin?typeof window!=\"undefined\"&&window.devicePixelRatio>=1.5:!0,r.isChromeOS&&(t.HI_DPI=!1);if(typeof document!=\"undefined\"){var f=document.createElement(\"div\");t.HI_DPI&&f.style.transform!==undefined&&(t.HAS_CSS_TRANSFORMS=!0),!r.isEdge&&typeof f.style.animationName!=\"undefined\"&&(t.HAS_CSS_ANIMATION=!0),f=null}t.HAS_CSS_TRANSFORMS?t.translate=function(e,t,n){e.style.transform=\"translate(\"+Math.round(t)+\"px, \"+Math.round(n)+\"px)\"}:t.translate=function(e,t,n){e.style.top=Math.round(n)+\"px\",e.style.left=Math.round(t)+\"px\"}}),define(\"ace/lib/net\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"./dom\");t.get=function(e,t){var n=new XMLHttpRequest;n.open(\"GET\",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement(\"script\");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState==\"loaded\"||i.readyState==\"complete\")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement(\"a\");return t.href=e,t.href}}),define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!=\"object\"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o<n.length;o++){n[o](t,this);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t,this)},r._signal=function(e,t){var n=(this._eventRegistry||{})[e];if(!n)return;n=n.slice();for(var r=0;r<n.length;r++)n[r](t,this)},r.once=function(e,t){var n=this;this.on(e,function r(){n.off(e,r),t.apply(null,arguments)});if(!t)return new Promise(function(e){t=e})},r.setDefaultHandler=function(e,t){var n=this._defaultHandlers;n||(n=this._defaultHandlers={_disabled_:{}});if(n[e]){var r=n[e],i=n._disabled_[e];i||(n._disabled_[e]=i=[]),i.push(r);var s=i.indexOf(t);s!=-1&&i.splice(s,1)}n[e]=t},r.removeDefaultHandler=function(e,t){var n=this._defaultHandlers;if(!n)return;var r=n._disabled_[e];if(n[e]==t)r&&this.setDefaultHandler(e,r.pop());else if(r){var i=r.indexOf(t);i!=-1&&r.splice(i,1)}},r.on=r.addEventListener=function(e,t,n){this._eventRegistry=this._eventRegistry||{};var r=this._eventRegistry[e];return r||(r=this._eventRegistry[e]=[]),r.indexOf(t)==-1&&r[n?\"unshift\":\"push\"](t),t},r.off=r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){e||(this._eventRegistry=this._defaultHandlers=undefined),this._eventRegistry&&(this._eventRegistry[e]=undefined),this._defaultHandlers&&(this._defaultHandlers[e]=undefined)},t.EventEmitter=r}),define(\"ace/lib/app_config\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"no use strict\";function o(e){typeof console!=\"undefined\"&&console.warn&&console.warn.apply(console,arguments)}function u(e,t){var n=new Error(e);n.data=t,typeof console==\"object\"&&console.error&&console.error(n),setTimeout(function(){throw n})}var r=e(\"./oop\"),i=e(\"./event_emitter\").EventEmitter,s={setOptions:function(e){Object.keys(e).forEach(function(t){this.setOption(t,e[t])},this)},getOptions:function(e){var t={};if(!e){var n=this.$options;e=Object.keys(n).filter(function(e){return!n[e].hidden})}else Array.isArray(e)||(t=e,e=Object.keys(t));return e.forEach(function(e){t[e]=this.getOption(e)},this),t},setOption:function(e,t){if(this[\"$\"+e]===t)return;var n=this.$options[e];if(!n)return o('misspelled option \"'+e+'\"');if(n.forwardTo)return this[n.forwardTo]&&this[n.forwardTo].setOption(e,t);n.handlesSet||(this[\"$\"+e]=t),n&&n.set&&n.set.call(this,t)},getOption:function(e){var t=this.$options[e];return t?t.forwardTo?this[t.forwardTo]&&this[t.forwardTo].getOption(e):t&&t.get?t.get.call(this):this[\"$\"+e]:o('misspelled option \"'+e+'\"')}},a,f=function(){function e(){this.$defaultOptions={}}return e.prototype.defineOptions=function(e,t,n){return e.$options||(this.$defaultOptions[t]=e.$options={}),Object.keys(n).forEach(function(t){var r=n[t];typeof r==\"string\"&&(r={forwardTo:r}),r.name||(r.name=t),e.$options[r.name]=r,\"initialValue\"in r&&(e[\"$\"+r.name]=r.initialValue)}),r.implement(e,s),this},e.prototype.resetOptions=function(e){Object.keys(e.$options).forEach(function(t){var n=e.$options[t];\"value\"in n&&e.setOption(t,n.value)})},e.prototype.setDefaultValue=function(e,t,n){if(!e){for(e in this.$defaultOptions)if(this.$defaultOptions[e][t])break;if(!this.$defaultOptions[e][t])return!1}var r=this.$defaultOptions[e]||(this.$defaultOptions[e]={});r[t]&&(r.forwardTo?this.setDefaultValue(r.forwardTo,t,n):r[t].value=n)},e.prototype.setDefaultValues=function(e,t){Object.keys(t).forEach(function(n){this.setDefaultValue(e,n,t[n])},this)},e.prototype.setMessages=function(e){a=e},e.prototype.nls=function(e,t){var n=a&&a[e]||e;return t&&(n=n.replace(/\\$(\\$|[\\d]+)/g,function(e,n){return n==\"$\"?\"$\":t[n]})),n},e}();f.prototype.warn=o,f.prototype.reportError=u,r.implement(f.prototype,i),t.AppConfig=f}),define(\"ace/theme/textmate.css\",[\"require\",\"exports\",\"module\"],function(e,t,n){n.exports='.ace-tm .ace_gutter {\\n  background: #f0f0f0;\\n  color: #333;\\n}\\n\\n.ace-tm .ace_print-margin {\\n  width: 1px;\\n  background: #e8e8e8;\\n}\\n\\n.ace-tm .ace_fold {\\n    background-color: #6B72E6;\\n}\\n\\n.ace-tm {\\n  background-color: #FFFFFF;\\n  color: black;\\n}\\n\\n.ace-tm .ace_cursor {\\n  color: black;\\n}\\n        \\n.ace-tm .ace_invisible {\\n  color: rgb(191, 191, 191);\\n}\\n\\n.ace-tm .ace_storage,\\n.ace-tm .ace_keyword {\\n  color: blue;\\n}\\n\\n.ace-tm .ace_constant {\\n  color: rgb(197, 6, 11);\\n}\\n\\n.ace-tm .ace_constant.ace_buildin {\\n  color: rgb(88, 72, 246);\\n}\\n\\n.ace-tm .ace_constant.ace_language {\\n  color: rgb(88, 92, 246);\\n}\\n\\n.ace-tm .ace_constant.ace_library {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-tm .ace_invalid {\\n  background-color: rgba(255, 0, 0, 0.1);\\n  color: red;\\n}\\n\\n.ace-tm .ace_support.ace_function {\\n  color: rgb(60, 76, 114);\\n}\\n\\n.ace-tm .ace_support.ace_constant {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-tm .ace_support.ace_type,\\n.ace-tm .ace_support.ace_class {\\n  color: rgb(109, 121, 222);\\n}\\n\\n.ace-tm .ace_keyword.ace_operator {\\n  color: rgb(104, 118, 135);\\n}\\n\\n.ace-tm .ace_string {\\n  color: rgb(3, 106, 7);\\n}\\n\\n.ace-tm .ace_comment {\\n  color: rgb(76, 136, 107);\\n}\\n\\n.ace-tm .ace_comment.ace_doc {\\n  color: rgb(0, 102, 255);\\n}\\n\\n.ace-tm .ace_comment.ace_doc.ace_tag {\\n  color: rgb(128, 159, 191);\\n}\\n\\n.ace-tm .ace_constant.ace_numeric {\\n  color: rgb(0, 0, 205);\\n}\\n\\n.ace-tm .ace_variable {\\n  color: rgb(49, 132, 149);\\n}\\n\\n.ace-tm .ace_xml-pe {\\n  color: rgb(104, 104, 91);\\n}\\n\\n.ace-tm .ace_entity.ace_name.ace_function {\\n  color: #0000A2;\\n}\\n\\n\\n.ace-tm .ace_heading {\\n  color: rgb(12, 7, 255);\\n}\\n\\n.ace-tm .ace_list {\\n  color:rgb(185, 6, 144);\\n}\\n\\n.ace-tm .ace_meta.ace_tag {\\n  color:rgb(0, 22, 142);\\n}\\n\\n.ace-tm .ace_string.ace_regex {\\n  color: rgb(255, 0, 0)\\n}\\n\\n.ace-tm .ace_marker-layer .ace_selection {\\n  background: rgb(181, 213, 255);\\n}\\n.ace-tm.ace_multiselect .ace_selection.ace_start {\\n  box-shadow: 0 0 3px 0px white;\\n}\\n.ace-tm .ace_marker-layer .ace_step {\\n  background: rgb(252, 255, 0);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_stack {\\n  background: rgb(164, 229, 101);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_bracket {\\n  margin: -1px 0 0 -1px;\\n  border: 1px solid rgb(192, 192, 192);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_active-line {\\n  background: rgba(0, 0, 0, 0.07);\\n}\\n\\n.ace-tm .ace_gutter-active-line {\\n    background-color : #dcdcdc;\\n}\\n\\n.ace-tm .ace_marker-layer .ace_selected-word {\\n  background: rgb(250, 250, 255);\\n  border: 1px solid rgb(200, 200, 250);\\n}\\n\\n.ace-tm .ace_indent-guide {\\n  background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\\n}\\n\\n.ace-tm .ace_indent-guide-active {\\n  background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAZSURBVHjaYvj///9/hivKyv8BAAAA//8DACLqBhbvk+/eAAAAAElFTkSuQmCC\") right repeat-y;\\n}\\n'}),define(\"ace/theme/textmate\",[\"require\",\"exports\",\"module\",\"ace/theme/textmate.css\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";t.isDark=!1,t.cssClass=\"ace-tm\",t.cssText=e(\"./textmate.css\"),t.$id=\"ace/theme/textmate\";var r=e(\"../lib/dom\");r.importCssString(t.cssText,t.cssClass,!1)}),define(\"ace/config\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/net\",\"ace/lib/dom\",\"ace/lib/app_config\",\"ace/theme/textmate\"],function(e,t,n){\"no use strict\";var r=e(\"./lib/lang\"),i=e(\"./lib/net\"),s=e(\"./lib/dom\"),o=e(\"./lib/app_config\").AppConfig;n.exports=t=new o;var u={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:\"\",suffix:\".js\",$moduleUrls:{},loadWorkerFromBlob:!0,sharedPopups:!1,useStrictCSP:null};t.get=function(e){if(!u.hasOwnProperty(e))throw new Error(\"Unknown config key: \"+e);return u[e]},t.set=function(e,t){if(u.hasOwnProperty(e))u[e]=t;else if(this.setDefaultValue(\"\",e,t)==0)throw new Error(\"Unknown config key: \"+e);e==\"useStrictCSP\"&&s.useStrictCSP(t)},t.all=function(){return r.copyObject(u)},t.$modes={},t.moduleUrl=function(e,t){if(u.$moduleUrls[e])return u.$moduleUrls[e];var n=e.split(\"/\");t=t||n[n.length-2]||\"\";var r=t==\"snippets\"?\"/\":\"-\",i=n[n.length-1];if(t==\"worker\"&&r==\"-\"){var s=new RegExp(\"^\"+t+\"[\\\\-_]|[\\\\-_]\"+t+\"$\",\"g\");i=i.replace(s,\"\")}(!i||i==t)&&n.length>1&&(i=n[n.length-2]);var o=u[t+\"Path\"];return o==null?o=u.basePath:r==\"/\"&&(t=r=\"\"),o&&o.slice(-1)!=\"/\"&&(o+=\"/\"),o+t+r+i+this.get(\"suffix\")},t.setModuleUrl=function(e,t){return u.$moduleUrls[e]=t};var a=function(t,n){return t===\"ace/theme/textmate\"||t===\"./theme/textmate\"?n(null,e(\"./theme/textmate\")):console.error(\"loader is not configured\")};t.setLoader=function(e){a=e},t.dynamicModules=Object.create(null),t.$loading={},t.loadModule=function(n,r){var s,o;Array.isArray(n)&&(o=n[0],n=n[1]);var u=function(e){if(e&&!t.$loading[n])return r&&r(e);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var s=function(){a(n,function(e,r){t._emit(\"load.module\",{name:n,module:r});var i=t.$loading[n];t.$loading[n]=null,i.forEach(function(e){e&&e(r)})})};if(!t.get(\"packaged\"))return s();i.loadScript(t.moduleUrl(n,o),s),f()};if(t.dynamicModules[n])t.dynamicModules[n]().then(function(e){e.default?u(e.default):u(e)});else{try{s=e(n)}catch(l){}u(s)}},t.setModuleLoader=function(e,n){t.dynamicModules[e]=n};var f=function(){!u.basePath&&!u.workerPath&&!u.modePath&&!u.themePath&&!Object.keys(u.$moduleUrls).length&&(console.error(\"Unable to infer path to ace from script src,\",\"use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes\",\"or with webpack use ace/webpack-resolver\"),f=function(){})};t.version=\"1.22.1\"}),define(\"ace/loader_build\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/config\"],function(e,t,n){\"use strict\";function s(t){if(!i||!i.document)return;r.set(\"packaged\",t||e.packaged||n.packaged||i.define&&define.packaged);var s={},u=\"\",a=document.currentScript||document._currentScript,f=a&&a.ownerDocument||document;a&&a.src&&(u=a.src.split(/[?#]/)[0].split(\"/\").slice(0,-1).join(\"/\")||\"\");var l=f.getElementsByTagName(\"script\");for(var c=0;c<l.length;c++){var h=l[c],p=h.src||h.getAttribute(\"src\");if(!p)continue;var d=h.attributes;for(var v=0,m=d.length;v<m;v++){var g=d[v];g.name.indexOf(\"data-ace-\")===0&&(s[o(g.name.replace(/^data-ace-/,\"\"))]=g.value)}var y=p.match(/^(.*)\\/ace([\\-.]\\w+)?\\.js(\\?|$)/);y&&(u=y[1])}u&&(s.base=s.base||u,s.packaged=!0),s.basePath=s.base,s.workerPath=s.workerPath||s.base,s.modePath=s.modePath||s.base,s.themePath=s.themePath||s.base,delete s.base;for(var b in s)typeof s[b]!=\"undefined\"&&r.set(b,s[b])}function o(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}e(\"./lib/fixoldbrowsers\");var r=e(\"./config\");r.setLoader(function(t,n){e([t],function(e){n(null,e)})});var i=function(){return this||typeof window!=\"undefined\"&&window}();n.exports=function(t){r.init=s,t.require=e,typeof define==\"function\"&&(t.define=define)}}),define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(){function e(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}}return e.prototype.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},e.prototype.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},e.prototype.contains=function(e,t){return this.compare(e,t)==0},e.prototype.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},e.prototype.comparePoint=function(e){return this.compare(e.row,e.column)},e.prototype.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},e.prototype.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},e.prototype.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},e.prototype.isStart=function(e,t){return this.start.row==e&&this.start.column==t},e.prototype.setStart=function(e,t){typeof e==\"object\"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},e.prototype.setEnd=function(e,t){typeof e==\"object\"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},e.prototype.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},e.prototype.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},e.prototype.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},e.prototype.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},e.prototype.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},e.prototype.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},e.prototype.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},e.prototype.clipRows=function(t,n){if(this.end.row>n)var r={row:n+1,column:0};else if(this.end.row<t)var r={row:t,column:0};if(this.start.row>n)var i={row:n+1,column:0};else if(this.start.row<t)var i={row:t,column:0};return e.fromPoints(i||this.start,r||this.end)},e.prototype.extend=function(t,n){var r=this.compare(t,n);if(r==0)return this;if(r==-1)var i={row:t,column:n};else var s={row:t,column:n};return e.fromPoints(i||this.start,s||this.end)},e.prototype.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},e.prototype.isMultiLine=function(){return this.start.row!==this.end.row},e.prototype.clone=function(){return e.fromPoints(this.start,this.end)},e.prototype.collapseRows=function(){return this.end.column==0?new e(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new e(this.start.row,0,this.end.row,0)},e.prototype.toScreenRange=function(t){var n=t.documentToScreenPosition(this.start),r=t.documentToScreenPosition(this.end);return new e(n.row,n.column,r.row,r.column)},e.prototype.moveBy=function(e,t){this.start.row+=e,this.start.column+=t,this.end.row+=e,this.end.column+=t},e}();i.fromPoints=function(e,t){return new i(e.row,e.column,t.row,t.column)},i.comparePoints=r,i.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},t.Range=i}),define(\"ace/lib/keys\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";var r=e(\"./oop\"),i=function(){var e={MODIFIER_KEYS:{16:\"Shift\",17:\"Ctrl\",18:\"Alt\",224:\"Meta\",91:\"MetaLeft\",92:\"MetaRight\",93:\"ContextMenu\"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,\"super\":8,meta:8,command:8,cmd:8,control:1},FUNCTION_KEYS:{8:\"Backspace\",9:\"Tab\",13:\"Return\",19:\"Pause\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"Print\",45:\"Insert\",46:\"Delete\",96:\"Numpad0\",97:\"Numpad1\",98:\"Numpad2\",99:\"Numpad3\",100:\"Numpad4\",101:\"Numpad5\",102:\"Numpad6\",103:\"Numpad7\",104:\"Numpad8\",105:\"Numpad9\",\"-13\":\"NumpadEnter\",112:\"F1\",113:\"F2\",114:\"F3\",115:\"F4\",116:\"F5\",117:\"F6\",118:\"F7\",119:\"F8\",120:\"F9\",121:\"F10\",122:\"F11\",123:\"F12\",144:\"Numlock\",145:\"Scrolllock\"},PRINTABLE_KEYS:{32:\" \",48:\"0\",49:\"1\",50:\"2\",51:\"3\",52:\"4\",53:\"5\",54:\"6\",55:\"7\",56:\"8\",57:\"9\",59:\";\",61:\"=\",65:\"a\",66:\"b\",67:\"c\",68:\"d\",69:\"e\",70:\"f\",71:\"g\",72:\"h\",73:\"i\",74:\"j\",75:\"k\",76:\"l\",77:\"m\",78:\"n\",79:\"o\",80:\"p\",81:\"q\",82:\"r\",83:\"s\",84:\"t\",85:\"u\",86:\"v\",87:\"w\",88:\"x\",89:\"y\",90:\"z\",107:\"+\",109:\"-\",110:\".\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",111:\"/\",106:\"*\"}};e.PRINTABLE_KEYS[173]=\"-\";var t,n;for(n in e.FUNCTION_KEYS)t=e.FUNCTION_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);for(n in e.PRINTABLE_KEYS)t=e.PRINTABLE_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e[\"return\"],e.escape=e.esc,e.del=e[\"delete\"],function(){var t=[\"cmd\",\"ctrl\",\"alt\",\"shift\"];for(var n=Math.pow(2,t.length);n--;)e.KEY_MODS[n]=t.filter(function(t){return n&e.KEY_MODS[t]}).join(\"-\")+\"-\"}(),e.KEY_MODS[0]=\"\",e.KEY_MODS[-1]=\"input-\",e}();r.mixin(t,i),t.keyCodeToString=function(e){var t=i[e];return typeof t!=\"string\"&&(t=String.fromCharCode(e)),t.toLowerCase()}}),define(\"ace/lib/event\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function a(){u=!1;try{document.createComment(\"\").addEventListener(\"test\",function(){},{get passive(){u={passive:!1}}})}catch(e){}}function f(){return u==undefined&&a(),u}function l(e,t,n){this.elem=e,this.type=t,this.callback=n}function d(e,t,n){var u=p(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState(\"OS\")||t.getModifierState(\"Win\"))&&(u|=8);if(s.altGr){if((3&u)==3)return;s.altGr=0}if(n===18||n===17){var a=\"location\"in t?t.location:t.keyLocation;if(n===17&&a===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&u===3&&a===2){var f=t.timeStamp-o;f<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1);if(!u&&n===13){var a=\"location\"in t?t.location:t.keyLocation;if(a===3){e(t,u,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&u&8){e(t,u,n);if(t.defaultPrevented)return;u&=-9}return!!u||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,u,n):!1}function v(){s=Object.create(null)}var r=e(\"./keys\"),i=e(\"./useragent\"),s=null,o=0,u;l.prototype.destroy=function(){h(this.elem,this.type,this.callback),this.elem=this.type=this.callback=undefined};var c=t.addListener=function(e,t,n,r){e.addEventListener(t,n,f()),r&&r.$toDestroy.push(new l(e,t,n))},h=t.removeListener=function(e,t,n){e.removeEventListener(t,n,f())};t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation&&e.stopPropagation()},t.preventDefault=function(e){e.preventDefault&&e.preventDefault()},t.getButton=function(e){return e.type==\"dblclick\"?0:e.type==\"contextmenu\"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.button},t.capture=function(e,t,n){function i(e){t&&t(e),n&&n(e),h(r,\"mousemove\",t),h(r,\"mouseup\",i),h(r,\"dragstart\",i)}var r=e&&e.ownerDocument||document;return c(r,\"mousemove\",t),c(r,\"mouseup\",i),c(r,\"dragstart\",i),i},t.addMouseWheelListener=function(e,t,n){c(e,\"wheel\",function(e){var n=.15,r=e.deltaX||0,i=e.deltaY||0;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=r*n,e.wheelY=i*n;break;case e.DOM_DELTA_LINE:var s=15;e.wheelX=r*s,e.wheelY=i*s;break;case e.DOM_DELTA_PAGE:var o=150;e.wheelX=r*o,e.wheelY=i*o}t(e)},n)},t.addMultiMouseDownListener=function(e,n,r,s,o){function p(e){t.getButton(e)!==0?u=0:e.detail>1?(u++,u>4&&(u=1)):u=1;if(i.isIE){var o=Math.abs(e.clientX-a)>5||Math.abs(e.clientY-f)>5;if(!l||o)u=1;l&&clearTimeout(l),l=setTimeout(function(){l=null},n[u-1]||600),u==1&&(a=e.clientX,f=e.clientY)}e._clicks=u,r[s](\"mousedown\",e);if(u>4)u=0;else if(u>1)return r[s](h[u],e)}var u=0,a,f,l,h={2:\"dblclick\",3:\"tripleclick\",4:\"quadclick\"};Array.isArray(e)||(e=[e]),e.forEach(function(e){c(e,\"mousedown\",p,o)})};var p=function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[p(e)]},t.addCommandKeyListener=function(e,n,r){if(i.isOldGecko||i.isOpera&&!(\"KeyboardEvent\"in window)){var o=null;c(e,\"keydown\",function(e){o=e.keyCode},r),c(e,\"keypress\",function(e){return d(n,e,o)},r)}else{var u=null;c(e,\"keydown\",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=d(n,e,e.keyCode);return u=e.defaultPrevented,t},r),c(e,\"keypress\",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)},r),c(e,\"keyup\",function(e){s[e.keyCode]=null},r),s||(v(),c(window,\"focus\",v))}};if(typeof window==\"object\"&&window.postMessage&&!i.isOldIE){var m=1;t.nextTick=function(e,n){n=n||window;var r=\"zero-timeout-message-\"+m++,i=function(s){s.data==r&&(t.stopPropagation(s),h(n,\"message\",i),e())};c(n,\"message\",i),n.postMessage(r,\"*\")}}t.$idleBlocked=!1,t.onIdle=function(e,n){return setTimeout(function r(){t.$idleBlocked?setTimeout(r,100):e()},n)},t.$idleBlockId=null,t.blockIdle=function(e){t.$idleBlockId&&clearTimeout(t.$idleBlockId),t.$idleBlocked=!0,t.$idleBlockId=setTimeout(function(){t.$idleBlocked=!1},e||100)},t.nextFrame=typeof window==\"object\"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define(\"ace/clipboard\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r;n.exports={lineMode:!1,pasteCancelled:function(){return r&&r>Date.now()-50?!0:r=!1},cancel:function(){r=Date.now()}}}),define(\"ace/keyboard/textinput\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/config\",\"ace/lib/useragent\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/clipboard\",\"ace/lib/keys\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../config\").nls,s=e(\"../lib/useragent\"),o=e(\"../lib/dom\"),u=e(\"../lib/lang\"),a=e(\"../clipboard\"),f=s.isChrome<18,l=s.isIE,c=s.isChrome>63,h=400,p=e(\"../lib/keys\"),d=p.KEY_MODS,v=s.isIOS,m=v?/\\s/:/\\n/,g=s.isMobile,y=function(e,t){function P(e){(!n||!n.parentNode)&&document.removeEventListener(\"selectionchange\",P);if(w)return;if(n.selectionStart!==n.selectionEnd)return;var r=n.selectionStart-C,i=k-C;r>0?r=Math.max(r-i,1):r===0&&i&&(r=-1);var s=Math.abs(r),o=r>0?p.right:p.left;for(var u=0;u<s;u++)t.onCommandKey({},0,o)}function $(){T=!0,n.blur(),n.focus(),T=!1}function K(e){e.keyCode==27&&n.value.length<n.selectionStart&&(w||(N=n.value),C=k=-1,M()),J()}function G(){clearTimeout(Q),Q=setTimeout(function(){S&&(n.style.cssText=S,S=\"\"),t.renderer.$isMousePressed=!1,t.renderer.$keepTextAreaAtCursor&&t.renderer.$moveTextAreaToCursor()},0)}function Z(e,t,n){var r=null,i=!1;n.addEventListener(\"keydown\",function(e){r&&clearTimeout(r),i=!0},!0),n.addEventListener(\"keyup\",function(e){r=setTimeout(function(){i=!1},100)},!0);var s=function(e){if(document.activeElement!==n)return;if(i||w||t.$mouseHandler.isMousePressed)return;if(y)return;var r=n.selectionStart,s=n.selectionEnd,o=null,u=0;if(r==0)o=p.up;else if(r==1)o=p.home;else if(s>k&&N[s]==\"\\n\")o=p.end;else if(r<C&&N[r-1]==\" \")o=p.left,u=d.option;else if(r<C||r==C&&k!=C&&r==s)o=p.left;else if(s>k&&N.slice(0,s).split(\"\\n\").length>2)o=p.down;else if(s>k&&N[s-1]==\" \")o=p.right,u=d.option;else if(s>k||s==k&&k!=C&&r==s)o=p.right;r!==s&&(u|=d.shift);if(o){var a=t.onCommandKey({},u,o);if(!a&&t.commands){o=p.keyCodeToString(o);var f=t.commands.findKeyCommand(u,o);f&&t.execCommand(f)}C=r,k=s,M(\"\")}};document.addEventListener(\"selectionchange\",s),t.on(\"destroy\",function(){document.removeEventListener(\"selectionchange\",s)})}var n=o.createElement(\"textarea\");n.className=\"ace_text-input\",n.setAttribute(\"wrap\",\"off\"),n.setAttribute(\"autocorrect\",\"off\"),n.setAttribute(\"autocapitalize\",\"off\"),n.setAttribute(\"spellcheck\",!1),n.style.opacity=\"0\",e.insertBefore(n,e.firstChild);var y=!1,b=!1,w=!1,E=!1,S=\"\";g||(n.style.fontSize=\"1px\");var x=!1,T=!1,N=\"\",C=0,k=0,L=0;try{var A=document.activeElement===n}catch(O){}this.setAriaOptions=function(e){e.activeDescendant?(n.setAttribute(\"aria-haspopup\",\"true\"),n.setAttribute(\"aria-autocomplete\",e.inline?\"both\":\"list\"),n.setAttribute(\"aria-activedescendant\",e.activeDescendant)):(n.setAttribute(\"aria-haspopup\",\"false\"),n.setAttribute(\"aria-autocomplete\",\"both\"),n.removeAttribute(\"aria-activedescendant\")),e.role&&n.setAttribute(\"role\",e.role)},this.setAriaLabel=function(){if(t.session&&t.renderer.enableKeyboardAccessibility){var e=t.session.selection.cursor.row;n.setAttribute(\"aria-roledescription\",i(\"editor\")),n.setAttribute(\"aria-label\",i(\"Cursor at row $0\",[e+1]))}else n.removeAttribute(\"aria-roledescription\"),n.removeAttribute(\"aria-label\")},this.setAriaOptions({role:\"textbox\"}),this.setAriaLabel(),r.addListener(n,\"blur\",function(e){if(T)return;t.onBlur(e),A=!1,g&&!v&&document.removeEventListener(\"selectionchange\",P)},t),r.addListener(n,\"focus\",function(e){if(T)return;A=!0;if(s.isEdge)try{if(!document.hasFocus())return}catch(e){}t.onFocus(e),s.isEdge?setTimeout(M):M(),g&&!v&&document.addEventListener(\"selectionchange\",P)},t),this.$focusScroll=!1,this.focus=function(){this.setAriaLabel();if(S||c||this.$focusScroll==\"browser\")return n.focus({preventScroll:!0});var e=n.style.top;n.style.position=\"fixed\",n.style.top=\"0px\";try{var t=n.getBoundingClientRect().top!=0}catch(r){return}var i=[];if(t){var s=n.parentElement;while(s&&s.nodeType==1)i.push(s),s.setAttribute(\"ace_nocontext\",!0),!s.parentElement&&s.getRootNode?s=s.getRootNode().host:s=s.parentElement}n.focus({preventScroll:!0}),t&&i.forEach(function(e){e.removeAttribute(\"ace_nocontext\")}),setTimeout(function(){n.style.position=\"\",n.style.top==\"0px\"&&(n.style.top=e)},0)},this.blur=function(){n.blur()},this.isFocused=function(){return A},t.on(\"beforeEndOperation\",function(){var e=t.curOp,r=e&&e.command&&e.command.name;if(r==\"insertstring\")return;var i=r&&(e.docChanged||e.selectionChanged);w&&i&&(N=n.value=\"\",V()),M()});var M=v?function(e){if(!A||y&&!e||E)return;e||(e=\"\");var r=\"\\n ab\"+e+\"cde fg\\n\";r!=n.value&&(n.value=N=r);var i=4,s=4+(e.length||(t.selection.isEmpty()?0:1));(C!=i||k!=s)&&n.setSelectionRange(i,s),C=i,k=s}:function(){if(w||E)return;if(!A&&!B)return;w=!0;var e=0,r=0,i=\"\";if(t.session){var s=t.selection,o=s.getRange(),u=s.cursor.row;e=o.start.column,r=o.end.column,i=t.session.getLine(u);if(o.start.row!=u){var a=t.session.getLine(u-1);e=o.start.row<u-1?0:e,r+=a.length+1,i=a+\"\\n\"+i}else if(o.end.row!=u){var f=t.session.getLine(u+1);r=o.end.row>u+1?f.length:r,r+=i.length+1,i=i+\"\\n\"+f}else g&&u>0&&(i=\"\\n\"+i,r+=1,e+=1);i.length>h&&(e<h&&r<h?i=i.slice(0,h):(i=\"\\n\",e==r?e=r=0:(e=0,r=1)))}var l=i+\"\\n\\n\";l!=N&&(n.value=N=l,C=k=l.length),B&&(C=n.selectionStart,k=n.selectionEnd);if(k!=r||C!=e||n.selectionEnd!=k)try{n.setSelectionRange(e,r),C=e,k=r}catch(c){}w=!1};this.resetSelection=M,A&&t.onFocus();var _=function(e){return e.selectionStart===0&&e.selectionEnd>=N.length&&e.value===N&&N&&e.selectionEnd!==k},D=function(e){if(w)return;y?y=!1:_(n)?(t.selectAll(),M()):g&&n.selectionStart!=C&&M()},H=null;this.setInputHandler=function(e){H=e},this.getInputHandler=function(){return H};var B=!1,j=function(e,r){B&&(B=!1);if(b)return M(),e&&t.onPaste(e),b=!1,\"\";var i=n.selectionStart,o=n.selectionEnd,u=C,a=N.length-k,f=e,l=e.length-i,c=e.length-o,h=0;while(u>0&&N[h]==e[h])h++,u--;f=f.slice(h),h=1;while(a>0&&N.length-h>C-1&&N[N.length-h]==e[e.length-h])h++,a--;l-=h-1,c-=h-1;var p=f.length-h+1;p<0&&(u=-p,p=0),f=f.slice(0,p);if(!r&&!f&&!l&&!u&&!a&&!c)return\"\";E=!0;var d=!1;return s.isAndroid&&f==\". \"&&(f=\"  \",d=!0),f&&!u&&!a&&!l&&!c||x?t.onTextInput(f):t.onTextInput(f,{extendLeft:u,extendRight:a,restoreStart:l,restoreEnd:c}),E=!1,N=e,C=i,k=o,L=c,d?\"\\n\":f},F=function(e){if(w)return X();if(e&&e.inputType){if(e.inputType==\"historyUndo\")return t.execCommand(\"undo\");if(e.inputType==\"historyRedo\")return t.execCommand(\"redo\")}var r=n.value,i=j(r,!0);(r.length>h+100||m.test(i)||g&&C<1&&C==k)&&M()},I=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||f)return;var i=l||n?\"Text\":\"text/plain\";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return I(e,t,!0)}},q=function(e,i){var s=t.getCopyText();if(!s)return r.preventDefault(e);I(e,s)?(v&&(M(s),y=s,setTimeout(function(){y=!1},10)),i?t.onCut():t.onCopy(),r.preventDefault(e)):(y=!0,n.value=s,n.select(),setTimeout(function(){y=!1,M(),i?t.onCut():t.onCopy()}))},R=function(e){q(e,!0)},U=function(e){q(e,!1)},z=function(e){var i=I(e);if(a.pasteCancelled())return;typeof i==\"string\"?(i&&t.onPaste(i,e),s.isIE&&setTimeout(M),r.preventDefault(e)):(n.value=\"\",b=!0)};r.addCommandKeyListener(n,t.onCommandKey.bind(t),t),r.addListener(n,\"select\",D,t),r.addListener(n,\"input\",F,t),r.addListener(n,\"cut\",R,t),r.addListener(n,\"copy\",U,t),r.addListener(n,\"paste\",z,t),(!(\"oncut\"in n)||!(\"oncopy\"in n)||!(\"onpaste\"in n))&&r.addListener(e,\"keydown\",function(e){if(s.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:U(e);break;case 86:z(e);break;case 88:R(e)}},t);var W=function(e){if(w||!t.onCompositionStart||t.$readOnly)return;w={};if(x)return;e.data&&(w.useTextareaForIME=!1),setTimeout(X,0),t._signal(\"compositionStart\"),t.on(\"mousedown\",$);var r=t.getSelectionRange();r.end.row=r.start.row,r.end.column=r.start.column,w.markerRange=r,w.selectionStart=C,t.onCompositionStart(w),w.useTextareaForIME?(N=n.value=\"\",C=0,k=0):(n.msGetInputContext&&(w.context=n.msGetInputContext()),n.getInputContext&&(w.context=n.getInputContext()))},X=function(){if(!w||!t.onCompositionUpdate||t.$readOnly)return;if(x)return $();if(w.useTextareaForIME)t.onCompositionUpdate(n.value);else{var e=n.value;j(e),w.markerRange&&(w.context&&(w.markerRange.start.column=w.selectionStart=w.context.compositionStartOffset),w.markerRange.end.column=w.markerRange.start.column+k-w.selectionStart+L)}},V=function(e){if(!t.onCompositionEnd||t.$readOnly)return;w=!1,t.onCompositionEnd(),t.off(\"mousedown\",$),e&&F()},J=u.delayedCall(X,50).schedule.bind(null,null);r.addListener(n,\"compositionstart\",W,t),r.addListener(n,\"compositionupdate\",X,t),r.addListener(n,\"keyup\",K,t),r.addListener(n,\"keydown\",J,t),r.addListener(n,\"compositionend\",V,t),this.getElement=function(){return n},this.setCommandMode=function(e){x=e,n.readOnly=!1},this.setReadOnly=function(e){x||(n.readOnly=e)},this.setCopyWithEmptySelection=function(e){},this.onContextMenu=function(e){B=!0,M(),t._emit(\"nativecontextmenu\",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,i){S||(S=n.style.cssText),n.style.cssText=(i?\"z-index:100000;\":\"\")+(s.isIE?\"opacity:0.1;\":\"\")+\"text-indent: -\"+(C+k)*t.renderer.characterWidth*.5+\"px;\";var u=t.container.getBoundingClientRect(),a=o.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){o.translate(n,e.clientX-l-2,Math.min(e.clientY-f-2,c))};h(e);if(e.type!=\"mousedown\")return;t.renderer.$isMousePressed=!0,clearTimeout(Q),s.isWin&&r.capture(t.container,h,G)},this.onContextMenuClose=G;var Q,Y=function(e){t.textInput.onContextMenu(e),G()};r.addListener(n,\"mouseup\",Y,t),r.addListener(n,\"mousedown\",function(e){e.preventDefault(),G()},t),r.addListener(t.renderer.scroller,\"contextmenu\",Y,t),r.addListener(n,\"contextmenu\",Y,t),v&&Z(e,t,n),this.destroy=function(){n.parentElement&&n.parentElement.removeChild(n)}};t.TextInput=y,t.$setUserAgentForTests=function(e,t){g=e,v=t}}),define(\"ace/mouse/default_handlers\",[\"require\",\"exports\",\"module\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function u(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function a(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e(\"../lib/useragent\"),i=0,s=550,o=function(){function e(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler(\"mousedown\",this.onMouseDown.bind(e)),t.setDefaultHandler(\"dblclick\",this.onDoubleClick.bind(e)),t.setDefaultHandler(\"tripleclick\",this.onTripleClick.bind(e)),t.setDefaultHandler(\"quadclick\",this.onQuadClick.bind(e)),t.setDefaultHandler(\"mousewheel\",this.onMouseWheel.bind(e));var n=[\"select\",\"startSelect\",\"selectEnd\",\"selectAllEnd\",\"selectByWordsEnd\",\"selectByLinesEnd\",\"dragWait\",\"dragWaitEnd\",\"focusWait\"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,\"getLineRange\"),e.selectByWords=this.extendSelectionBy.bind(e,\"getWordRange\")}return e.prototype.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var i=this.editor,s=e.getButton();if(s!==0){var o=i.getSelectionRange(),u=o.isEmpty();(u||s==1)&&i.selection.moveToPosition(n),s==2&&(i.textInput.onContextMenu(e.domEvent),r.isMozilla||e.preventDefault());return}this.mousedownEvent.time=Date.now();if(t&&!i.isFocused()){i.focus();if(this.$focusTimeout&&!this.$clickSelection&&!i.inMultiSelectMode){this.setState(\"focusWait\"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},e.prototype.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;if(!this.mousedownEvent)return;this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.setStyle(\"ace_selecting\"),this.setState(\"select\")},e.prototype.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=a(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.renderer.scrollCursorIntoView()},e.prototype.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=a(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.renderer.scrollCursorIntoView()},e.prototype.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle(\"ace_selecting\")},e.prototype.focusWait=function(){var e=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>i||t-this.mousedownEvent.time>this.$focusTimeout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},e.prototype.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState(\"select\")):(i=n.selection.getWordRange(t.row,t.column),this.setState(\"selectByWords\")),this.$clickSelection=i,this.select()},e.prototype.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState(\"selectByLines\");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},e.prototype.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState(\"selectAll\")},e.prototype.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=this.editor;this.$lastScroll||(this.$lastScroll={t:0,vx:0,vy:0,allowed:0});var n=this.$lastScroll,r=e.domEvent.timeStamp,i=r-n.t,o=i?e.wheelX/i:n.vx,u=i?e.wheelY/i:n.vy;i<s&&(o=(o+n.vx)/2,u=(u+n.vy)/2);var a=Math.abs(o/u),f=!1;a>=1&&t.renderer.isScrollableBy(e.wheelX*e.speed,0)&&(f=!0),a<=1&&t.renderer.isScrollableBy(0,e.wheelY*e.speed)&&(f=!0);if(f)n.allowed=r;else if(r-n.allowed<s){var l=Math.abs(o)<=1.5*Math.abs(n.vx)&&Math.abs(u)<=1.5*Math.abs(n.vy);l?(f=!0,n.allowed=r):n.allowed=0}n.t=r,n.vx=o,n.vy=u;if(f)return t.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()},e}();o.prototype.selectEnd=o.prototype.selectByLinesEnd,o.prototype.selectAllEnd=o.prototype.selectByLinesEnd,o.prototype.selectByWordsEnd=o.prototype.selectByLinesEnd,t.DefaultHandlers=o}),define(\"ace/tooltip\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/range\"],function(e,t,n){\"use strict\";var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=this&&this.__values||function(e){var t=typeof Symbol==\"function\"&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&typeof e.length==\"number\")return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")},s=e(\"./lib/dom\"),o=e(\"./range\").Range,u=\"ace_tooltip\",a=function(){function e(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}return e.prototype.$init=function(){return this.$element=s.createElement(\"div\"),this.$element.className=u,this.$element.style.display=\"none\",this.$parentNode.appendChild(this.$element),this.$element},e.prototype.getElement=function(){return this.$element||this.$init()},e.prototype.setText=function(e){this.getElement().textContent=e},e.prototype.setHtml=function(e){this.getElement().innerHTML=e},e.prototype.setPosition=function(e,t){this.getElement().style.left=e+\"px\",this.getElement().style.top=t+\"px\"},e.prototype.setClassName=function(e){s.addCssClass(this.getElement(),e)},e.prototype.setTheme=function(e){this.$element.className=u+\" \"+(e.isDark?\"ace_dark \":\"\")+(e.cssClass||\"\")},e.prototype.show=function(e,t,n){e!=null&&this.setText(e),t!=null&&n!=null&&this.setPosition(t,n),this.isOpen||(this.getElement().style.display=\"block\",this.isOpen=!0)},e.prototype.hide=function(){this.isOpen&&(this.getElement().style.display=\"none\",this.getElement().className=u,this.isOpen=!1)},e.prototype.getHeight=function(){return this.getElement().offsetHeight},e.prototype.getWidth=function(){return this.getElement().offsetWidth},e.prototype.destroy=function(){this.isOpen=!1,this.$element&&this.$element.parentNode&&this.$element.parentNode.removeChild(this.$element)},e}(),f=function(){function e(){this.popups=[]}return e.prototype.addPopup=function(e){this.popups.push(e),this.updatePopups()},e.prototype.removePopup=function(e){var t=this.popups.indexOf(e);t!==-1&&(this.popups.splice(t,1),this.updatePopups())},e.prototype.updatePopups=function(){var e,t,n,r;this.popups.sort(function(e,t){return t.priority-e.priority});var s=[];try{for(var o=i(this.popups),u=o.next();!u.done;u=o.next()){var a=u.value,f=!0;try{for(var l=(n=void 0,i(s)),c=l.next();!c.done;c=l.next()){var h=c.value;if(this.doPopupsOverlap(h,a)){f=!1;break}}}catch(p){n={error:p}}finally{try{c&&!c.done&&(r=l.return)&&r.call(l)}finally{if(n)throw n.error}}f?s.push(a):a.hide()}}catch(d){e={error:d}}finally{try{u&&!u.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}},e.prototype.doPopupsOverlap=function(e,t){var n=e.getElement().getBoundingClientRect(),r=t.getElement().getBoundingClientRect();return n.left<r.right&&n.right>r.left&&n.top<r.bottom&&n.bottom>r.top},e}(),l=new f;t.popupManager=l,t.Tooltip=a;var c=function(e){function t(t){t===void 0&&(t=document.body);var n=e.call(this,t)||this;n.timeout=undefined,n.lastT=0,n.idleTime=350,n.lastEvent=undefined,n.onMouseOut=n.onMouseOut.bind(n),n.onMouseMove=n.onMouseMove.bind(n),n.waitForHover=n.waitForHover.bind(n),n.hide=n.hide.bind(n);var r=n.getElement();return r.style.whiteSpace=\"pre-wrap\",r.style.pointerEvents=\"auto\",r.addEventListener(\"mouseout\",n.onMouseOut),r.tabIndex=-1,r.addEventListener(\"blur\",function(){r.contains(document.activeElement)||this.hide()}.bind(n)),n}return r(t,e),t.prototype.addToEditor=function(e){e.on(\"mousemove\",this.onMouseMove),e.on(\"mousedown\",this.hide),e.renderer.getMouseEventTarget().addEventListener(\"mouseout\",this.onMouseOut,!0)},t.prototype.removeFromEditor=function(e){e.off(\"mousemove\",this.onMouseMove),e.off(\"mousedown\",this.hide),e.renderer.getMouseEventTarget().removeEventListener(\"mouseout\",this.onMouseOut,!0),this.timeout&&(clearTimeout(this.timeout),this.timeout=null)},t.prototype.onMouseMove=function(e,t){this.lastEvent=e,this.lastT=Date.now();var n=t.$mouseHandler.isMousePressed;if(this.isOpen){var r=this.lastEvent&&this.lastEvent.getDocumentPosition();(!this.range||!this.range.contains(r.row,r.column)||n||this.isOutsideOfText(this.lastEvent))&&this.hide()}if(this.timeout||n)return;this.lastEvent=e,this.timeout=setTimeout(this.waitForHover,this.idleTime)},t.prototype.waitForHover=function(){this.timeout&&clearTimeout(this.timeout);var e=Date.now()-this.lastT;if(this.idleTime-e>10){this.timeout=setTimeout(this.waitForHover,this.idleTime-e);return}this.timeout=null,this.lastEvent&&!this.isOutsideOfText(this.lastEvent)&&this.$gatherData(this.lastEvent,this.lastEvent.editor)},t.prototype.isOutsideOfText=function(e){var t=e.editor,n=e.getDocumentPosition(),r=t.session.getLine(n.row);if(n.column==r.length){var i=t.renderer.pixelToScreenCoordinates(e.clientX,e.clientY),s=t.session.documentToScreenPosition(n.row,n.column);if(s.column!=i.column||s.row!=i.row)return!0}return!1},t.prototype.setDataProvider=function(e){this.$gatherData=e},t.prototype.showForRange=function(e,t,n,r){if(r&&r!=this.lastEvent)return;if(this.isOpen&&document.activeElement==this.getElement())return;var i=e.renderer;this.isOpen||(l.addPopup(this),this.$registerCloseEvents(),this.setTheme(i.theme)),this.isOpen=!0,this.addMarker(t,e.session),this.range=o.fromPoints(t.start,t.end);var s=this.getElement();s.innerHTML=\"\",s.appendChild(n),s.style.display=\"block\";var u=i.textToScreenCoordinates(t.start.row,t.start.column),a=e.getCursorPosition(),f=s.clientHeight,c=i.scroller.getBoundingClientRect(),h=!0;this.row>a.row?h=!0:this.row<a.row&&(h=!1),u.pageY-f+i.lineHeight<c.top?h=!0:u.pageY+f>c.bottom&&(h=!1),h?u.pageY+=i.lineHeight:u.pageY-=f,s.style.maxWidth=c.width-(u.pageX-c.left)+\"px\",this.setPosition(u.pageX,u.pageY)},t.prototype.addMarker=function(e,t){this.marker&&this.$markerSession.removeMarker(this.marker),this.$markerSession=t,this.marker=t&&t.addMarker(e,\"ace_highlight-marker\",\"text\")},t.prototype.hide=function(e){if(!e&&document.activeElement==this.getElement())return;if(e&&e.target&&(e.type!=\"keydown\"||e.ctrlKey||e.metaKey)&&this.$element.contains(e.target))return;this.lastEvent=null,this.timeout&&clearTimeout(this.timeout),this.timeout=null,this.addMarker(null),this.isOpen&&(this.$removeCloseEvents(),this.getElement().style.display=\"none\",this.isOpen=!1,l.removePopup(this))},t.prototype.$registerCloseEvents=function(){window.addEventListener(\"keydown\",this.hide,!0),window.addEventListener(\"mousewheel\",this.hide,!0),window.addEventListener(\"mousedown\",this.hide,!0)},t.prototype.$removeCloseEvents=function(){window.removeEventListener(\"keydown\",this.hide,!0),window.removeEventListener(\"mousewheel\",this.hide,!0),window.removeEventListener(\"mousedown\",this.hide,!0)},t.prototype.onMouseOut=function(e){this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.lastEvent=null;if(!this.isOpen)return;if(!e.relatedTarget||e.relatedTarget==this.getElement())return;if(e&&e.currentTarget.contains(e.relatedTarget))return;e.relatedTarget.classList.contains(\"ace_content\")||this.hide()},t}(a);t.HoverTooltip=c}),define(\"ace/mouse/default_gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/tooltip\",\"ace/config\"],function(e,t,n){\"use strict\";function f(e){function a(){var i=u.getDocumentPosition().row,s=t.session.getLength();if(i==s){var o=t.renderer.pixelToScreenCoordinates(0,u.y).row,a=u.$pos;if(o>t.session.documentToScreenRow(a.row,a.column))return f()}r.showTooltip(i);if(!r.isOpen)return;t.on(\"mousewheel\",f);if(e.$tooltipFollowsMouse)c(u);else{var l=n.$lines.cells[i].element.querySelector(\"[class*=ace_icon]\"),h=l.getBoundingClientRect(),p=r.getElement().style;p.left=h.right+\"px\",p.top=h.bottom+\"px\"}}function f(){i&&(i=clearTimeout(i)),r.isOpen&&(r.hide(),t._signal(\"hideGutterTooltip\",r),t.off(\"mousewheel\",f))}function c(e){r.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,r=new l(t);e.editor.setDefaultHandler(\"guttermousedown\",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i==\"foldWidgets\")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState(\"selectByLines\"),e.captureMouse(r),r.preventDefault()});var i,u;e.editor.setDefaultHandler(\"guttermousemove\",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(s.hasCssClass(n,\"ace_fold-widget\"))return f();r.isOpen&&e.$tooltipFollowsMouse&&c(t),u=t;if(i)return;i=setTimeout(function(){i=null,u&&!e.isMousePressed?a():f()},50)}),o.addListener(t.renderer.$gutter,\"mouseout\",function(e){u=null;if(!r.isOpen||i)return;i=setTimeout(function(){i=null,f()},50)},t),t.on(\"changeSession\",f),t.on(\"input\",f)}var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=this&&this.__values||function(e){var t=typeof Symbol==\"function\"&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&typeof e.length==\"number\")return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")},s=e(\"../lib/dom\"),o=e(\"../lib/event\"),u=e(\"../tooltip\").Tooltip,a=e(\"../config\").nls;t.GutterHandler=f;var l=function(e){function t(t){var n=e.call(this,t.container)||this;return n.editor=t,n}return r(t,e),t.prototype.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),u.prototype.setPosition.call(this,e,t)},Object.defineProperty(t,\"annotationLabels\",{get:function(){return{error:{singular:a(\"error\"),plural:a(\"errors\")},warning:{singular:a(\"warning\"),plural:a(\"warnings\")},info:{singular:a(\"information message\"),plural:a(\"information messages\")}}},enumerable:!1,configurable:!0}),t.prototype.showTooltip=function(e){var n=this.editor.renderer.$gutterLayer,r=n.$annotations[e],i;r?i={text:Array.from(r.text),type:Array.from(r.type)}:i={text:[],type:[]};var s=n.session.getFoldLine(e);if(s&&n.$showFoldedAnnotations){var o={error:[],warning:[],info:[]},u;for(var a=e+1;a<=s.end.row;a++){if(!n.$annotations[a])continue;for(var f=0;f<n.$annotations[a].text.length;f++){var l=n.$annotations[a].type[f];o[l].push(n.$annotations[a].text[f]);if(l===\"error\"){u=\"error_fold\";continue}if(l===\"warning\"){u=\"warning_fold\";continue}}}if(u===\"error_fold\"||u===\"warning_fold\"){var c=\"\".concat(t.annotationsToSummaryString(o),\" in folded code.\");i.text.push(c),i.type.push(u)}}if(i.text.length===0)return this.hide();var h={error:[],warning:[],info:[]},p=n.$useSvgGutterIcons?\"ace_icon_svg\":\"ace_icon\";for(var a=0;a<i.text.length;a++){var d=\"<span class='ace_\".concat(i.type[a],\" \").concat(p,\"' aria-label='\").concat(t.annotationLabels[i.type[a].replace(\"_fold\",\"\")].singular,\"' role=img> </span> \").concat(i.text[a]);h[i.type[a].replace(\"_fold\",\"\")].push(d)}var v=[].concat(h.error,h.warning,h.info).join(\"<br>\");this.setHtml(v),this.setClassName(\"ace_gutter-tooltip\"),this.$element.setAttribute(\"aria-live\",\"polite\"),this.isOpen||this.setTheme(this.editor.renderer.theme),this.editor._signal(\"showGutterTooltip\",this),this.show()},t.annotationsToSummaryString=function(e){var n,r,s=[],o=[\"error\",\"warning\",\"info\"];try{for(var u=i(o),a=u.next();!a.done;a=u.next()){var f=a.value;if(!e[f].length)continue;var l=e[f].length===1?t.annotationLabels[f].singular:t.annotationLabels[f].plural;s.push(\"\".concat(e[f].length,\" \").concat(l))}}catch(c){n={error:c}}finally{try{a&&!a.done&&(r=u.return)&&r.call(u)}finally{if(n)throw n.error}}return s.join(\", \")},t}(u);t.GutterTooltip=l}),define(\"ace/mouse/mouse_event\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=function(){function e(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1}return e.prototype.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},e.prototype.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},e.prototype.stop=function(){this.stopPropagation(),this.preventDefault()},e.prototype.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},e.prototype.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},e.prototype.getButton=function(){return r.getButton(this.domEvent)},e.prototype.getShiftKey=function(){return this.domEvent.shiftKey},e.prototype.getAccelKey=function(){return i.isMac?this.domEvent.metaKey:this.domEvent.ctrlKey},e}();t.MouseEvent=s}),define(\"ace/mouse/dragdrop_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.moveCursorToPosition(e),S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left<a.x.right?-3:2),l/i<=1&&(c.row+=a.y.top<a.y.bottom?-1:1);var h=e.row!=c.row,v=e.column!=c.column,m=!n||e.row!=n.row;h||v&&!m?E?r-E>=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,\"ace_selection\",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,\"mousemove\",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.selection.fromOrientedRange(m),t.isFocused()&&!w&&t.$resetCursorStyle(),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,\"mousemove\",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e==\"text/plain\"||e==\"Text\"})}function _(e){var t=[\"copy\",\"copymove\",\"all\",\"uninitialized\"],n=[\"move\",\"copymove\",\"linkmove\",\"all\",\"uninitialized\"],r=s.isMac?e.altKey:e.ctrlKey,i=\"uninitialized\";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o=\"none\";return r&&t.indexOf(i)>=0?o=\"copy\":n.indexOf(i)>=0?o=\"move\":t.indexOf(i)>=0&&(o=\"copy\"),o}var t=e.editor,n=r.createElement(\"div\");n.style.cssText=\"top:-100px;position:absolute;z-index:2147483647;opacity:0.5\",n.textContent=\"\\u00a0\";var f=[\"dragWait\",\"dragWaitEnd\",\"startDrag\",\"dragReadyEnd\",\"onMouseDrag\"];f.forEach(function(t){e[t]=this[t]},this),t.on(\"mousedown\",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?\"copy\":\"copyMove\",t.container.appendChild(n),i.setDragImage&&i.setDragImage(n,0,0),setTimeout(function(){t.container.removeChild(n)}),i.clearData(),i.setData(\"Text\",t.session.getTextRange()),w=!0,this.setState(\"drag\")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n==\"move\"&&t.session.remove(t.getSelectionRange()),t.$resetCursorStyle()}this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case\"move\":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case\"copy\":m=t.moveText(m,g,!0)}else{var r=n.getData(\"Text\");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,\"dragstart\",this.onDragStart.bind(e),t),i.addListener(c,\"dragend\",this.onDragEnd.bind(e),t),i.addListener(c,\"dragenter\",this.onDragEnter.bind(e),t),i.addListener(c,\"dragover\",this.onDragOver.bind(e),t),i.addListener(c,\"dragleave\",this.onDragLeave.bind(e),t),i.addListener(c,\"drop\",this.onDrop.bind(e),t);var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e(\"../lib/dom\"),i=e(\"../lib/event\"),s=e(\"../lib/useragent\"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.$resetCursorStyle(),this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\"),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle(\"ace_dragging\");var n=s.isWin?\"default\":\"move\";e.renderer.setCursorStyle(n),this.setState(\"dragReady\")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state==\"dragReady\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state===\"dragWait\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;\"unselectable\"in o&&(o.unselectable=\"on\");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState(\"dragWait\")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define(\"ace/mouse/touch_handler\",[\"require\",\"exports\",\"module\",\"ace/mouse/mouse_event\",\"ace/lib/event\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"./mouse_event\").MouseEvent,i=e(\"../lib/event\"),s=e(\"../lib/dom\");t.addTouchListeners=function(e,t){function b(){var e=window.navigator&&window.navigator.clipboard,r=!1,i=function(){var n=t.getCopyText(),i=t.session.getUndoManager().hasUndo();y.replaceChild(s.buildDom(r?[\"span\",!n&&[\"span\",{\"class\":\"ace_mobile-button\",action:\"selectall\"},\"Select All\"],n&&[\"span\",{\"class\":\"ace_mobile-button\",action:\"copy\"},\"Copy\"],n&&[\"span\",{\"class\":\"ace_mobile-button\",action:\"cut\"},\"Cut\"],e&&[\"span\",{\"class\":\"ace_mobile-button\",action:\"paste\"},\"Paste\"],i&&[\"span\",{\"class\":\"ace_mobile-button\",action:\"undo\"},\"Undo\"],[\"span\",{\"class\":\"ace_mobile-button\",action:\"find\"},\"Find\"],[\"span\",{\"class\":\"ace_mobile-button\",action:\"openCommandPallete\"},\"Palette\"]]:[\"span\"]),y.firstChild)},o=function(n){var s=n.target.getAttribute(\"action\");if(s==\"more\"||!r)return r=!r,i();if(s==\"paste\")e.readText().then(function(e){t.execCommand(s,e)});else if(s){if(s==\"cut\"||s==\"copy\")e?e.writeText(t.getCopyText()):document.execCommand(\"copy\");t.execCommand(s)}y.firstChild.style.display=\"none\",r=!1,s!=\"openCommandPallete\"&&t.focus()};y=s.buildDom([\"div\",{\"class\":\"ace_mobile-menu\",ontouchstart:function(e){n=\"menu\",e.stopPropagation(),e.preventDefault(),t.textInput.focus()},ontouchend:function(e){e.stopPropagation(),e.preventDefault(),o(e)},onclick:o},[\"span\"],[\"span\",{\"class\":\"ace_mobile-button\",action:\"more\"},\"...\"]],t.container)}function w(){y||b();var e=t.selection.cursor,n=t.renderer.textToScreenCoordinates(e.row,e.column),r=t.renderer.textToScreenCoordinates(0,0).pageX,i=t.renderer.scrollLeft,s=t.container.getBoundingClientRect();y.style.top=n.pageY-s.top-3+\"px\",n.pageX-s.left<s.width-70?(y.style.left=\"\",y.style.right=\"10px\"):(y.style.right=\"\",y.style.left=r+i-s.left+\"px\"),y.style.display=\"\",y.firstChild.style.display=\"none\",t.on(\"input\",E)}function E(e){y&&(y.style.display=\"none\"),t.off(\"input\",E)}function S(){l=null,clearTimeout(l);var e=t.selection.getRange(),r=e.contains(p.row,p.column);if(e.isEmpty()||!r)t.selection.moveToPosition(p),t.selection.selectWord();n=\"wait\",w()}function x(){l=null,clearTimeout(l),t.selection.moveToPosition(p);var e=d>=2?t.selection.getLineRange(p.row):t.session.getBracketRange(p);e&&!e.isEmpty()?t.selection.setRange(e):t.selection.selectWord(),n=\"wait\"}function T(){h+=60,c=setInterval(function(){h--<=0&&(clearInterval(c),c=null),Math.abs(v)<.01&&(v=0),Math.abs(m)<.01&&(m=0),h<20&&(v=.9*v),h<20&&(m=.9*m);var e=t.session.getScrollTop();t.renderer.scrollBy(10*v,10*m),e==t.session.getScrollTop()&&(h=0)},10)}var n=\"scroll\",o,u,a,f,l,c,h=0,p,d=0,v=0,m=0,g,y;i.addListener(e,\"contextmenu\",function(e){if(!g)return;var n=t.textInput.getElement();n.focus()},t),i.addListener(e,\"touchstart\",function(e){var i=e.touches;if(l||i.length>1){clearTimeout(l),l=null,a=-1,n=\"zoom\";return}g=t.$mouseHandler.isMousePressed=!0;var s=t.renderer.layerConfig.lineHeight,c=t.renderer.layerConfig.lineHeight,y=e.timeStamp;f=y;var b=i[0],w=b.clientX,E=b.clientY;Math.abs(o-w)+Math.abs(u-E)>s&&(a=-1),o=e.clientX=w,u=e.clientY=E,v=m=0;var T=new r(e,t);p=T.getDocumentPosition();if(y-a<500&&i.length==1&&!h)d++,e.preventDefault(),e.button=0,x();else{d=0;var N=t.selection.cursor,C=t.selection.isEmpty()?N:t.selection.anchor,k=t.renderer.$cursorLayer.getPixelPosition(N,!0),L=t.renderer.$cursorLayer.getPixelPosition(C,!0),A=t.renderer.scroller.getBoundingClientRect(),O=t.renderer.layerConfig.offset,M=t.renderer.scrollLeft,_=function(e,t){return e/=c,t=t/s-.75,e*e+t*t};if(e.clientX<A.left){n=\"zoom\";return}var D=_(e.clientX-A.left-k.left+M,e.clientY-A.top-k.top+O),P=_(e.clientX-A.left-L.left+M,e.clientY-A.top-L.top+O);D<3.5&&P<3.5&&(n=D>P?\"cursor\":\"anchor\"),P<3.5?n=\"anchor\":D<3.5?n=\"cursor\":n=\"scroll\",l=setTimeout(S,450)}a=y},t),i.addListener(e,\"touchend\",function(e){g=t.$mouseHandler.isMousePressed=!1,c&&clearInterval(c),n==\"zoom\"?(n=\"\",h=0):l?(t.selection.moveToPosition(p),h=0,w()):n==\"scroll\"?(T(),E()):w(),clearTimeout(l),l=null},t),i.addListener(e,\"touchmove\",function(e){l&&(clearTimeout(l),l=null);var i=e.touches;if(i.length>1||n==\"zoom\")return;var s=i[0],a=o-s.clientX,c=u-s.clientY;if(n==\"wait\"){if(!(a*a+c*c>4))return e.preventDefault();n=\"cursor\"}o=s.clientX,u=s.clientY,e.clientX=s.clientX,e.clientY=s.clientY;var h=e.timeStamp,p=h-f;f=h;if(n==\"scroll\"){var d=new r(e,t);d.speed=1,d.wheelX=a,d.wheelY=c,10*Math.abs(a)<Math.abs(c)&&(a=0),10*Math.abs(c)<Math.abs(a)&&(c=0),p!=0&&(v=a/p,m=c/p),t._emit(\"mousewheel\",d),d.propagationStopped||(v=m=0)}else{var g=new r(e,t),y=g.getDocumentPosition();n==\"cursor\"?t.selection.moveCursorToPosition(y):n==\"anchor\"&&t.selection.setSelectionAnchor(y.row,y.column),t.renderer.scrollCursorIntoView(y),e.preventDefault()}},t)}}),define(\"ace/mouse/mouse_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/mouse/default_handlers\",\"ace/mouse/default_gutter_handler\",\"ace/mouse/mouse_event\",\"ace/mouse/dragdrop_handler\",\"ace/mouse/touch_handler\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"./default_handlers\").DefaultHandlers,o=e(\"./default_gutter_handler\").GutterHandler,u=e(\"./mouse_event\").MouseEvent,a=e(\"./dragdrop_handler\").DragdropHandler,f=e(\"./touch_handler\").addTouchListeners,l=e(\"../config\"),c=function(){function e(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus(),setTimeout(function(){e.isFocused()||e.focus()})},u=e.renderer.getMouseEventTarget();r.addListener(u,\"click\",this.onMouseEvent.bind(this,\"click\"),e),r.addListener(u,\"mousemove\",this.onMouseMove.bind(this,\"mousemove\"),e),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,\"onMouseEvent\",e),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,\"mousewheel\"),e),f(e.container,e);var l=e.renderer.$gutter;r.addListener(l,\"mousedown\",this.onMouseEvent.bind(this,\"guttermousedown\"),e),r.addListener(l,\"click\",this.onMouseEvent.bind(this,\"gutterclick\"),e),r.addListener(l,\"dblclick\",this.onMouseEvent.bind(this,\"gutterdblclick\"),e),r.addListener(l,\"mousemove\",this.onMouseEvent.bind(this,\"guttermousemove\"),e),r.addListener(u,\"mousedown\",n,e),r.addListener(l,\"mousedown\",n,e),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,\"mousedown\",n,e),r.addListener(e.renderer.scrollBarH.element,\"mousedown\",n,e)),e.on(\"mousemove\",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle(\"default\"):s.setCursorStyle(\"\")},e)}return e.prototype.onMouseEvent=function(e,t){if(!this.editor.session)return;this.editor._emit(e,new u(t,this.editor))},e.prototype.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},e.prototype.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},e.prototype.setState=function(e){this.state=e},e.prototype.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor,s=this.editor.renderer;s.$isMousePressed=!0;var o=this,a=function(e){if(!e)return;if(i.isWebKit&&!e.which&&o.releaseMouse)return o.releaseMouse();o.x=e.clientX,o.y=e.clientY,t&&t(e),o.mouseEvent=new u(e,o.editor),o.$mouseMoved=!0},f=function(e){n.off(\"beforeEndOperation\",c),clearInterval(h),n.session&&l(),o[o.state+\"End\"]&&o[o.state+\"End\"](e),o.state=\"\",o.isMousePressed=s.$isMousePressed=!1,s.$keepTextAreaAtCursor&&s.$moveTextAreaToCursor(),o.$onCaptureMouseMove=o.releaseMouse=null,e&&o.onMouseEvent(\"mouseup\",e),n.endOperation()},l=function(){o[o.state]&&o[o.state](),o.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type==\"dblclick\")return setTimeout(function(){f(e)});var c=function(e){if(!o.releaseMouse)return;n.curOp.command.name&&n.curOp.selectionChanged&&(o[o.state+\"End\"]&&o[o.state+\"End\"](),o.state=\"\",o.releaseMouse())};n.on(\"beforeEndOperation\",c),n.startOperation({command:{name:\"mouse\"}}),o.$onCaptureMouseMove=a,o.releaseMouse=r.capture(this.editor.container,a,f);var h=setInterval(l,20)},e.prototype.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!=\"contextmenu\")return;this.editor.off(\"nativecontextmenu\",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on(\"nativecontextmenu\",e)},e.prototype.destroy=function(){this.releaseMouse&&this.releaseMouse()},e}();c.prototype.releaseMouse=null,l.defineOptions(c.prototype,\"mouseHandler\",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimeout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=c}),define(\"ace/mouse/fold_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=function(){function e(e){e.on(\"click\",function(t){var n=t.getDocumentPosition(),i=e.session,s=i.getFoldAt(n.row,n.column,1);s&&(t.getAccelKey()?i.removeFold(s):i.expandFold(s),t.stop());var o=t.domEvent&&t.domEvent.target;o&&r.hasCssClass(o,\"ace_inline_button\")&&r.hasCssClass(o,\"ace_toggle_wrap\")&&(i.setOption(\"wrap\",!i.getUseWrapMode()),e.renderer.scrollCursorIntoView())}),e.on(\"gutterclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on(\"gutterdblclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold(\"...\",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}return e}();t.FoldHandler=i}),define(\"ace/keyboard/keybinding\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"../lib/keys\"),i=e(\"../lib/event\"),s=function(){function e(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)}return e.prototype.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},e.prototype.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},e.prototype.addKeyboardHandler=function(e,t){if(!e)return;typeof e==\"function\"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},e.prototype.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},e.prototype.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},e.prototype.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||\"\"}).filter(Boolean).join(\" \")},e.prototype.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command==\"null\"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:\"insertstring\"},o=u.exec(\"insertstring\",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal(\"keyboardActivity\",s),o},e.prototype.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);return this.$callKeyboardHandlers(t,i,n,e)},e.prototype.onTextInput=function(e){return this.$callKeyboardHandlers(-1,e)},e}();t.KeyBinding=s}),define(\"ace/lib/bidiutil\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function F(e,t,n,r){var i=s?d:p,c=null,h=null,v=null,m=0,g=null,y=null,b=-1,w=null,E=null,T=[];if(!r)for(w=0,r=[];w<n;w++)r[w]=R(e[w]);o=s,u=!1,a=!1,f=!1,l=!1;for(E=0;E<n;E++){c=m,T[E]=h=q(e,r,T,E),m=i[c][h],g=m&240,m&=15,t[E]=v=i[m][5];if(g>0)if(g==16){for(w=b;w<E;w++)t[w]=1;b=-1}else b=-1;y=i[m][6];if(y)b==-1&&(b=E);else if(b>-1){for(w=b;w<E;w++)t[w]=v;b=-1}r[E]==S&&(t[E]=0),o|=v}if(l)for(w=0;w<n;w++)if(r[w]==x){t[w]=s;for(var C=w-1;C>=0;C--){if(r[C]!=N)break;t[C]=s}}}function I(e,t,n){if(o<e)return;if(e==1&&s==m&&!f){n.reverse();return}var r=n.length,i=0,u,a,l,c;while(i<r){if(t[i]>=e){u=i+1;while(u<r&&t[u]>=e)u++;for(a=i,l=u-1;a<l;a++,l--)c=n[a],n[a]=n[l],n[l]=c;i=u}i++}}function q(e,t,n,r){var i=t[r],o,c,h,p;switch(i){case g:case y:u=!1;case E:case w:return i;case b:return u?w:b;case T:return u=!0,a=!0,y;case N:return E;case C:if(r<1||r+1>=t.length||(o=n[r-1])!=b&&o!=w||(c=t[r+1])!=b&&c!=w)return E;return u&&(c=w),c==o?c:E;case k:o=r>0?n[r-1]:S;if(o==b&&r+1<t.length&&t[r+1]==b)return b;return E;case L:if(r>0&&n[r-1]==b)return b;if(u)return E;p=r+1,h=t.length;while(p<h&&t[p]==L)p++;if(p<h&&t[p]==b)return b;return E;case A:h=t.length,p=r+1;while(p<h&&t[p]==A)p++;if(p<h){var d=e[r],v=d>=1425&&d<=2303||d==64286;o=t[p];if(v&&(o==y||o==T))return y}if(r<1||(o=t[r-1])==S)return E;return n[r-1];case S:return u=!1,f=!0,s;case x:return l=!0,E;case O:case M:case D:case P:case _:u=!1;case H:return E}}function R(e){var t=e.charCodeAt(0),n=t>>8;return n==0?t>191?g:B[t]:n==5?/[\\u0591-\\u05f4]/.test(e)?y:g:n==6?/[\\u0610-\\u061a\\u064b-\\u065f\\u06d6-\\u06e4\\u06e7-\\u06ed]/.test(e)?A:/[\\u0660-\\u0669\\u066b-\\u066c]/.test(e)?w:t==1642?L:/[\\u06f0-\\u06f9]/.test(e)?b:T:n==32&&t<=8287?j[t&255]:n==254?t>=65136?T:E:E}function U(e){return e>=\"\\u064b\"&&e<=\"\\u0655\"}var r=[\"\\u0621\",\"\\u0641\"],i=[\"\\u063a\",\"\\u064a\"],s=0,o=0,u=!1,a=!1,f=!1,l=!1,c=!1,h=!1,p=[[0,3,0,1,0,0,0],[0,3,0,1,2,2,0],[0,3,0,17,2,0,1],[0,3,5,5,4,1,0],[0,3,21,21,4,0,1],[0,3,5,5,4,2,0]],d=[[2,0,1,1,0,1,0],[2,0,1,1,0,2,0],[2,0,2,1,3,2,0],[2,0,2,33,3,1,1]],v=0,m=1,g=0,y=1,b=2,w=3,E=4,S=5,x=6,T=7,N=8,C=9,k=10,L=11,A=12,O=13,M=14,_=15,D=16,P=17,H=18,B=[H,H,H,H,H,H,H,H,H,x,S,x,N,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,S,S,S,x,N,E,E,L,L,L,E,E,E,E,E,k,C,k,C,C,b,b,b,b,b,b,b,b,b,b,C,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,H,H,H,H,H,H,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,C,E,L,L,L,L,E,E,E,E,g,E,E,H,E,E,L,L,b,b,E,g,E,E,E,b,g,E,E,E,E,E],j=[N,N,N,N,N,N,N,N,N,N,N,H,H,H,g,y,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N,S,O,M,_,D,P,C,L,L,L,L,L,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,C,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N];t.L=g,t.R=y,t.EN=b,t.ON_R=3,t.AN=4,t.R_H=5,t.B=6,t.RLE=7,t.DOT=\"\\u00b7\",t.doBidiReorder=function(e,n,r){if(e.length<2)return{};var i=e.split(\"\"),o=new Array(i.length),u=new Array(i.length),a=[];s=r?m:v,F(i,a,i.length,n);for(var f=0;f<o.length;o[f]=f,f++);I(2,a,o),I(1,a,o);for(var f=0;f<o.length-1;f++)n[f]===w?a[f]=t.AN:a[f]===y&&(n[f]>T&&n[f]<O||n[f]===E||n[f]===H)?a[f]=t.ON_R:f>0&&i[f-1]===\"\\u0644\"&&/\\u0622|\\u0623|\\u0625|\\u0627/.test(i[f])&&(a[f-1]=a[f]=t.R_H,f++);i[i.length-1]===t.DOT&&(a[i.length-1]=t.B),i[0]===\"\\u202b\"&&(a[0]=t.RLE);for(var f=0;f<o.length;f++)u[f]=a[o[f]];return{logicalFromVisual:o,bidiLevels:u}},t.hasBidiCharacters=function(e,t){var n=!1;for(var r=0;r<e.length;r++)t[r]=R(e.charAt(r)),!n&&(t[r]==y||t[r]==T||t[r]==w)&&(n=!0);return n},t.getVisualFromLogicalIdx=function(e,t){for(var n=0;n<t.logicalFromVisual.length;n++)if(t.logicalFromVisual[n]==e)return n;return 0}}),define(\"ace/bidihandler\",[\"require\",\"exports\",\"module\",\"ace/lib/bidiutil\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"./lib/bidiutil\"),i=e(\"./lib/lang\"),s=/[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac\\u202B]/,o=function(){function e(e){this.session=e,this.bidiMap={},this.currentRow=null,this.bidiUtil=r,this.charWidths=[],this.EOL=\"\\u00ac\",this.showInvisibles=!0,this.isRtlDir=!1,this.$isRtl=!1,this.line=\"\",this.wrapIndent=0,this.EOF=\"\\u00b6\",this.RLE=\"\\u202b\",this.contentWidth=0,this.fontMetrics=null,this.rtlLineOffset=0,this.wrapOffset=0,this.isMoveLeftOperation=!1,this.seenBidi=s.test(e.getValue())}return e.prototype.isBidiRow=function(e,t,n){return this.seenBidi?(e!==this.currentRow&&(this.currentRow=e,this.updateRowLine(t,n),this.updateBidiMap()),this.bidiMap.bidiLevels):!1},e.prototype.onChange=function(e){this.seenBidi?this.currentRow=null:e.action==\"insert\"&&s.test(e.lines.join(\"\\n\"))&&(this.seenBidi=!0,this.currentRow=null)},e.prototype.getDocumentRow=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n=this.session.$getRowCacheIndex(t,this.currentRow);n>=0&&(e=this.session.$docRowCache[n])}return e},e.prototype.getSplitIndex=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n,r=this.session.$getRowCacheIndex(t,this.currentRow);while(this.currentRow-e>0){n=this.session.$getRowCacheIndex(t,this.currentRow-e-1);if(n!==r)break;r=n,e++}}else e=this.currentRow;return e},e.prototype.updateRowLine=function(e,t){e===undefined&&(e=this.getDocumentRow());var n=e===this.session.getLength()-1,s=n?this.EOF:this.EOL;this.wrapIndent=0,this.line=this.session.getLine(e),this.isRtlDir=this.$isRtl||this.line.charAt(0)===this.RLE;if(this.session.$useWrapMode){var o=this.session.$wrapData[e];o&&(t===undefined&&(t=this.getSplitIndex()),t>0&&o.length?(this.wrapIndent=o.indent,this.wrapOffset=this.wrapIndent*this.charWidths[r.L],this.line=t<o.length?this.line.substring(o[t-1],o[t]):this.line.substring(o[o.length-1])):this.line=this.line.substring(0,o[t]),t==o.length&&(this.line+=this.showInvisibles?s:r.DOT))}else this.line+=this.showInvisibles?s:r.DOT;var u=this.session,a=0,f;this.line=this.line.replace(/\\t|[\\u1100-\\u2029, \\u202F-\\uFFE6]/g,function(e,t){return e===\"\t\"||u.isFullWidth(e.charCodeAt(0))?(f=e===\"\t\"?u.getScreenTabSize(t+a):2,a+=f-1,i.stringRepeat(r.DOT,f)):e}),this.isRtlDir&&(this.fontMetrics.$main.textContent=this.line.charAt(this.line.length-1)==r.DOT?this.line.substr(0,this.line.length-1):this.line,this.rtlLineOffset=this.contentWidth-this.fontMetrics.$main.getBoundingClientRect().width)},e.prototype.updateBidiMap=function(){var e=[];r.hasBidiCharacters(this.line,e)||this.isRtlDir?this.bidiMap=r.doBidiReorder(this.line,e,this.isRtlDir):this.bidiMap={}},e.prototype.markAsDirty=function(){this.currentRow=null},e.prototype.updateCharacterWidths=function(e){if(this.characterWidth===e.$characterSize.width)return;this.fontMetrics=e;var t=this.characterWidth=e.$characterSize.width,n=e.$measureCharWidth(\"\\u05d4\");this.charWidths[r.L]=this.charWidths[r.EN]=this.charWidths[r.ON_R]=t,this.charWidths[r.R]=this.charWidths[r.AN]=n,this.charWidths[r.R_H]=n*.45,this.charWidths[r.B]=this.charWidths[r.RLE]=0,this.currentRow=null},e.prototype.setShowInvisibles=function(e){this.showInvisibles=e,this.currentRow=null},e.prototype.setEolChar=function(e){this.EOL=e},e.prototype.setContentWidth=function(e){this.contentWidth=e},e.prototype.isRtlLine=function(e){return this.$isRtl?!0:e!=undefined?this.session.getLine(e).charAt(0)==this.RLE:this.isRtlDir},e.prototype.setRtlDirection=function(e,t){var n=e.getCursorPosition();for(var r=e.selection.getSelectionAnchor().row;r<=n.row;r++)!t&&e.session.getLine(r).charAt(0)===e.session.$bidiHandler.RLE?e.session.doc.removeInLine(r,0,1):t&&e.session.getLine(r).charAt(0)!==e.session.$bidiHandler.RLE&&e.session.doc.insert({column:0,row:r},e.session.$bidiHandler.RLE)},e.prototype.getPosLeft=function(e){e-=this.wrapIndent;var t=this.line.charAt(0)===this.RLE?1:0,n=e>t?this.session.getOverwrite()?e:e-1:t,i=r.getVisualFromLogicalIdx(n,this.bidiMap),s=this.bidiMap.bidiLevels,o=0;!this.session.getOverwrite()&&e<=t&&s[i]%2!==0&&i++;for(var u=0;u<i;u++)o+=this.charWidths[s[u]];return!this.session.getOverwrite()&&e>t&&s[i]%2===0&&(o+=this.charWidths[s[i]]),this.wrapIndent&&(o+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset),this.isRtlDir&&(o+=this.rtlLineOffset),o},e.prototype.getSelections=function(e,t){var n=this.bidiMap,r=n.bidiLevels,i,s=[],o=0,u=Math.min(e,t)-this.wrapIndent,a=Math.max(e,t)-this.wrapIndent,f=!1,l=!1,c=0;this.wrapIndent&&(o+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset);for(var h,p=0;p<r.length;p++)h=n.logicalFromVisual[p],i=r[p],f=h>=u&&h<a,f&&!l?c=o:!f&&l&&s.push({left:c,width:o-c}),o+=this.charWidths[i],l=f;f&&p===r.length&&s.push({left:c,width:o-c});if(this.isRtlDir)for(var d=0;d<s.length;d++)s[d].left+=this.rtlLineOffset;return s},e.prototype.offsetToCol=function(e){this.isRtlDir&&(e-=this.rtlLineOffset);var t=0,e=Math.max(e,0),n=0,r=0,i=this.bidiMap.bidiLevels,s=this.charWidths[i[r]];this.wrapIndent&&(e-=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset);while(e>n+s/2){n+=s;if(r===i.length-1){s=0;break}s=this.charWidths[i[++r]]}return r>0&&i[r-1]%2!==0&&i[r]%2===0?(e<n&&r--,t=this.bidiMap.logicalFromVisual[r]):r>0&&i[r-1]%2===0&&i[r]%2!==0?t=1+(e>n?this.bidiMap.logicalFromVisual[r]:this.bidiMap.logicalFromVisual[r-1]):this.isRtlDir&&r===i.length-1&&s===0&&i[r-1]%2===0||!this.isRtlDir&&r===0&&i[r]%2!==0?t=1+this.bidiMap.logicalFromVisual[r]:(r>0&&i[r-1]%2!==0&&s!==0&&r--,t=this.bidiMap.logicalFromVisual[r]),t===0&&this.isRtlDir&&t++,t+this.wrapIndent},e}();t.BidiHandler=o}),define(\"ace/selection\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=function(e){this.session=e,this.doc=e.getDocument(),this.clearSelection(),this.cursor=this.lead=this.doc.createAnchor(0,0),this.anchor=this.doc.createAnchor(0,0),this.$silent=!1;var t=this;this.cursor.on(\"change\",function(e){t.$cursorChanged=!0,t.$silent||t._emit(\"changeCursor\"),!t.$isEmpty&&!t.$silent&&t._emit(\"changeSelection\"),!t.$keepDesiredColumnOnChange&&e.old.column!=e.value.column&&(t.$desiredColumn=null)}),this.anchor.on(\"change\",function(){t.$anchorChanged=!0,!t.$isEmpty&&!t.$silent&&t._emit(\"changeSelection\")})};(function(){r.implement(this,s),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return!this.$isEmpty&&this.anchor.row!=this.cursor.row},this.getCursor=function(){return this.lead.getPosition()},this.setAnchor=function(e,t){this.$isEmpty=!1,this.anchor.setPosition(e,t)},this.setSelectionAnchor=this.setAnchor,this.getAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionAnchor=this.getAnchor,this.getSelectionLead=function(){return this.lead.getPosition()},this.isBackwards=function(){var e=this.anchor,t=this.lead;return e.row>t.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.$isEmpty?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit(\"changeSelection\"))},this.selectAll=function(){this.$setSelection(0,0,Number.MAX_VALUE,Number.MAX_VALUE)},this.setRange=this.setSelectionRange=function(e,t){var n=t?e.end:e.start,r=t?e.start:e.end;this.$setSelection(n.row,n.column,r.row,r.column)},this.$setSelection=function(e,t,n,r){if(this.$silent)return;var i=this.$isEmpty,s=this.inMultiSelectMode;this.$silent=!0,this.$cursorChanged=this.$anchorChanged=!1,this.anchor.setPosition(e,t),this.cursor.setPosition(n,r),this.$isEmpty=!o.comparePoints(this.anchor,this.cursor),this.$silent=!1,this.$cursorChanged&&this._emit(\"changeCursor\"),(this.$cursorChanged||this.$anchorChanged||i!=this.$isEmpty||s)&&this._emit(\"changeSelection\")},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t==\"undefined\"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e==\"number\"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.wouldMoveIntoSoftTab=function(e,t,n){var r=e.column,i=e.column+t;return n<0&&(r=e.column-t,i=e.column),this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(r,i).split(\" \").length-1==t},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.wouldMoveIntoSoftTab(e,n,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row<this.doc.getLength()-1&&this.moveCursorTo(this.lead.row+1,0);else{var n=this.session.getTabSize(),e=this.lead;this.wouldMoveIntoSoftTab(e,n,1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,n):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var e=this.lead.row,t=this.lead.column,n=this.session.documentToScreenRow(e,t),r=this.session.screenToDocumentPosition(n,0),i=this.session.getDisplayLine(e,null,r.row,r.column),s=i.match(/^\\s*/);s[0].length!=t&&!this.session.$useEmacsStyleLineStart&&(r.column+=s[0].length),this.moveCursorToPosition(r)},this.moveCursorLineEnd=function(){var e=this.lead,t=this.session.getDocumentLastRowColumnPosition(e.row,e.column);if(this.lead.column==t.column){var n=this.session.getLine(t.row);if(t.column==n.length){var r=n.search(/\\s+$/);r>0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var i=this.session.getFoldAt(e,t,1);if(i){this.moveCursorTo(i.end.row,i.end.column);return}this.session.nonTokenRe.exec(r)&&(t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t));if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e<this.doc.getLength()-1&&this.moveCursorWordRight();return}this.session.tokenRe.exec(r)&&(t+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),this.moveCursorTo(e,t)},this.moveCursorLongWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1)){this.moveCursorTo(n.start.row,n.start.column);return}var r=this.session.getFoldStringAt(e,t,-1);r==null&&(r=this.doc.getLine(e).substring(0,t));var s=i.stringReverse(r);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0,this.session.nonTokenRe.exec(s)&&(t-=this.session.nonTokenRe.lastIndex,s=s.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0);if(t<=0){this.moveCursorTo(e,0),this.moveCursorLeft(),e>0&&this.moveCursorWordLeft();return}this.session.tokenRe.exec(s)&&(t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t=0,n,r=/\\s/,i=this.session.tokenRe;i.lastIndex=0;if(this.session.tokenRe.exec(e))t=this.session.tokenRe.lastIndex;else{while((n=e[t])&&r.test(n))t++;if(t<1){i.lastIndex=0;while((n=e[t])&&!i.test(n)){i.lastIndex=0,t++;if(r.test(n)){if(t>2){t--;break}while((n=e[t])&&r.test(n))t++;if(t>2)break}}}}return i.lastIndex=0,t},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e<s&&/^\\s*$/.test(r));/^\\s+/.test(r)||(r=\"\"),t=0}var o=this.$shortWordEndIndex(r);this.moveCursorTo(e,t+o)},this.moveCursorShortWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1))return this.moveCursorTo(n.start.row,n.start.column);var r=this.session.getLine(e).substring(0,t);if(t===0){do e--,r=this.doc.getLine(e);while(e>0&&/^\\s*$/.test(r));t=r.length,/\\s+$/.test(r)||(r=\"\")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column),r;t===0&&(e!==0&&(this.session.$bidiHandler.isBidiRow(n.row,this.lead.row)?(r=this.session.$bidiHandler.getPosLeft(n.column),n.column=Math.round(r/this.session.$bidiHandler.charWidths[0])):r=n.column*this.session.$bidiHandler.charWidths[0]),this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);if(e!=0&&this.session.lineWidgets&&this.session.lineWidgets[this.lead.row]){var i=this.session.lineWidgets[this.lead.row];e<0?e-=i.rowsAbove||0:e>0&&(e+=i.rowCount-(i.rowsAbove||0))}var s=this.session.screenToDocumentPosition(n.row+e,n.column,r);e!==0&&t===0&&s.row===this.lead.row&&s.column===this.lead.column,this.moveCursorTo(s.row,s.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0;var i=this.session.getLine(e);/[\\uDC00-\\uDFFF]/.test(i.charAt(t))&&i.charAt(t-1)&&(this.lead.row==e&&this.lead.column==t+1?t-=1:t+=1),this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach()},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList&&e.length>1){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define(\"ace/tokenizer\",[\"require\",\"exports\",\"module\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"./config\"),i=2e3,s=function(){function e(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:\"text\"},o=\"g\",u=[];for(var a=0;a<n.length;a++){var f=n[a];f.defaultToken&&(s.defaultToken=f.defaultToken),f.caseInsensitive&&o.indexOf(\"i\")===-1&&(o+=\"i\"),f.unicode&&o.indexOf(\"u\")===-1&&(o+=\"u\");if(f.regex==null)continue;f.regex instanceof RegExp&&(f.regex=f.regex.toString().slice(1,-1));var l=f.regex,c=(new RegExp(\"(?:(\"+l+\")|(.))\")).exec(\"a\").length-2;Array.isArray(f.token)?f.token.length==1||c==1?f.token=f.token[0]:c-1!=f.token.length?(this.reportError(\"number of classes and regexp groups doesn't match\",{rule:f,groupCount:c-1}),f.token=f.token[0]):(f.tokenArray=f.token,f.token=null,f.onMatch=this.$arrayTokens):typeof f.token==\"function\"&&!f.onMatch&&(c>1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\\\\d/.test(f.regex)?l=f.regex.replace(/\\\\([0-9]+)/g,function(e,t){return\"\\\\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!=\"string\"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push(\"$\")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp(\"(\"+r.join(\")|(\")+\")|($)\",o)}}return e.prototype.$setMaxTokenCount=function(e){i=e|0},e.prototype.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n==\"string\")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;i<s;i++)t[i]&&(r[r.length]={type:n[i],value:t[i]});return r},e.prototype.$arrayTokens=function(e){if(!e)return[];var t=this.splitRegex.exec(e);if(!t)return\"text\";var n=[],r=this.tokenArray;for(var i=0,s=r.length;i<s;i++)t[i+1]&&(n[n.length]={type:r[i],value:t[i+1]});return n},e.prototype.removeCapturingGroups=function(e){var t=e.replace(/\\\\.|\\[(?:\\\\.|[^\\\\\\]])*|\\(\\?[:=!<]|(\\()/g,function(e,t){return t?\"(?:\":e});return t},e.prototype.createSplitterRegexp=function(e,t){if(e.indexOf(\"(?=\")!=-1){var n=0,r=!1,i={};e.replace(/(\\\\.)|(\\((?:\\?[=!])?)|(\\))|([\\[\\]])/g,function(e,t,s,o,u,a){return r?r=u!=\"]\":u?r=!0:o?(n==i.stack&&(i.end=a+1,i.stack=-1),n--):s&&(n++,s.length!=1&&(i.stack=n,i.start=a)),e}),i.end!=null&&/^\\)*$/.test(e.substr(i.end))&&(e=e.substring(0,i.start)+e.substr(i.end))}return e.charAt(0)!=\"^\"&&(e=\"^\"+e),e.charAt(e.length-1)!=\"$\"&&(e+=\"$\"),new RegExp(e,(t||\"\").replace(\"g\",\"\"))},e.prototype.getLineTokens=function(e,t){if(t&&typeof t!=\"string\"){var n=t.slice(0);t=n[0],t===\"#tmp\"&&(n.shift(),t=n.shift())}else var n=[];var r=t||\"start\",s=this.states[r];s||(r=\"start\",s=this.states[r]);var o=this.matchMappings[r],u=this.regExps[r];u.lastIndex=0;var a,f=[],l=0,c=0,h={type:null,value:\"\"};while(a=u.exec(e)){var p=o.defaultToken,d=null,v=a[0],m=u.lastIndex;if(m-v.length>l){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;y<a.length-2;y++){if(a[y+1]===undefined)continue;d=s[o[y]],d.onMatch?p=d.onMatch(v,r,n,e):p=d.token,d.next&&(typeof d.next==\"string\"?r=d.next:r=d.next(r,n),s=this.states[r],s||(this.reportError(\"state doesn't exist\",r),r=\"start\",s=this.states[r]),o=this.matchMappings[r],l=m,u=this.regExps[r],u.lastIndex=m),d.consumeLineEnd&&(l=m);break}if(v)if(typeof p==\"string\")!!d&&d.merge===!1||h.type!==p?(h.type&&f.push(h),h={type:p,value:v}):h.value+=v;else if(p){h.type&&f.push(h),h={type:null,value:\"\"};for(var y=0;y<p.length;y++)f.push(p[y])}if(l==e.length)break;l=m;if(c++>i){c>2*e.length&&this.reportError(\"infinite loop with in ace tokenizer\",{startState:t,line:e});while(l<e.length)h.type&&f.push(h),h={value:e.substring(l,l+=500),type:\"overflow\"};r=\"start\",n=[];break}}return h.type&&f.push(h),n.length>1&&n[0]!==r&&n.unshift(\"#tmp\",r),{tokens:f,state:n.length?n:r}},e}();s.prototype.reportError=r.reportError,t.Tokenizer=s}),define(\"ace/mode/text_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../lib/lang\"),i=function(){this.$rules={start:[{token:\"empty_line\",regex:\"^$\"},{defaultToken:\"text\"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i<r.length;i++){var s=r[i];if(s.next||s.onMatch)typeof s.next==\"string\"&&s.next.indexOf(t)!==0&&(s.next=t+s.next),s.nextState&&s.nextState.indexOf(t)!==0&&(s.nextState=t+s.nextState)}this.$rules[t+n]=r}},this.getRules=function(){return this.$rules},this.embedRules=function(e,t,n,i,s){var o=typeof e==\"function\"?(new e).getRules():e;if(i)for(var u=0;u<i.length;u++)i[u]=t+i[u];else{i=[];for(var a in o)i.push(t+a)}this.addRules(o,t);if(n){var f=Array.prototype[s?\"push\":\"unshift\"];for(var u=0;u<i.length;u++)f.apply(this.$rules[i[u]],r.deepCopy(n))}this.$embeds||(this.$embeds=[]),this.$embeds.push(t)},this.getEmbeds=function(){return this.$embeds};var e=function(e,t){return(e!=\"start\"||t.length)&&t.unshift(this.nextState,e),this.nextState},t=function(e,t){return t.shift(),t.shift()||\"start\"};this.normalizeRules=function(){function i(s){var o=r[s];o.processed=!0;for(var u=0;u<o.length;u++){var a=o[u],f=null;Array.isArray(a)&&(f=a,a={}),!a.regex&&a.start&&(a.regex=a.start,a.next||(a.next=[]),a.next.push({defaultToken:a.token},{token:a.token+\".end\",regex:a.end||a.start,next:\"pop\"}),a.token=a.token+\".start\",a.push=!0);var l=a.next||a.push;if(l&&Array.isArray(l)){var c=a.stateName;c||(c=a.token,typeof c!=\"string\"&&(c=c[0]||\"\"),r[c]&&(c+=n++)),r[c]=l,a.next=c,i(c)}else l==\"pop\"&&(a.next=t);a.push&&(a.nextState=a.next||a.push,a.next=e,delete a.push);if(a.rules)for(var h in a.rules)r[h]?r[h].push&&r[h].push.apply(r[h],a.rules[h]):r[h]=a.rules[h];var p=typeof a==\"string\"?a:a.include;p&&(p===\"$self\"&&(p=\"start\"),Array.isArray(p)?f=p.map(function(e){return r[e]}):f=r[p]);if(f){var d=[u,1].concat(f);a.noEscape&&(d=d.filter(function(e){return!e.next})),o.splice.apply(o,d),u--}a.keywordMap&&(a.token=this.createKeywordMapper(a.keywordMap,a.defaultToken||\"text\",a.caseInsensitive),delete a.defaultToken)}}var n=0,r=this.$rules;Object.keys(r).forEach(i,this)},this.createKeywordMapper=function(e,t,n,r){var i=Object.create(null);return this.$keywordList=[],Object.keys(e).forEach(function(t){var s=e[t],o=s.split(r||\"|\");for(var u=o.length;u--;){var a=o[u];this.$keywordList.push(a),n&&(a=a.toLowerCase()),i[a]=t}},this),e=null,n?function(e){return i[e.toLowerCase()]||t}:function(e){return i[e]||t}},this.getKeywords=function(){return this.$keywords}}).call(i.prototype),t.TextHighlightRules=i}),define(\"ace/mode/behaviour\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(){this.$behaviours={}};(function(){this.add=function(e,t,n){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[e]:this.$behaviours[e]={}}this.$behaviours[e][t]=n},this.addBehaviours=function(e){for(var t in e)for(var n in e[t])this.add(t,n,e[t][n])},this.remove=function(e){this.$behaviours&&this.$behaviours[e]&&delete this.$behaviours[e]},this.inherit=function(e,t){if(typeof e==\"function\")var n=(new e).getBehaviours(t);else var n=e.getBehaviours(t);this.addBehaviours(n)},this.getBehaviours=function(e){if(!e)return this.$behaviours;var t={};for(var n=0;n<e.length;n++)this.$behaviours[e[n]]&&(t[e[n]]=this.$behaviours[e[n]]);return t}}).call(r.prototype),t.Behaviour=r}),define(\"ace/token_iterator\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=function(){function e(e,t,n){this.$session=e,this.$row=t,this.$rowTokens=e.getTokens(t);var r=e.getTokenAt(t,n);this.$tokenIndex=r?r.index:-1}return e.prototype.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},e.prototype.stepForward=function(){this.$tokenIndex+=1;var e;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},e.prototype.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},e.prototype.getCurrentTokenRow=function(){return this.$row},e.prototype.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},e.prototype.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}},e.prototype.getCurrentTokenRange=function(){var e=this.$rowTokens[this.$tokenIndex],t=this.getCurrentTokenColumn();return new r(this.$row,t,this.$row,t+e.value.length)},e}();t.TokenIterator=i}),define(\"ace/mode/behaviour/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/behaviour\",\"ace/token_iterator\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../../lib/oop\"),i=e(\"../behaviour\").Behaviour,s=e(\"../../token_iterator\").TokenIterator,o=e(\"../../lib/lang\"),u=[\"text\",\"paren.rparen\",\"rparen\",\"paren\",\"punctuation.operator\"],a=[\"text\",\"paren.rparen\",\"rparen\",\"paren\",\"punctuation.operator\",\"comment\"],f,l={},c={'\"':'\"',\"'\":\"'\"},h=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:\"\",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:\"\",maybeInsertedLineEnd:\"\"}},p=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},d=function(e){e=e||{},this.add(\"braces\",\"insertion\",function(t,n,r,i,s){var u=r.getCursorPosition(),a=i.doc.getLine(u.row);if(s==\"{\"){h(r);var l=r.getSelectionRange(),c=i.doc.getTextRange(l);if(c!==\"\"&&c!==\"{\"&&r.getWrapBehavioursEnabled())return p(l,c,\"{\",\"}\");if(d.isSaneInsertion(r,i))return/[\\]\\}\\)]/.test(a[u.column])||r.inMultiSelectMode||e.braces?(d.recordAutoInsert(r,i,\"}\"),{text:\"{}\",selection:[1,1]}):(d.recordMaybeInsert(r,i,\"{\"),{text:\"{\",selection:[1,1]})}else if(s==\"}\"){h(r);var v=a.substring(u.column,u.column+1);if(v==\"}\"){var m=i.$findOpeningBracket(\"}\",{column:u.column+1,row:u.row});if(m!==null&&d.isAutoInsertedClosing(u,a,s))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}else{if(s==\"\\n\"||s==\"\\r\\n\"){h(r);var g=\"\";d.isMaybeInsertedClosing(u,a)&&(g=o.stringRepeat(\"}\",f.maybeInsertedBrackets),d.clearMaybeInsertedClosing());var v=a.substring(u.column,u.column+1);if(v===\"}\"){var y=i.findMatchingBracket({row:u.row,column:u.column+1},\"}\");if(!y)return null;var b=this.$getIndent(i.getLine(y.row))}else{if(!g){d.clearMaybeInsertedClosing();return}var b=this.$getIndent(a)}var w=b+i.getTabString();return{text:\"\\n\"+w+\"\\n\"+b+g,selection:[1,w.length,1,w.length]}}d.clearMaybeInsertedClosing()}}),this.add(\"braces\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"{\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u==\"}\")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add(\"parens\",\"insertion\",function(e,t,n,r,i){if(i==\"(\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"(\",\")\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\")\"),{text:\"()\",selection:[1,1]}}else if(i==\")\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\")\"){var l=r.$findOpeningBracket(\")\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"parens\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"(\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\")\")return i.end.column++,i}}),this.add(\"brackets\",\"insertion\",function(e,t,n,r,i){if(i==\"[\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"[\",\"]\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\"]\"),{text:\"[]\",selection:[1,1]}}else if(i==\"]\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\"]\"){var l=r.$findOpeningBracket(\"]\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"brackets\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"[\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\"]\")return i.end.column++,i}}),this.add(\"string_dquotes\",\"insertion\",function(e,t,n,r,i){var s=r.$mode.$quotes||c;if(i.length==1&&s[i]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;h(n);var o=i,u=n.getSelectionRange(),a=r.doc.getTextRange(u);if(a!==\"\"&&(a.length!=1||!s[a])&&n.getWrapBehavioursEnabled())return p(u,a,o,o);if(!a){var f=n.getCursorPosition(),l=r.doc.getLine(f.row),d=l.substring(f.column-1,f.column),v=l.substring(f.column,f.column+1),m=r.getTokenAt(f.row,f.column),g=r.getTokenAt(f.row,f.column+1);if(d==\"\\\\\"&&m&&/escape/.test(m.type))return null;var y=m&&/string|escape/.test(m.type),b=!g||/string|escape/.test(g.type),w;if(v==o)w=y!==b,w&&/string\\.end/.test(g.type)&&(w=!1);else{if(y&&!b)return null;if(y&&b)return null;var E=r.$mode.tokenRe;E.lastIndex=0;var S=E.test(d);E.lastIndex=0;var x=E.test(v),T=r.$mode.$pairQuotesAfter,N=T&&T[o]&&T[o].test(d);if(!N&&S||x)return null;if(v&&!/[\\s;,.})\\]\\\\]/.test(v))return null;var C=l[f.column-2];if(!(d!=o||C!=o&&!E.test(C)))return null;w=!0}return{text:w?o+o:\"\",selection:[1,1]}}}}),this.add(\"string_dquotes\",\"deletion\",function(e,t,n,r,i){var s=r.$mode.$quotes||c,o=r.doc.getTextRange(i);if(!i.isMultiLine()&&s.hasOwnProperty(o)){h(n);var u=r.doc.getLine(i.start.row),a=u.substring(i.start.column+1,i.start.column+2);if(a==o)return i.end.column++,i}}),e.closeDocComment!==!1&&this.add(\"doc comment end\",\"insertion\",function(e,t,n,r,i){if(e===\"doc-start\"&&(i===\"\\n\"||i===\"\\r\\n\")&&n.selection.isEmpty()){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=r.doc.getLine(s.row+1),a=this.$getIndent(o);if(/\\s*\\*/.test(u))return/^\\s*\\*/.test(o)?{text:i+a+\"* \",selection:[1,3+a.length,1,3+a.length]}:{text:i+a+\" * \",selection:[1,3+a.length,1,3+a.length]};if(/\\/\\*\\*/.test(o.substring(0,s.column)))return{text:i+a+\" * \"+i+\" \"+a+\"*/\",selection:[1,4+a.length,1,4+a.length]}}})};d.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||\"text\",u)){if(/[)}\\]]/.test(e.session.getLine(n.row)[n.column]))return!0;var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||\"text\",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||\"text\",a)},d.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},d.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},d.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},d.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},d.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},d.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},d.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(d,i),t.CstyleBehaviour=d}),define(\"ace/unicode\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=[48,9,8,25,5,0,2,25,48,0,11,0,5,0,6,22,2,30,2,457,5,11,15,4,8,0,2,0,18,116,2,1,3,3,9,0,2,2,2,0,2,19,2,82,2,138,2,4,3,155,12,37,3,0,8,38,10,44,2,0,2,1,2,1,2,0,9,26,6,2,30,10,7,61,2,9,5,101,2,7,3,9,2,18,3,0,17,58,3,100,15,53,5,0,6,45,211,57,3,18,2,5,3,11,3,9,2,1,7,6,2,2,2,7,3,1,3,21,2,6,2,0,4,3,3,8,3,1,3,3,9,0,5,1,2,4,3,11,16,2,2,5,5,1,3,21,2,6,2,1,2,1,2,1,3,0,2,4,5,1,3,2,4,0,8,3,2,0,8,15,12,2,2,8,2,2,2,21,2,6,2,1,2,4,3,9,2,2,2,2,3,0,16,3,3,9,18,2,2,7,3,1,3,21,2,6,2,1,2,4,3,8,3,1,3,2,9,1,5,1,2,4,3,9,2,0,17,1,2,5,4,2,2,3,4,1,2,0,2,1,4,1,4,2,4,11,5,4,4,2,2,3,3,0,7,0,15,9,18,2,2,7,2,2,2,22,2,9,2,4,4,7,2,2,2,3,8,1,2,1,7,3,3,9,19,1,2,7,2,2,2,22,2,9,2,4,3,8,2,2,2,3,8,1,8,0,2,3,3,9,19,1,2,7,2,2,2,22,2,15,4,7,2,2,2,3,10,0,9,3,3,9,11,5,3,1,2,17,4,23,2,8,2,0,3,6,4,0,5,5,2,0,2,7,19,1,14,57,6,14,2,9,40,1,2,0,3,1,2,0,3,0,7,3,2,6,2,2,2,0,2,0,3,1,2,12,2,2,3,4,2,0,2,5,3,9,3,1,35,0,24,1,7,9,12,0,2,0,2,0,5,9,2,35,5,19,2,5,5,7,2,35,10,0,58,73,7,77,3,37,11,42,2,0,4,328,2,3,3,6,2,0,2,3,3,40,2,3,3,32,2,3,3,6,2,0,2,3,3,14,2,56,2,3,3,66,5,0,33,15,17,84,13,619,3,16,2,25,6,74,22,12,2,6,12,20,12,19,13,12,2,2,2,1,13,51,3,29,4,0,5,1,3,9,34,2,3,9,7,87,9,42,6,69,11,28,4,11,5,11,11,39,3,4,12,43,5,25,7,10,38,27,5,62,2,28,3,10,7,9,14,0,89,75,5,9,18,8,13,42,4,11,71,55,9,9,4,48,83,2,2,30,14,230,23,280,3,5,3,37,3,5,3,7,2,0,2,0,2,0,2,30,3,52,2,6,2,0,4,2,2,6,4,3,3,5,5,12,6,2,2,6,67,1,20,0,29,0,14,0,17,4,60,12,5,0,4,11,18,0,5,0,3,9,2,0,4,4,7,0,2,0,2,0,2,3,2,10,3,3,6,4,5,0,53,1,2684,46,2,46,2,132,7,6,15,37,11,53,10,0,17,22,10,6,2,6,2,6,2,6,2,6,2,6,2,6,2,6,2,31,48,0,470,1,36,5,2,4,6,1,5,85,3,1,3,2,2,89,2,3,6,40,4,93,18,23,57,15,513,6581,75,20939,53,1164,68,45,3,268,4,27,21,31,3,13,13,1,2,24,9,69,11,1,38,8,3,102,3,1,111,44,25,51,13,68,12,9,7,23,4,0,5,45,3,35,13,28,4,64,15,10,39,54,10,13,3,9,7,22,4,1,5,66,25,2,227,42,2,1,3,9,7,11171,13,22,5,48,8453,301,3,61,3,105,39,6,13,4,6,11,2,12,2,4,2,0,2,1,2,1,2,107,34,362,19,63,3,53,41,11,5,15,17,6,13,1,25,2,33,4,2,134,20,9,8,25,5,0,2,25,12,88,4,5,3,5,3,5,3,2],i=0,s=[];for(var o=0;o<r.length;o+=2)s.push(i+=r[o]),r[o+1]&&s.push(45,i+=r[o+1]);t.wordChars=String.fromCharCode.apply(null,s)}),define(\"ace/mode/text\",[\"require\",\"exports\",\"module\",\"ace/config\",\"ace/tokenizer\",\"ace/mode/text_highlight_rules\",\"ace/mode/behaviour/cstyle\",\"ace/unicode\",\"ace/lib/lang\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../config\"),i=e(\"../tokenizer\").Tokenizer,s=e(\"./text_highlight_rules\").TextHighlightRules,o=e(\"./behaviour/cstyle\").CstyleBehaviour,u=e(\"../unicode\"),a=e(\"../lib/lang\"),f=e(\"../token_iterator\").TokenIterator,l=e(\"../range\").Range,c=function(){this.HighlightRules=s};(function(){this.$defaultBehaviour=new o,this.tokenRe=new RegExp(\"^[\"+u.wordChars+\"\\\\$_]+\",\"g\"),this.nonTokenRe=new RegExp(\"^(?:[^\"+u.wordChars+\"\\\\$_]|\\\\s])+\",\"g\"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules(this.$highlightRuleConfig),this.$tokenizer=new i(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart=\"\",this.blockComment=\"\",this.toggleCommentLines=function(e,t,n,r){function w(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}var i=t.doc,s=!0,o=!0,u=Infinity,f=t.getTabSize(),l=!1;if(!this.lineCommentStart){if(!this.blockComment)return!1;var c=this.blockComment.start,h=this.blockComment.end,p=new RegExp(\"^(\\\\s*)(?:\"+a.escapeRegExp(c)+\")\"),d=new RegExp(\"(?:\"+a.escapeRegExp(h)+\")\\\\s*$\"),v=function(e,t){if(g(e,t))return;if(!s||/\\S/.test(e))i.insertInLine({row:t,column:e.length},h),i.insertInLine({row:t,column:u},c)},m=function(e,t){var n;(n=e.match(d))&&i.removeInLine(t,e.length-n[0].length,e.length),(n=e.match(p))&&i.removeInLine(t,n[1].length,n[0].length)},g=function(e,n){if(p.test(e))return!0;var r=t.getTokens(n);for(var i=0;i<r.length;i++)if(r[i].type===\"comment\")return!0}}else{if(Array.isArray(this.lineCommentStart))var p=this.lineCommentStart.map(a.escapeRegExp).join(\"|\"),c=this.lineCommentStart[0];else var p=a.escapeRegExp(this.lineCommentStart),c=this.lineCommentStart;p=new RegExp(\"^(\\\\s*)(?:\"+p+\") ?\"),l=t.getUseSoftTabs();var m=function(e,t){var n=e.match(p);if(!n)return;var r=n[1].length,s=n[0].length;!b(e,r,s)&&n[0][s-1]==\" \"&&s--,i.removeInLine(t,r,s)},y=c+\" \",v=function(e,t){if(!s||/\\S/.test(e))b(e,u,u)?i.insertInLine({row:t,column:u},y):i.insertInLine({row:t,column:u},c)},g=function(e,t){return p.test(e)},b=function(e,t,n){var r=0;while(t--&&e.charAt(t)==\" \")r++;if(r%f!=0)return!1;var r=0;while(e.charAt(n++)==\" \")r++;return f>2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\\S/);n!==-1?(n<u&&(u=n),o&&!g(e,t)&&(o=!1)):E>e.length&&(E=e.length)}),u==Infinity&&(u=E,s=!1,o=!1),l&&u%f!=0&&(u=Math.floor(u/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new f(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,a=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new l(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new f(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new l(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);a.start.row==c&&(a.start.column+=h),a.end.row==c&&(a.end.column+=h),t.selection.fromOrientedRange(a)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)if(e[t]){var n=e[t],i=n.prototype.$id,s=r.$modes[i];s||(r.$modes[i]=s=new n),r.$modes[t]||(r.$modes[t]=s),this.$embeds.push(t),this.$modes[t]=s}var o=[\"toggleBlockComment\",\"toggleCommentLines\",\"getNextLineIndent\",\"checkOutdent\",\"autoOutdent\",\"transformAction\",\"getCompletions\"];for(var t=0;t<o.length;t++)(function(e){var n=o[t],r=e[n];e[o[t]]=function(){return this.$delegator(n,arguments,r)}})(this)},this.$delegator=function(e,t,n){var r=t[0]||\"start\";if(typeof r!=\"string\"){if(Array.isArray(r[2])){var i=r[2][r[2].length-1],s=this.$modes[i];if(s)return s[e].apply(s,[r[1]].concat([].slice.call(t,1)))}r=r[0]||\"start\"}for(var o=0;o<this.$embeds.length;o++){if(!this.$modes[this.$embeds[o]])continue;var u=r.split(this.$embeds[o]);if(!u[0]&&u[1]){t[0]=u[1];var s=this.$modes[this.$embeds[o]];return s[e].apply(s,t)}}var a=n.apply(this,t);return n?a:undefined},this.transformAction=function(e,t,n,r,i){if(this.$behaviour){var s=this.$behaviour.getBehaviours();for(var o in s)if(s[o][t]){var u=s[o][t].apply(this,arguments);if(u)return u}}},this.getKeywords=function(e){if(!this.completionKeywords){var t=this.$tokenizer.rules,n=[];for(var r in t){var i=t[r];for(var s=0,o=i.length;s<o;s++)if(typeof i[s].token==\"string\")/keyword|support|storage/.test(i[s].token)&&n.push(i[s].regex);else if(typeof i[s].token==\"object\")for(var u=0,a=i[s].token.length;u<a;u++)if(/keyword|support|storage/.test(i[s].token[u])){var r=i[s].regex.match(/\\(.+?\\)/g)[u];n.push(r.substr(1,r.length-2))}}this.completionKeywords=n}return e?n.concat(this.$keywordList||[]):this.$keywordList},this.$createKeywordList=function(){return this.$highlightRules||this.getTokenizer(),this.$keywordList=this.$highlightRules.$keywordList||[]},this.getCompletions=function(e,t,n,r){var i=this.$keywordList||this.$createKeywordList();return i.map(function(e){return{name:e,value:e,score:0,meta:\"keyword\"}})},this.$id=\"ace/mode/text\"}).call(c.prototype),t.Mode=c}),define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e,t){throw console.log(\"Invalid Delta:\",e),\"Invalid Delta: \"+t}function i(e,t){return t.row>=0&&t.row<e.length&&t.column>=0&&t.column<=e[t.row].length}function s(e,t){t.action!=\"insert\"&&t.action!=\"remove\"&&r(t,\"delta.action must be 'insert' or 'remove'\"),t.lines instanceof Array||r(t,\"delta.lines must be an Array\"),(!t.start||!t.end)&&r(t,\"delta.start/end must be an present\");var n=t.start;i(e,t.start)||r(t,\"delta.start must be contained in document\");var s=t.end;t.action==\"remove\"&&!i(e,s)&&r(t,\"delta.end must contained in document for 'remove' actions\");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,\"delta.range must match delta lines\")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||\"\";switch(t.action){case\"insert\":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case\"remove\":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";function o(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e.row<t.row||e.row==t.row&&r}function u(e,t,n){var r=e.action==\"insert\",i=(r?1:-1)*(e.end.row-e.start.row),s=(r?1:-1)*(e.end.column-e.start.column),u=e.start,a=r?u:e.end;return o(t,u,n)?{row:t.row,column:t.column}:o(a,t,!n)?{row:t.row+i,column:t.column+(t.row==a.row?s:0)}:{row:u.row,column:u.column}}var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=function(){function e(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n==\"undefined\"?this.setPosition(t.row,t.column):this.setPosition(t,n)}return e.prototype.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},e.prototype.getDocument=function(){return this.document},e.prototype.onChange=function(e){if(e.start.row==e.end.row&&e.start.row!=this.row)return;if(e.start.row>this.row)return;var t=u(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(t.row,t.column,!0)},e.prototype.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal(\"change\",{old:i,value:r})},e.prototype.detach=function(){this.document.off(\"change\",this.$onChange)},e.prototype.attach=function(e){this.document=e||this.document,this.document.on(\"change\",this.$onChange)},e.prototype.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n},e}();s.prototype.$insertRight=!1,r.implement(s.prototype,i),t.Anchor=s}),define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./apply_delta\").applyDelta,s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=e(\"./anchor\").Anchor,a=function(){function e(e){this.$lines=[\"\"],e.length===0?this.$lines=[\"\"]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)}return e.prototype.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e||\"\")},e.prototype.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},e.prototype.createAnchor=function(e,t){return new u(this,e,t)},e.prototype.$detectNewLine=function(e){var t=e.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=t?t[1]:\"\\n\",this._signal(\"changeNewLineMode\")},e.prototype.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},e.prototype.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal(\"changeNewLineMode\")},e.prototype.getNewLineMode=function(){return this.$newLineMode},e.prototype.isNewLine=function(e){return e==\"\\r\\n\"||e==\"\\r\"||e==\"\\n\"},e.prototype.getLine=function(e){return this.$lines[e]||\"\"},e.prototype.getLines=function(e,t){return this.$lines.slice(e,t+1)},e.prototype.getAllLines=function(){return this.getLines(0,this.getLength())},e.prototype.getLength=function(){return this.$lines.length},e.prototype.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},e.prototype.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||\"\").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},e.prototype.insertLines=function(e,t){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(e,t)},e.prototype.removeLines=function(e,t){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(e,t)},e.prototype.insertNewLine=function(e){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(e,[\"\",\"\"])},e.prototype.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},e.prototype.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:\"insert\",lines:[t]},!0),this.clonePos(r)},e.prototype.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},e.prototype.clonePos=function(e){return{row:e.row,column:e.column}},e.prototype.pos=function(e,t){return{row:e,column:t}},e.prototype.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},e.prototype.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e<this.getLength()?(t=t.concat([\"\"]),n=0):(t=[\"\"].concat(t),e--,n=this.$lines[e].length),this.insertMergedLines({row:e,column:n},t)},e.prototype.insertMergedLines=function(e,t){var n=this.clippedPos(e.row,e.column),r={row:n.row+t.length-1,column:(t.length==1?n.column:0)+t[t.length-1].length};return this.applyDelta({start:n,end:r,action:\"insert\",lines:t}),this.clonePos(r)},e.prototype.remove=function(e){var t=this.clippedPos(e.start.row,e.start.column),n=this.clippedPos(e.end.row,e.end.column);return this.applyDelta({start:t,end:n,action:\"remove\",lines:this.getLinesForRange({start:t,end:n})}),this.clonePos(t)},e.prototype.removeInLine=function(e,t,n){var r=this.clippedPos(e,t),i=this.clippedPos(e,n);return this.applyDelta({start:r,end:i,action:\"remove\",lines:this.getLinesForRange({start:r,end:i})},!0),this.clonePos(r)},e.prototype.removeFullLines=function(e,t){e=Math.min(Math.max(0,e),this.getLength()-1),t=Math.min(Math.max(0,t),this.getLength()-1);var n=t==this.getLength()-1&&e>0,r=t<this.getLength()-1,i=n?e-1:e,s=n?this.getLine(i).length:0,u=r?t+1:t,a=r?0:this.getLine(u).length,f=new o(i,s,u,a),l=this.$lines.slice(e,t+1);return this.applyDelta({start:f.start,end:f.end,action:\"remove\",lines:this.getLinesForRange(f)}),l},e.prototype.removeNewLine=function(e){e<this.getLength()-1&&e>=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:\"remove\",lines:[\"\",\"\"]})},e.prototype.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},e.prototype.applyDeltas=function(e){for(var t=0;t<e.length;t++)this.applyDelta(e[t])},e.prototype.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--)this.revertDelta(e[t])},e.prototype.applyDelta=function(e,t){var n=e.action==\"insert\";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4?this.$splitAndapplyLargeDelta(e,2e4):(i(this.$lines,e,t),this._signal(\"change\",e))},e.prototype.$safeApplyDelta=function(e){var t=this.$lines.length;(e.action==\"remove\"&&e.start.row<t&&e.end.row<t||e.action==\"insert\"&&e.start.row<=t)&&this.applyDelta(e)},e.prototype.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length-t+1,i=e.start.row,s=e.start.column;for(var o=0,u=0;o<r;o=u){u+=t-1;var a=n.slice(o,u);a.push(\"\"),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}e.lines=n.slice(o),e.start.row=i+o,e.start.column=s,this.applyDelta(e,!0)},e.prototype.revertDelta=function(e){this.$safeApplyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action==\"insert\"?\"remove\":\"insert\",lines:e.lines.slice()})},e.prototype.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i<s;i++){e-=n[i].length+r;if(e<0)return{row:i,column:e+n[i].length+r}}return{row:s-1,column:e+n[s-1].length+r}},e.prototype.positionToIndex=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length,i=0,s=Math.min(e.row,n.length);for(var o=t||0;o<s;++o)i+=n[o].length+r;return i+e.column},e.prototype.$split=function(e){return e.split(/\\r\\n|\\r|\\n/)},e}();a.prototype.$autoNewLine=\"\",a.prototype.$newLineMode=\"auto\",r.implement(a.prototype,s),t.Document=a}),define(\"ace/background_tokenizer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=function(){function e(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=-1,i=n.doc,s=t;while(n.lines[t])t++;var o=i.getLength(),u=0;n.running=!1;while(t<o){n.$tokenizeRow(t),r=t;do t++;while(n.lines[t]);u++;if(u%5===0&&new Date-e>20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,r==-1&&(r=t),s<=r&&n.fireUpdateEvent(s,r)}}return e.prototype.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},e.prototype.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},e.prototype.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal(\"update\",{data:n})},e.prototype.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},e.prototype.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},e.prototype.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action==\"remove\")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},e.prototype.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},e.prototype.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},e.prototype.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||\"start\"},e.prototype.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+\"\"!=r.state+\"\"?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens},e.prototype.cleanup=function(){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.removeAllListeners()},e}();r.implement(s.prototype,i),t.BackgroundTokenizer=s}),define(\"ace/search_highlight\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/lang\"),i=e(\"./range\").Range,s=function(){function e(e,t,n){n===void 0&&(n=\"text\"),this.setRegexp(e),this.clazz=t,this.type=n}return e.prototype.setRegexp=function(e){if(this.regExp+\"\"==e+\"\")return;this.regExp=e,this.cache=[]},e.prototype.update=function(e,t,n,s){if(!this.regExp)return;var o=s.firstRow,u=s.lastRow,a={};for(var f=o;f<=u;f++){var l=this.cache[f];l==null&&(l=r.getMatchOffsets(n.getLine(f),this.regExp),l.length>this.MAX_RANGES&&(l=l.slice(0,this.MAX_RANGES)),l=l.map(function(e){return new i(f,e.offset,f,e.offset+e.length)}),this.cache[f]=l.length?l:\"\");for(var c=l.length;c--;){var h=l[c].toScreenRange(n),p=h.toString();if(a[p])continue;a[p]=!0,t.drawSingleLineMarker(e,h,this.clazz,s)}}},e}();s.prototype.MAX_RANGES=500,t.SearchHighlight=s}),define(\"ace/edit_session/fold_line\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=function(){function e(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}return e.prototype.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},e.prototype.addFold=function(e){if(e.sameRow){if(e.start.row<this.startRow||e.endRow>this.endRow)throw new Error(\"Can't add a fold to this FoldLine as it has no connection\");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error(\"Trying to add fold to FoldRow that doesn't have a matching row\");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},e.prototype.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},e.prototype.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f<i.length;f++){s=i[f],o=s.range.compareStart(t,n);if(o==-1){e(null,t,n,r,a);return}u=e(null,s.start.row,s.start.column,r,a),u=!u&&e(s.placeholder,s.start.row,s.start.column,r);if(u||o===0)return;a=!s.sameRow,r=s.end.column}e(null,t,n,r,a)},e.prototype.getNextFoldTo=function(e,t){var n,r;for(var i=0;i<this.folds.length;i++){n=this.folds[i],r=n.range.compareEnd(e,t);if(r==-1)return{fold:n,kind:\"after\"};if(r===0)return{fold:n,kind:\"inside\"}}return null},e.prototype.addRemoveChars=function(e,t,n){var r=this.getNextFoldTo(e,t),i,s;if(r){i=r.fold;if(r.kind==\"inside\"&&i.start.column!=t&&i.start.row!=e)window.console&&window.console.log(e,t,i);else if(i.start.row==e){s=this.folds;var o=s.indexOf(i);o===0&&(this.start.column+=n);for(o;o<s.length;o++){i=s[o],i.start.column+=n;if(!i.sameRow)return;i.end.column+=n}this.end.column+=n}}},e.prototype.split=function(t,n){var r=this.getNextFoldTo(t,n);if(!r||r.kind==\"inside\")return null;var i=r.fold,s=this.folds,o=this.foldData,u=s.indexOf(i),a=s[u-1];this.end.row=a.end.row,this.end.column=a.end.column,s=s.splice(u,s.length-u);var f=new e(o,s);return o.splice(o.indexOf(this)+1,0,f),f},e.prototype.merge=function(e){var t=e.folds;for(var n=0;n<t.length;n++)this.addFold(t[n]);var r=this.foldData;r.splice(r.indexOf(e),1)},e.prototype.toString=function(){var e=[this.range.toString()+\": [\"];return this.folds.forEach(function(t){e.push(\"  \"+t.toString())}),e.push(\"]\"),e.join(\"\\n\")},e.prototype.idxToPosition=function(e){var t=0;for(var n=0;n<this.folds.length;n++){var r=this.folds[n];e-=r.start.column-t;if(e<0)return{row:r.start.row,column:r.start.column+e};e-=r.placeholder.length;if(e<0)return r.start;t=r.end.column}return{row:this.end.row,column:this.end.column+e}},e}();t.FoldLine=i}),define(\"ace/range_list\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=r.comparePoints,s=function(){function e(){this.ranges=[],this.$bias=1}return e.prototype.pointIndex=function(e,t,n){var r=this.ranges;for(var s=n||0;s<r.length;s++){var o=r[s],u=i(e,o.end);if(u>0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},e.prototype.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},e.prototype.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},e.prototype.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},e.prototype.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s<t.length;s++){r=n,n=t[s];var o=i(r.end,n.start);if(o<0)continue;if(o==0&&!r.isEmpty()&&!n.isEmpty())continue;i(r.end,n.end)<0&&(r.end.row=n.end.row,r.end.column=n.end.column),t.splice(s,1),e.push(n),n=r,s--}return this.ranges=t,e},e.prototype.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},e.prototype.containsPoint=function(e){return this.pointIndex(e)>=0},e.prototype.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},e.prototype.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.row<e)return[];var r=this.pointIndex({row:e,column:0});r<0&&(r=-r-1);var i=this.pointIndex({row:t,column:0},r);i<0&&(i=-i-1);var s=[];for(var o=r;o<i;o++)s.push(n[o]);return s},e.prototype.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},e.prototype.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on(\"change\",this.onChange)},e.prototype.detach=function(){if(!this.session)return;this.session.removeListener(\"change\",this.onChange),this.session=null},e.prototype.$onChange=function(e){var t=e.start,n=e.end,r=t.row,i=n.row,s=this.ranges;for(var o=0,u=s.length;o<u;o++){var a=s[o];if(a.end.row>=r)break}if(e.action==\"insert\"){var f=i-r,l=-t.column+n.column;for(;o<u;o++){var a=s[o];if(a.start.row>r)break;a.start.row==r&&a.start.column>=t.column&&(a.start.column==t.column&&this.$bias<=0||(a.start.column+=l,a.start.row+=f));if(a.end.row==r&&a.end.column>=t.column){if(a.end.column==t.column&&this.$bias<0)continue;a.end.column==t.column&&l>0&&o<u-1&&a.end.column>a.start.column&&a.end.column==s[o+1].start.column&&(a.end.column-=l),a.end.column+=l,a.end.row+=f}}}else{var f=r-i,l=t.column-n.column;for(;o<u;o++){var a=s[o];if(a.start.row>i)break;if(a.end.row<i&&(r<a.end.row||r==a.end.row&&t.column<a.end.column))a.end.row=r,a.end.column=t.column;else if(a.end.row==i)if(a.end.column<=n.column){if(f||a.end.column>t.column)a.end.column=t.column,a.end.row=t.row}else a.end.column+=l,a.end.row+=f;else a.end.row>i&&(a.end.row+=f);if(a.start.row<i&&(r<a.start.row||r==a.start.row&&t.column<a.start.column))a.start.row=r,a.start.column=t.column;else if(a.start.row==i)if(a.start.column<=n.column){if(f||a.start.column>t.column)a.start.column=t.column,a.start.row=t.row}else a.start.column+=l,a.start.row+=f;else a.start.row>i&&(a.start.row+=f)}}if(f!=0&&o<u)for(;o<u;o++){var a=s[o];a.start.row+=f,a.end.row+=f}},e}();s.prototype.comparePoints=i,t.RangeList=s}),define(\"ace/edit_session/fold\",[\"require\",\"exports\",\"module\",\"ace/range_list\"],function(e,t,n){\"use strict\";function o(e,t){e.row-=t.row,e.row==0&&(e.column-=t.column)}function u(e,t){o(e.start,t),o(e.end,t)}function a(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row}function f(e,t){a(e.start,t),a(e.end,t)}var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=e(\"../range_list\").RangeList,s=function(e){function t(t,n){var r=e.call(this)||this;return r.foldLine=null,r.placeholder=n,r.range=t,r.start=t.start,r.end=t.end,r.sameRow=t.start.row==t.end.row,r.subFolds=r.ranges=[],r}return r(t,e),t.prototype.toString=function(){return'\"'+this.placeholder+'\" '+this.range.toString()},t.prototype.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},t.prototype.clone=function(){var e=this.range.clone(),n=new t(e,this.placeholder);return this.subFolds.forEach(function(e){n.subFolds.push(e.clone())}),n.collapseChildren=this.collapseChildren,n},t.prototype.addSubFold=function(e){if(this.range.isEqual(e))return;u(e,this.start);var t=e.start.row,n=e.start.column;for(var r=0,i=-1;r<this.subFolds.length;r++){i=this.subFolds[r].range.compare(t,n);if(i!=1)break}var s=this.subFolds[r],o=0;if(i==0){if(s.range.containsRange(e))return s.addSubFold(e);o=1}var t=e.range.end.row,n=e.range.end.column;for(var a=r,i=-1;a<this.subFolds.length;a++){i=this.subFolds[a].range.compare(t,n);if(i!=1)break}i==0&&a++;var f=this.subFolds.splice(r,a-r,e),l=i==0?f.length-1:f.length;for(var c=o;c<l;c++)e.addSubFold(f[c]);return e.setFoldLine(this.foldLine),e},t.prototype.restoreRange=function(e){return f(e,this.start)},t}(i);t.Fold=s}),define(\"ace/edit_session/folding\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/edit_session/fold_line\",\"ace/edit_session/fold\",\"ace/token_iterator\",\"ace/mouse/mouse_event\"],function(e,t,n){\"use strict\";function a(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s<i.length;s++){var o=i[s].range;if(o.contains(e,t)){if(n==1&&o.isEnd(e,t)&&!o.isEmpty())continue;if(n==-1&&o.isStart(e,t)&&!o.isEmpty())continue;return i[s]}}},this.getFoldsInRange=function(e){var t=e.start,n=e.end,r=this.$foldData,i=[];t.column+=1,n.column-=1;for(var s=0;s<r.length;s++){var o=r[s].range.compareRange(e);if(o==2)continue;if(o==-2)break;var u=r[s].folds;for(var a=0;a<u.length;a++){var f=u[a];o=f.range.compareRange(e);if(o==-2)break;if(o==2)continue;if(o==42)break;i.push(f)}}return t.column-=1,n.column+=1,i},this.getFoldsInRangeList=function(e){if(Array.isArray(e)){var t=[];e.forEach(function(e){t=t.concat(this.getFoldsInRange(e))},this)}else var t=this.getFoldsInRange(e);return t},this.getAllFolds=function(){var e=[],t=this.$foldData;for(var n=0;n<t.length;n++)for(var r=0;r<t[n].folds.length;r++)e.push(t[n].folds[r]);return e},this.getFoldStringAt=function(e,t,n,r){r=r||this.getFoldLine(e);if(!r)return null;var i={end:{column:0}},s,o;for(var u=0;u<r.folds.length;u++){o=r.folds[u];var a=o.range.compareEnd(e,t);if(a==-1){s=this.getLine(o.start.row).substring(i.end.column,o.start.column);break}if(a===0)return null;i=o}return s||(s=this.getLine(o.start.row).substring(i.end.column)),n==-1?s.substring(0,t-i.end.column):n==1?s.substring(t-i.end.column):s},this.getFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.start.row<=e&&i.end.row>=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.end.row>=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i<n.length;i++){var s=n[i],o=s.end.row,u=s.start.row;if(o>=t){u<t&&(u>=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column,c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);c&&!c.range.isStart(u,a)&&this.removeFold(c),h&&!h.range.isEnd(f,l)&&this.removeFold(h);var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),o.collapseChildren||p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d<n.length;d++){var v=n[d];if(f==v.start.row){v.addFold(o),r=!0;break}if(u==v.end.row){v.addFold(o),r=!0;if(!o.sameRow){var m=n[d+1];if(m&&m.start.row==f){v.merge(m);break}}break}if(f<=v.start.row)break}return r||(v=this.$addFoldLine(new i(this.$foldData,o))),this.$useWrapMode?this.$updateWrapData(v.start.row,v.start.row):this.$updateRowLengthCache(v.start.row,v.start.row),this.$modified=!0,this._signal(\"changeFold\",{data:o,action:\"add\"}),o},this.addFolds=function(e){e.forEach(function(e){this.addFold(e)},this)},this.removeFold=function(e){var t=e.foldLine,n=t.start.row,r=t.end.row,i=this.$foldData,s=t.folds;if(s.length==1)i.splice(i.indexOf(t),1);else if(t.range.isEnd(e.end.row,e.end.column))s.pop(),t.end.row=s[s.length-1].end.row,t.end.column=s[s.length-1].end.column;else if(t.range.isStart(e.start.row,e.start.column))s.shift(),t.start.row=s[0].start.row,t.start.column=s[0].start.column;else if(e.sameRow)s.splice(s.indexOf(e),1);else{var o=t.split(e.start.row,e.start.column);s=o.folds,s.shift(),o.start.row=s[0].start.row,o.start.column=s[0].start.column}this.$updating||(this.$useWrapMode?this.$updateWrapData(n,r):this.$updateRowLengthCache(n,r)),this.$modified=!0,this._signal(\"changeFold\",{data:e,action:\"remove\"})},this.removeFolds=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(e[n]);t.forEach(function(e){this.removeFold(e)},this),this.$modified=!0},this.expandFold=function(e){this.removeFold(e),e.subFolds.forEach(function(t){e.restoreRange(t),this.addFold(t)},this),e.collapseChildren>0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;if(e==null)n=new r(0,0,this.getLength(),0),t==null&&(t=!0);else if(typeof e==\"number\")n=new r(e,0,e,this.getLine(e).length);else if(\"row\"in e)n=r.fromPoints(e,e);else{if(Array.isArray(e))return i=[],e.forEach(function(e){i=i.concat(this.unfold(e))},this),i;n=e}i=this.getFoldsInRangeList(n);var s=i;while(i.length==1&&r.comparePoints(i[0].start,n.start)<0&&r.comparePoints(i[0].end,n.end)>0)this.expandFolds(i),i=this.getFoldsInRangeList(n);t!=0?this.removeFolds(i):this.expandFolds(i);if(s.length)return s},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o=\"\";return e.walk(function(e,t,n,u){if(t<r)return;if(t==r){if(n<i)return;u=Math.max(i,u)}e!=null?o+=e:o+=s.getLine(t).substring(u,n)},t,n),o},this.getDisplayLine=function(e,t,n,r){var i=this.getFoldLine(e);if(!i){var s;return s=this.doc.getLine(e),s.substring(r||0,t||s.length)}return this.getFoldDisplayLine(i,e,t,n,r)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var n=t.folds.map(function(e){return e.clone()});return new i(e,n)}),e},this.toggleFold=function(e){var t=this.selection,n=t.getRange(),r,i;if(n.isEmpty()){var s=n.start;r=this.getFoldAt(s.row,s.column);if(r){this.expandFold(r);return}(i=this.findMatchingBracket(s))?n.comparePoint(i)==1?n.end=i:(n.start=i,n.start.column++,n.end.column--):(i=this.findMatchingBracket({row:s.row,column:s.column+1}))?(n.comparePoint(i)==1?n.end=i:n.start=i,n.start.column++):n=this.getCommentFoldRange(s.row,s.column)||n}else{var o=this.getFoldsInRange(n);if(e&&o.length){this.expandFolds(o);return}o.length==1&&(r=o[0])}r||(r=this.getFoldAt(n.start.row,n.start.column));if(r&&r.range.toString()==n.toString()){this.expandFold(r);return}var u=\"...\";if(!n.isMultiLine()){u=this.getTextRange(n);if(u.length<4)return;u=u.trim().substring(0,2)+\"..\"}this.addFold(u,n)},this.getCommentFoldRange=function(e,t,n){var i=new o(this,e,t),s=i.getCurrentToken(),u=s&&s.type;if(s&&/^comment|string/.test(u)){u=u.match(/comment|string/)[0],u==\"comment\"&&(u+=\"|doc-start|\\\\.doc\");var a=new RegExp(u),f=new r;if(n!=1){do s=i.stepBackward();while(s&&a.test(s.type)&&!/^comment.end/.test(s.type));s=i.stepForward()}f.start.row=i.getCurrentTokenRow(),f.start.column=i.getCurrentTokenColumn()+(/^comment.start/.test(s.type)?s.value.length:2),i=new o(this,e,t);if(n!=-1){var l=-1;do{s=i.stepForward();if(l==-1){var c=this.getState(i.$row);a.test(c)||(l=i.$row)}else if(i.$row>l)break}while(s&&a.test(s.type)&&!/^comment.start/.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return f.end.row=i.getCurrentTokenRow(),f.end.column=i.getCurrentTokenColumn(),/^comment.end/.test(s.type)||(f.end.column+=s.value.length-2),f}},this.foldAll=function(e,t,n,r){n==undefined&&(n=1e5);var i=this.foldWidgets;if(!i)return;t=t||this.getLength(),e=e||0;for(var s=e;s<t;s++){i[s]==null&&(i[s]=this.getFoldWidget(s));if(i[s]!=\"start\")continue;if(r&&!r(s))continue;var o=this.getFoldWidgetRange(s);o&&o.isMultiLine()&&o.end.row<=t&&o.start.row>=e&&(s=o.end.row,o.collapseChildren=n,this.addFold(\"...\",o))}},this.foldToLevel=function(e){this.foldAll();while(e-->0)this.unfold(null,!1)},this.foldAllComments=function(){var e=this;this.foldAll(null,null,null,function(t){var n=e.getTokens(t);for(var r=0;r<n.length;r++){var i=n[r];if(i.type==\"text\"&&/^\\s+$/.test(i.value))continue;return/comment/.test(i.type)?!0:!1}})},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle=\"markbegin\",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error(\"invalid fold style: \"+e+\"[\"+Object.keys(this.$foldStyles).join(\", \")+\"]\");if(this.$foldStyle==e)return;this.$foldStyle=e,e==\"manual\"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off(\"change\",this.$updateFoldWidgets),this.off(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets),this._signal(\"changeAnnotation\");if(!e||this.$foldStyle==\"manual\"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on(\"change\",this.$updateFoldWidgets),this.on(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s==\"start\"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t instanceof u&&(t=t.domEvent);var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=\" ace_invalid\")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n===\"end\"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold(\"...\",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold(\"...\",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action==\"remove\")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e(\"../range\").Range,i=e(\"./fold_line\").FoldLine,s=e(\"./fold\").Fold,o=e(\"../token_iterator\").TokenIterator,u=e(\"../mouse/mouse_event\").MouseEvent;t.Folding=a}),define(\"ace/edit_session/bracket_match\",[\"require\",\"exports\",\"module\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n==\"\")return null;var r=n.match(/([\\(\\[\\{])|([\\)\\]\\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.getMatchingBracketRanges=function(e,t){var n=this.getLine(e.row),r=/([\\(\\[\\{])|([\\)\\]\\}])/,s=!t&&n.charAt(e.column-1),o=s&&s.match(r);o||(s=(t===undefined||t)&&n.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(r));if(!o)return null;var u=new i(e.row,e.column-1,e.row,e.column),a=o[1]?this.$findClosingBracket(o[1],e):this.$findOpeningBracket(o[2],e);if(!a)return[u];var f=new i(a.row,a.column,a.row,a.column+1);return[u,f]},this.$brackets={\")\":\"(\",\"(\":\")\",\"]\":\"[\",\"[\":\"]\",\"{\":\"}\",\"}\":\"{\",\"<\":\">\",\">\":\"<\"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"rparen\",\".paren\").replace(/\\b(?:end)\\b/,\"(?:start|begin|end)\").replace(/-close\\b/,\"-(close|open)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"lparen\",\".paren\").replace(/\\b(?:start|begin)\\b/,\"(?:start|begin|end)\").replace(/-open\\b/,\"-(close|open)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a<l){var c=f.charAt(a);if(c==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else c==e&&(s+=1);a+=1}do u=o.stepForward();while(u&&!n.test(u.type));if(u==null)break;a=0}return null},this.getMatchingTags=function(e){var t=new r(this,e.row,e.column),n=this.$findTagName(t);if(!n)return;var i=t.stepBackward();return i.value===\"<\"?this.$findClosingTag(t,n):this.$findOpeningTag(t,n)},this.$findTagName=function(e){var t=e.getCurrentToken(),n=!1,r=!1;if(t&&t.type.indexOf(\"tag-name\")===-1)do r?t=e.stepBackward():t=e.stepForward(),t&&(t.value===\"/>\"?r=!0:t.type.indexOf(\"tag-name\")!==-1&&(n=!0));while(t&&!n);return t},this.$findClosingTag=function(e,t){var n,r=t.value,s=t.value,o=0,u=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1);t=e.stepForward();var a=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+t.value.length),f=!1;do{n=t,t=e.stepForward();if(t){if(t.value===\">\"&&!f){var l=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1);f=!0}if(t.type.indexOf(\"tag-name\")!==-1){r=t.value;if(s===r)if(n.value===\"<\")o++;else if(n.value===\"</\"){o--;if(o<0){e.stepBackward();var c=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+2);t=e.stepForward();var h=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+t.value.length);t=e.stepForward();if(!t||t.value!==\">\")return;var p=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1)}}}else if(s===r&&t.value===\"/>\"){o--;if(o<0)var c=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+2),h=c,p=h,l=new i(a.end.row,a.end.column,a.end.row,a.end.column+1)}}}while(t&&o>=0);if(u&&l&&c&&p&&a&&h)return{openTag:new i(u.start.row,u.start.column,l.end.row,l.end.column),closeTag:new i(c.start.row,c.start.column,p.end.row,p.end.column),openTagName:a,closeTagName:h}},this.$findOpeningTag=function(e,t){var n=e.getCurrentToken(),r=t.value,s=0,o=e.getCurrentTokenRow(),u=e.getCurrentTokenColumn(),a=u+2,f=new i(o,u,o,a);e.stepForward();var l=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+t.value.length);t=e.stepForward();if(!t||t.value!==\">\")return;var c=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1);e.stepBackward(),e.stepBackward();do{t=n,o=e.getCurrentTokenRow(),u=e.getCurrentTokenColumn(),a=u+t.value.length,n=e.stepBackward();if(t)if(t.type.indexOf(\"tag-name\")!==-1){if(r===t.value)if(n.value===\"<\"){s++;if(s>0){var h=new i(o,u,o,a),p=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1);do t=e.stepForward();while(t&&t.value!==\">\");var d=new i(e.getCurrentTokenRow(),e.getCurrentTokenColumn(),e.getCurrentTokenRow(),e.getCurrentTokenColumn()+1)}}else n.value===\"</\"&&s--}else if(t.value===\"/>\"){var v=0,m=n;while(m){if(m.type.indexOf(\"tag-name\")!==-1&&m.value===r){s--;break}if(m.value===\"<\")break;m=e.stepBackward(),v++}for(var g=0;g<v;g++)e.stepForward()}}while(n&&s<=0);if(p&&d&&f&&c&&h&&l)return{openTag:new i(p.start.row,p.start.column,d.end.row,d.end.column),closeTag:new i(f.start.row,f.start.column,c.end.row,c.end.column),openTagName:h,closeTagName:l}}}var r=e(\"../token_iterator\").TokenIterator,i=e(\"../range\").Range;t.BracketMatch=s}),define(\"ace/edit_session\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/bidihandler\",\"ace/config\",\"ace/lib/event_emitter\",\"ace/selection\",\"ace/mode/text\",\"ace/range\",\"ace/document\",\"ace/background_tokenizer\",\"ace/search_highlight\",\"ace/edit_session/folding\",\"ace/edit_session/bracket_match\"],function(e,t,n){\"use strict\";function x(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./bidihandler\").BidiHandler,o=e(\"./config\"),u=e(\"./lib/event_emitter\").EventEmitter,a=e(\"./selection\").Selection,f=e(\"./mode/text\").Mode,l=e(\"./range\").Range,c=e(\"./document\").Document,h=e(\"./background_tokenizer\").BackgroundTokenizer,p=e(\"./search_highlight\").SearchHighlight,d=function(){function e(t,n){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.id=\"session\"+ ++e.$uid,this.$foldData.toString=function(){return this.join(\"\\n\")},this.bgTokenizer=new h((new f).getTokenizer(),this);var r=this;this.bgTokenizer.on(\"update\",function(e){r._signal(\"tokenizerUpdate\",e)}),this.on(\"changeFold\",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof t!=\"object\"||!t.getLine)t=new c(t);this.setDocument(t),this.selection=new a(this),this.$bidiHandler=new s(this),o.resetOptions(this),this.setMode(n),o._signal(\"session\",this),this.destroyed=!1}return e.prototype.setDocument=function(e){this.doc&&this.doc.off(\"change\",this.$onChange),this.doc=e,e.on(\"change\",this.$onChange,!0),this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},e.prototype.getDocument=function(){return this.doc},e.prototype.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},e.prototype.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t<s))return i;r=i-1}}return n-1},e.prototype.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.destroyed||this.bgTokenizer.start(0)},e.prototype.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},e.prototype.onChange=function(e){this.$modified=!0,this.$bidiHandler.onChange(e),this.$resetRowCache(e.start.row);var t=this.$updateInternalDataOnChange(e);!this.$fromUndo&&this.$undoManager&&(t&&t.length&&(this.$undoManager.add({action:\"removeFolds\",folds:t},this.mergeUndoDeltas),this.mergeUndoDeltas=!0),this.$undoManager.add(e,this.mergeUndoDeltas),this.mergeUndoDeltas=!0,this.$informUndoManager.schedule()),this.bgTokenizer.$updateOnChange(e),this._signal(\"change\",e)},e.prototype.setValue=function(e){this.doc.setValue(e),this.selection.moveTo(0,0),this.$resetRowCache(0),this.setUndoManager(this.$undoManager),this.getUndoManager().reset()},e.prototype.toString=function(){return this.doc.getValue()},e.prototype.getSelection=function(){return this.selection},e.prototype.getState=function(e){return this.bgTokenizer.getState(e)},e.prototype.getTokens=function(e){return this.bgTokenizer.getTokens(e)},e.prototype.getTokenAt=function(e,t){var n=this.bgTokenizer.getTokens(e),r,i=0;if(t==null){var s=n.length-1;i=this.getLine(e).length}else for(var s=0;s<n.length;s++){i+=n[s].value.length;if(i>=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},e.prototype.setUndoManager=function(e){this.$undoManager=e,this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;e.addSession(this),this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.mergeUndoDeltas=!1},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}else this.$syncInformUndoManager=function(){}},e.prototype.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},e.prototype.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},e.prototype.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(\" \",this.getTabSize()):\"\t\"},e.prototype.setUseSoftTabs=function(e){this.setOption(\"useSoftTabs\",e)},e.prototype.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},e.prototype.setTabSize=function(e){this.setOption(\"tabSize\",e)},e.prototype.getTabSize=function(){return this.$tabSize},e.prototype.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},e.prototype.setNavigateWithinSoftTabs=function(e){this.setOption(\"navigateWithinSoftTabs\",e)},e.prototype.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},e.prototype.setOverwrite=function(e){this.setOption(\"overwrite\",e)},e.prototype.getOverwrite=function(){return this.$overwrite},e.prototype.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},e.prototype.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=\"\"),this.$decorations[e]+=\" \"+t,this._signal(\"changeBreakpoint\",{})},e.prototype.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||\"\").replace(\" \"+t,\"\"),this._signal(\"changeBreakpoint\",{})},e.prototype.getBreakpoints=function(){return this.$breakpoints},e.prototype.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t<e.length;t++)this.$breakpoints[e[t]]=\"ace_breakpoint\";this._signal(\"changeBreakpoint\",{})},e.prototype.clearBreakpoints=function(){this.$breakpoints=[],this._signal(\"changeBreakpoint\",{})},e.prototype.setBreakpoint=function(e,t){t===undefined&&(t=\"ace_breakpoint\"),t?this.$breakpoints[e]=t:delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},e.prototype.clearBreakpoint=function(e){delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},e.prototype.addMarker=function(e,t,n,r){var i=this.$markerId++,s={range:e,type:n||\"line\",renderer:typeof n==\"function\"?n:null,clazz:t,inFront:!!r,id:i};return r?(this.$frontMarkers[i]=s,this._signal(\"changeFrontMarker\")):(this.$backMarkers[i]=s,this._signal(\"changeBackMarker\")),i},e.prototype.addDynamicMarker=function(e,t){if(!e.update)return;var n=this.$markerId++;return e.id=n,e.inFront=!!t,t?(this.$frontMarkers[n]=e,this._signal(\"changeFrontMarker\")):(this.$backMarkers[n]=e,this._signal(\"changeBackMarker\")),e},e.prototype.removeMarker=function(e){var t=this.$frontMarkers[e]||this.$backMarkers[e];if(!t)return;var n=t.inFront?this.$frontMarkers:this.$backMarkers;delete n[e],this._signal(t.inFront?\"changeFrontMarker\":\"changeBackMarker\")},e.prototype.getMarkers=function(e){return e?this.$frontMarkers:this.$backMarkers},e.prototype.highlight=function(e){if(!this.$searchHighlight){var t=new p(null,\"ace_selected-word\",\"text\");this.$searchHighlight=this.addDynamicMarker(t)}this.$searchHighlight.setRegexp(e)},e.prototype.highlightLines=function(e,t,n,r){typeof t!=\"number\"&&(n=t,t=e),n||(n=\"ace_step\");var i=new l(e,0,t,Infinity);return i.id=this.addMarker(i,n,\"fullLine\",r),i},e.prototype.setAnnotations=function(e){this.$annotations=e,this._signal(\"changeAnnotation\",{})},e.prototype.getAnnotations=function(){return this.$annotations||[]},e.prototype.clearAnnotations=function(){this.setAnnotations([])},e.prototype.$detectNewLine=function(e){var t=e.match(/^.*?(\\r?\\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine=\"\\n\"},e.prototype.getWordRange=function(e,t){var n=this.getLine(e),r=!1;t>0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\\s+$/.test(n.slice(t-1,t+1)))var i=/\\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(o<n.length&&n.charAt(o).match(i))o++;return new l(e,s,e,o)},e.prototype.getAWordRange=function(e,t){var n=this.getWordRange(e,t),r=this.getLine(n.end.row);while(r.charAt(n.end.column).match(/[ \\t]/))n.end.column+=1;return n},e.prototype.setNewLineMode=function(e){this.doc.setNewLineMode(e)},e.prototype.getNewLineMode=function(){return this.doc.getNewLineMode()},e.prototype.setUseWorker=function(e){this.setOption(\"useWorker\",e)},e.prototype.getUseWorker=function(){return this.$useWorker},e.prototype.onReloadTokenizer=function(e){var t=e.data;this.bgTokenizer.start(t.first),this._signal(\"tokenizerUpdate\",e)},e.prototype.setMode=function(e,t){if(e&&typeof e==\"object\"){if(e.getTokenizer)return this.$onChangeMode(e);var n=e,r=n.path}else r=e||\"ace/mode/text\";this.$modes[\"ace/mode/text\"]||(this.$modes[\"ace/mode/text\"]=new f);if(this.$modes[r]&&!n){this.$onChangeMode(this.$modes[r]),t&&t();return}this.$modeId=r,o.loadModule([\"mode\",r],function(e){if(this.$modeId!==r)return t&&t();this.$modes[r]&&!n?this.$onChangeMode(this.$modes[r]):e&&e.Mode&&(e=new e.Mode(n),n||(this.$modes[r]=e,e.$id=r),this.$onChangeMode(e)),t&&t()}.bind(this)),this.$mode||this.$onChangeMode(this.$modes[\"ace/mode/text\"],!0)},e.prototype.$onChangeMode=function(e,t){t||(this.$modeId=e.$id);if(this.$mode===e)return;var n=this.$mode;this.$mode=e,this.$stopWorker(),this.$useWorker&&this.$startWorker();var r=e.getTokenizer();if(r.on!==undefined){var i=this.onReloadTokenizer.bind(this);r.on(\"update\",i)}this.bgTokenizer.setTokenizer(r),this.bgTokenizer.setDocument(this.getDocument()),this.tokenRe=e.tokenRe,this.nonTokenRe=e.nonTokenRe,t||(e.attachToSession&&e.attachToSession(this),this.$options.wrapMethod.set.call(this,this.$wrapMethod),this.$setFolding(e.foldingRules),this.bgTokenizer.start(0),this._emit(\"changeMode\",{oldMode:n,mode:e}))},e.prototype.$stopWorker=function(){this.$worker&&(this.$worker.terminate(),this.$worker=null)},e.prototype.$startWorker=function(){try{this.$worker=this.$mode.createWorker(this)}catch(e){o.warn(\"Could not load worker\",e),this.$worker=null}},e.prototype.getMode=function(){return this.$mode},e.prototype.setScrollTop=function(e){if(this.$scrollTop===e||isNaN(e))return;this.$scrollTop=e,this._signal(\"changeScrollTop\",e)},e.prototype.getScrollTop=function(){return this.$scrollTop},e.prototype.setScrollLeft=function(e){if(this.$scrollLeft===e||isNaN(e))return;this.$scrollLeft=e,this._signal(\"changeScrollLeft\",e)},e.prototype.getScrollLeft=function(){return this.$scrollLeft},e.prototype.getScreenWidth=function(){return this.$computeWidth(),this.lineWidgets?Math.max(this.getLineWidgetMaxWidth(),this.screenWidth):this.screenWidth},e.prototype.getLineWidgetMaxWidth=function(){if(this.lineWidgetsWidth!=null)return this.lineWidgetsWidth;var e=0;return this.lineWidgets.forEach(function(t){t&&t.screenWidth>e&&(e=t.screenWidth)}),this.lineWidgetWidth=e},e.prototype.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;a<u;a++){if(a>o){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},e.prototype.getLine=function(e){return this.doc.getLine(e)},e.prototype.getLines=function(e,t){return this.doc.getLines(e,t)},e.prototype.getLength=function(){return this.doc.getLength()},e.prototype.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},e.prototype.insert=function(e,t){return this.doc.insert(e,t)},e.prototype.remove=function(e){return this.doc.remove(e)},e.prototype.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},e.prototype.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;for(var n=e.length-1;n!=-1;n--){var r=e[n];r.action==\"insert\"||r.action==\"remove\"?this.doc.revertDelta(r):r.folds&&this.addFolds(r.folds)}!t&&this.$undoSelect&&(e.selectionBefore?this.selection.fromJSON(e.selectionBefore):this.selection.setRange(this.$getUndoSelection(e,!0))),this.$fromUndo=!1},e.prototype.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;for(var n=0;n<e.length;n++){var r=e[n];(r.action==\"insert\"||r.action==\"remove\")&&this.doc.$safeApplyDelta(r)}!t&&this.$undoSelect&&(e.selectionAfter?this.selection.fromJSON(e.selectionAfter):this.selection.setRange(this.$getUndoSelection(e,!1))),this.$fromUndo=!1},e.prototype.setUndoSelect=function(e){this.$undoSelect=e},e.prototype.$getUndoSelection=function(e,t){function n(e){return t?e.action!==\"insert\":e.action===\"insert\"}var r,i;for(var s=0;s<e.length;s++){var o=e[s];if(!o.start)continue;if(!r){n(o)?r=l.fromPoints(o.start,o.end):r=l.fromPoints(o.start,o.start);continue}n(o)?(i=o.start,r.compare(i.row,i.column)==-1&&r.setStart(i),i=o.end,r.compare(i.row,i.column)==1&&r.setEnd(i)):(i=o.start,r.compare(i.row,i.column)==-1&&(r=l.fromPoints(o.start,o.start)))}return r},e.prototype.replace=function(e,t){return this.doc.replace(e,t)},e.prototype.moveText=function(e,t,n){var r=this.getTextRange(e),i=this.getFoldsInRange(e),s=l.fromPoints(t,t);if(!n){this.remove(e);var o=e.start.row-e.end.row,u=o?-e.end.column:e.start.column-e.end.column;u&&(s.start.row==e.end.row&&s.start.column>e.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,f=s.start,o=f.row-a.row,u=f.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},e.prototype.indentRows=function(e,t,n){n=n.replace(/\\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},e.prototype.outdentRows=function(e){var t=e.collapseRows(),n=new l(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o<r;++o)if(s.charAt(o)!=\" \")break;o<r&&s.charAt(o)==\"\t\"?(n.start.column=o,n.end.column=o+1):(n.start.column=0,n.end.column=o),this.remove(n)}},e.prototype.$moveLines=function(e,t,n){e=this.getRowFoldStart(e),t=this.getRowFoldEnd(t);if(n<0){var r=this.getRowFoldStart(e+n);if(r<0)return 0;var i=r-e}else if(n>0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new l(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},e.prototype.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},e.prototype.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},e.prototype.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},e.prototype.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},e.prototype.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},e.prototype.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},e.prototype.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},e.prototype.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal(\"changeWrapMode\")}},e.prototype.getUseWrapMode=function(){return this.$useWrapMode},e.prototype.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$bidiHandler.markAsDirty(),this.$useWrapMode&&this._signal(\"changeWrapMode\")},e.prototype.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal(\"changeWrapLimit\")),!0):!1},e.prototype.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},e.prototype.getWrapLimit=function(){return this.$wrapLimit},e.prototype.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},e.prototype.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},e.prototype.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n===\"remove\"){this[t?\"$wrapData\":\"$rowLengthCache\"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n===\"remove\"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error(\"doc.getLength() and $wrapData.length have to be the same!\"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},e.prototype.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},e.prototype.$updateWrapData=function(e,t){var n=this.doc.getAllLines(),r=this.getTabSize(),i=this.$wrapData,s=this.$wrapLimit,o,u,a=e;t=Math.min(t,n.length-1);while(a<=t)u=this.getFoldLine(a,u),u?(o=[],u.walk(function(e,t,r,i){var s;if(e!=null){s=this.$getDisplayTokens(e,o.length),s[0]=g;for(var u=1;u<s.length;u++)s[u]=y}else s=this.$getDisplayTokens(n[t].substring(i,r),o.length);o=o.concat(s)}.bind(this),u.end.row,n[u.end.row].length+1),i[u.start.row]=this.$computeWrapSplits(o,s,r),a=u.end.row+1):(o=this.$getDisplayTokens(n[a]),i[a]=this.$computeWrapSplits(o,s,r),a++)},e.prototype.$computeWrapSplits=function(e,t,n){function l(){var t=0;if(f===0)return t;if(a)for(var r=0;r<e.length;r++){var i=e[r];if(i==w)t+=1;else{if(i!=E){if(i==S)continue;break}t+=n}}return u&&a!==!1&&(t+=n),Math.min(t,f)}function c(t){var n=t-s;for(var i=s;i<t;i++){var u=e[i];if(u===12||u===2)n-=1}r.length||(h=l(),r.indent=h),o+=n,r.push(o),s=t}if(e.length==0)return[];var r=[],i=e.length,s=0,o=0,u=this.$wrapAsCode,a=this.$indentedSoftWrap,f=t<=Math.max(2*n,8)||a===!1?0:Math.floor(t/2),h=0;while(i-s>t-h){var p=s+t-h;if(e[p-1]>=w&&e[p]>=w){c(p);continue}if(e[p]==g||e[p]==y){for(p;p!=s-1;p--)if(e[p]==g)break;if(p>s){c(p);continue}p=s+t;for(p;p<e.length;p++)if(e[p]!=y)break;if(p==e.length)break;c(p);continue}var d=Math.max(p-(t-(t>>2)),s-1);while(p>d&&e[p]<g)p--;if(u){while(p>d&&e[p]<g)p--;while(p>d&&e[p]==b)p--}else while(p>d&&e[p]<w)p--;if(p>d){c(++p);continue}p=s+t,e[p]==m&&p--,c(p-h)}return r},e.prototype.$getDisplayTokens=function(e,t){var n=[],r;t=t||0;for(var i=0;i<e.length;i++){var s=e.charCodeAt(i);if(s==9){r=this.getScreenTabSize(n.length+t),n.push(E);for(var o=1;o<r;o++)n.push(S)}else s==32?n.push(w):s>39&&s<48||s>57&&s<64?n.push(b):s>=4352&&x(s)?n.push(v,m):n.push(v)}return n},e.prototype.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i<e.length;i++){r=e.charCodeAt(i),r==9?n+=this.getScreenTabSize(n):r>=4352&&x(r)?n+=2:n+=1;if(n>t)break}return[n,i]},e.prototype.getRowLength=function(e){var t=1;return this.lineWidgets&&(t+=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0),!this.$useWrapMode||!this.$wrapData[e]?t:this.$wrapData[e].length+t},e.prototype.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},e.prototype.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]<t.column?n.indent:0}return 0},e.prototype.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},e.prototype.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},e.prototype.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},e.prototype.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},e.prototype.getScreenTabSize=function(e){return this.$tabSize-(e%this.$tabSize|0)},e.prototype.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},e.prototype.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},e.prototype.screenToDocumentPosition=function(e,t,n){if(e<0)return{row:0,column:0};var r,i=0,s=0,o,u=0,a=0,f=this.$screenRowCache,l=this.$getRowCacheIndex(f,e),c=f.length;if(c&&l>=0)var u=f[l],i=this.$docRowCache[l],h=e>f[c-1];else var h=!c;var p=this.getLength()-1,d=this.getNextFoldLine(i),v=d?d.start.row:Infinity;while(u<=e){a=this.getRowLength(i);if(u+a>e||i>=p)break;u+=a,i++,i>v&&(i=d.end.row+1,d=this.getNextFoldLine(i,d),v=d?d.start.row:Infinity),h&&(this.$docRowCache.push(i),this.$screenRowCache.push(u))}if(d&&d.start.row<=i)r=this.getFoldDisplayLine(d),i=d.start.row;else{if(u+a<=e||i>p)return{row:p,column:this.getLine(p).length};r=this.getLine(i),d=null}var m=0,g=Math.floor(e-u);if(this.$useWrapMode){var y=this.$wrapData[i];y&&(o=y[g],g>0&&y.length&&(m=y.indent,s=y[g-1]||y[y.length-1],r=r.substring(s)))}return n!==undefined&&this.$bidiHandler.isBidiRow(u+g,i,g)&&(t=this.$bidiHandler.offsetToCol(n)),s+=this.$getStringScreenWidth(r,t-m)[1],this.$useWrapMode&&s>=o&&(s=o-1),d?d.idxToPosition(s):{row:i,column:s}},e.prototype.documentToScreenPosition=function(e,t){if(typeof t==\"undefined\")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u<e){if(u>=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d=\"\";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return this.lineWidgets&&this.lineWidgets[u]&&this.lineWidgets[u].rowsAbove&&(r+=this.lineWidgets[u].rowsAbove),{row:r,column:v+this.$getStringScreenWidth(d)[0]}},e.prototype.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},e.prototype.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},e.prototype.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;r<n.length;r++)t=n[r],e-=t.end.row-t.start.row}else{var i=this.$wrapData.length,s=0,r=0,t=this.$foldData[r++],o=t?t.start.row:Infinity;while(s<i){var u=this.$wrapData[s];e+=u?u.length+1:1,s++,s>o&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},e.prototype.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;s<t.length;s++){i=t.charAt(s),i===\"\t\"?r+=this.getScreenTabSize(r):r+=e.getCharacterWidth(i);if(r>n)break}return[r,s]}},e.prototype.destroy=function(){this.destroyed||(this.bgTokenizer.setDocument(null),this.bgTokenizer.cleanup(),this.destroyed=!0),this.$stopWorker(),this.removeAllListeners(),this.doc&&this.doc.off(\"change\",this.$onChange),this.selection.detach()},e}();d.$uid=0,d.prototype.$modes=o.$modes,d.prototype.getValue=d.prototype.toString,d.prototype.$defaultUndoManager={undo:function(){},redo:function(){},hasUndo:function(){},hasRedo:function(){},reset:function(){},add:function(){},addSelection:function(){},startNewGroup:function(){},addSession:function(){}},d.prototype.$overwrite=!1,d.prototype.$mode=null,d.prototype.$modeId=null,d.prototype.$scrollTop=0,d.prototype.$scrollLeft=0,d.prototype.$wrapLimit=80,d.prototype.$useWrapMode=!1,d.prototype.$wrapLimitRange={min:null,max:null},d.prototype.lineWidgets=null,d.prototype.isFullWidth=x,r.implement(d.prototype,u);var v=1,m=2,g=3,y=4,b=9,w=10,E=11,S=12;e(\"./edit_session/folding\").Folding.call(d.prototype),e(\"./edit_session/bracket_match\").BracketMatch.call(d.prototype),o.defineOptions(d.prototype,\"session\",{wrap:{set:function(e){!e||e==\"off\"?e=!1:e==\"free\"?e=!0:e==\"printMargin\"?e=-1:typeof e==\"string\"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e==\"number\"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?\"printMargin\":this.getWrapLimitRange().min?this.$wrap:\"free\":\"off\"},handlesSet:!0},wrapMethod:{set:function(e){e=e==\"auto\"?this.$mode.type!=\"text\":e!=\"text\",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0)))},initialValue:\"auto\"},indentedSoftWrap:{set:function(){this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0))},initialValue:!0},firstLineNumber:{set:function(){this._signal(\"changeBreakpoint\")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){e=parseInt(e),e>0&&this.$tabSize!==e&&(this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal(\"changeTabSize\"))},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},foldStyle:{set:function(e){this.setFoldStyle(e)},handlesSet:!0},overwrite:{set:function(e){this._signal(\"changeOverwrite\")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId},handlesSet:!0}}),t.EditSession=d}),define(\"ace/search\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(e,t,n){\"use strict\";function u(e,t){function n(e){return/\\w/.test(e)||t.regExp?\"\\\\b\":\"\"}return n(e[0])+e+n(e[e.length-1])}var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./range\").Range,o=function(){function e(){this.$options={}}return e.prototype.set=function(e){return i.mixin(this.$options,e),this},e.prototype.getOptions=function(){return r.copyObject(this.$options)},e.prototype.setOptions=function(e){this.$options=e},e.prototype.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i,o){return r=new s(e,n,i,o),n==o&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start)?(r=null,!1):!0}),r},e.prototype.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;h<a;h++)if(i[c+h].search(u[h])==-1)continue e;var p=i[c],d=i[c+a-1],v=p.length-p.match(u[0])[0].length,m=d.match(u[a-1])[0].length;if(l&&l.end.row===c&&l.end.column>v)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;g<i.length;g++){var y=r.getMatchOffsets(i[g],u);for(var h=0;h<y.length;h++){var b=y[h];o.push(new s(g,b.offset,g,b.offset+b.length))}}if(n){var w=n.start.column,E=n.end.column,g=0,h=o.length-1;while(g<h&&o[g].start.column<w&&o[g].start.row==0)g++;var S=n.end.row-n.start.row;while(g<h&&o[h].end.column>E&&o[h].end.row==S)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g<h;g++)o[g].start.row+=n.start.row,o[g].end.row+=n.start.row}return o},e.prototype.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split(\"\");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join(\"\")}return t},e.prototype.$assembleRegExp=function(e,t){if(e.needle instanceof RegExp)return e.re=e.needle;var n=e.needle;if(!e.needle)return e.re=!1;e.regExp||(n=r.escapeRegExp(n)),e.wholeWord&&(n=u(n,e));var i=e.caseSensitive?\"gm\":\"gmi\";e.$isMultiLine=!t&&/[\\n\\r]/.test(n);if(e.$isMultiLine)return e.re=this.$assembleMultilineRegExp(n,i);try{var s=new RegExp(n,i)}catch(o){s=!1}return e.re=s},e.prototype.$assembleMultilineRegExp=function(e,t){var n=e.replace(/\\r\\n|\\r|\\n/g,\"$\\n^\").split(\"\\n\"),r=[];for(var i=0;i<n.length;i++)try{r.push(new RegExp(n[i],t))}catch(s){return!1}return r},e.prototype.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var r=t.backwards==1,i=t.skipCurrent!=0,s=t.range,o=t.start;o||(o=s?s[r?\"end\":\"start\"]:e.selection.getRange()),o.start&&(o=o[i!=r?\"end\":\"start\"]);var u=s?s.start.row:0,a=s?s.end.row:e.getLength()-1;if(r)var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n--;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return;if(t.wrap==0)return;for(n=a,u=o.row;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return};else var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n+=1;n<=a;n++)if(c(n,0,e))return;if(t.wrap==0)return;for(n=u,a=o.row;n<=a;n++)if(c(n,0,e))return};if(t.$isMultiLine)var l=n.length,c=function(t,i,s){var o=r?t-l+1:t;if(o<0||o+l>e.getLength())return;var u=e.getLine(o),a=u.search(n[0]);if(!r&&a<i||a===-1)return;for(var f=1;f<l;f++){u=e.getLine(o+f);if(u.search(n[f])==-1)return}var c=u.match(n[l-1])[0].length;if(r&&c>i)return;if(s(o,a,o+l-1,c))return!0};else if(r)var c=function(t,r,i){var s=e.getLine(t),o=[],u,a=0;n.lastIndex=0;while(u=n.exec(s)){var f=u[0].length;a=u.index;if(!f){if(a>=s.length)break;n.lastIndex=a+=1}if(u.index+f>r)break;o.push(u.index,f)}for(var l=o.length-1;l>=0;l-=2){var c=o[l-1],f=o[l];if(i(t,c,t,c+f))return!0}};else var c=function(t,r,i){var s=e.getLine(t),o,u;n.lastIndex=r;while(u=n.exec(s)){var a=u[0].length;o=u.index;if(i(t,o,t,o+a))return!0;if(!a){n.lastIndex=o+=1;if(o>=s.length)return!1}}};return{forEach:f}},e}();t.Search=o}),define(\"ace/keyboard/hash_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function a(e){return typeof e==\"object\"&&e.bindKey&&e.bindKey.position||(e.isDefault?-100:0)}var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=e(\"../lib/keys\"),s=e(\"../lib/useragent\"),o=i.KEY_MODS,u=function(){function e(e,t){this.$init(e,t,!1)}return e.prototype.$init=function(e,t,n){this.platform=t||(s.isMac?\"mac\":\"win\"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=n},e.prototype.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},e.prototype.removeCommand=function(e,t){var n=e&&(typeof e==\"string\"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},e.prototype.bindKey=function(e,t,n){typeof e==\"object\"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t==\"function\")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split(\"|\").forEach(function(e){var r=\"\";if(e.indexOf(\" \")!=-1){var i=e.split(/\\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=o[t.hashId]+t.key;r+=(r?\" \":\"\")+n,this._addCommandToBinding(r,\"chainKeys\")},this),r+=\" \"}var s=this.parseKeys(e),u=o[s.hashId]+s.key;this._addCommandToBinding(r+u,t,n)},this)},e.prototype._addCommandToBinding=function(e,t,n){var r=this.commandKeyBinding,i;if(!t)delete r[e];else if(!r[e]||this.$singleCommand)r[e]=t;else{Array.isArray(r[e])?(i=r[e].indexOf(t))!=-1&&r[e].splice(i,1):r[e]=[r[e]],typeof n!=\"number\"&&(n=a(t));var s=r[e];for(i=0;i<s.length;i++){var o=s[i],u=a(o);if(u>n)break}s.splice(i,0,t)}},e.prototype.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n==\"string\")return this.bindKey(n,t);typeof n==\"function\"&&(n={exec:n});if(typeof n!=\"object\")return;n.name||(n.name=t),this.addCommand(n)},this)},e.prototype.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},e.prototype.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},e.prototype._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},e.prototype.parseKeys=function(e){var t=e.toLowerCase().split(/[\\-\\+]([\\-\\+])?/).filter(function(e){return e}),n=t.pop(),r=i[n];if(i.FUNCTION_KEYS[r])n=i.FUNCTION_KEYS[r].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]==\"shift\")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=i.KEY_MODS[t[o]];if(u==null)return typeof console!=\"undefined\"&&console.error(\"invalid modifier \"+t[o]+\" in \"+e),!1;s|=u}return{key:n,hashId:s}},e.prototype.findKeyCommand=function(e,t){var n=o[e]+t;return this.commandKeyBinding[n]},e.prototype.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=o[t]+n,s=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=\" \"+i,s=this.commandKeyBinding[e.$keyChain]||s);if(s)if(s==\"chainKeys\"||s[s.length-1]==\"chainKeys\")return e.$keyChain=e.$keyChain||i,{command:\"null\"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=\"\"}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:s}},e.prototype.getStatusText=function(e,t){return t.$keyChain||\"\"},e}(),f=function(e){function t(t,n){var r=e.call(this,t,n)||this;return r.$singleCommand=!0,r}return r(t,e),t}(u);f.call=function(e,t,n){u.prototype.$init.call(e,t,n,!0)},u.call=function(e,t,n){u.prototype.$init.call(e,t,n,!1)},t.HashHandler=f,t.MultiHashHandler=u}),define(\"ace/commands/command_manager\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/keyboard/hash_handler\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=e(\"../lib/oop\"),s=e(\"../keyboard/hash_handler\").MultiHashHandler,o=e(\"../lib/event_emitter\").EventEmitter,u=function(e){function t(t,n){var r=e.call(this,n,t)||this;return r.byName=r.commands,r.setDefaultHandler(\"exec\",function(e){return e.args?e.command.exec(e.editor,e.args,e.event,!1):e.command.exec(e.editor,{},e.event,!0)}),r}return r(t,e),t.prototype.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e==\"string\"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;if(this.$checkCommandState!=0&&e.isAvailable&&!e.isAvailable(t))return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit(\"exec\",i),this._signal(\"afterExec\",i),i.returnValue===!1?!1:!0},t.prototype.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit(\"changeStatus\"),this.recording?(this.macro.pop(),this.off(\"exec\",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on(\"exec\",this.$addCommandToMacro),this.recording=!0)},t.prototype.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t==\"string\"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},t.prototype.trimMacro=function(e){return e.map(function(e){return typeof e[0]!=\"string\"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})},t}(s);i.implement(u.prototype,o),t.CommandManager=u}),define(\"ace/commands/default_commands\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/config\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e,t){return{win:e,mac:t}}var r=e(\"../lib/lang\"),i=e(\"../config\"),s=e(\"../range\").Range;t.commands=[{name:\"showSettingsMenu\",description:\"Show settings menu\",bindKey:o(\"Ctrl-,\",\"Command-,\"),exec:function(e){i.loadModule(\"ace/ext/settings_menu\",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:\"goToNextError\",description:\"Go to next error\",bindKey:o(\"Alt-E\",\"F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"goToPreviousError\",description:\"Go to previous error\",bindKey:o(\"Alt-Shift-E\",\"Shift-F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"selectall\",description:\"Select all\",bindKey:o(\"Ctrl-A\",\"Command-A\"),exec:function(e){e.selectAll()},readOnly:!0},{name:\"centerselection\",description:\"Center selection\",bindKey:o(null,\"Ctrl-L\"),exec:function(e){e.centerSelection()},readOnly:!0},{name:\"gotoline\",description:\"Go to line...\",bindKey:o(\"Ctrl-L\",\"Command-L\"),exec:function(e,t){typeof t==\"number\"&&!isNaN(t)&&e.gotoLine(t),e.prompt({$type:\"gotoLine\"})},readOnly:!0},{name:\"fold\",bindKey:o(\"Alt-L|Ctrl-F1\",\"Command-Alt-L|Command-F1\"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"unfold\",bindKey:o(\"Alt-Shift-L|Ctrl-Shift-F1\",\"Command-Alt-Shift-L|Command-Shift-F1\"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleFoldWidget\",description:\"Toggle fold widget\",bindKey:o(\"F2\",\"F2\"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleParentFoldWidget\",description:\"Toggle parent fold widget\",bindKey:o(\"Alt-F2\",\"Alt-F2\"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"foldall\",description:\"Fold all\",bindKey:o(null,\"Ctrl-Command-Option-0\"),exec:function(e){e.session.foldAll()},scrollIntoView:\"center\",readOnly:!0},{name:\"foldAllComments\",description:\"Fold all comments\",bindKey:o(null,\"Ctrl-Command-Option-0\"),exec:function(e){e.session.foldAllComments()},scrollIntoView:\"center\",readOnly:!0},{name:\"foldOther\",description:\"Fold other\",bindKey:o(\"Alt-0\",\"Command-Option-0\"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:\"center\",readOnly:!0},{name:\"unfoldall\",description:\"Unfold all\",bindKey:o(\"Alt-Shift-0\",\"Command-Option-Shift-0\"),exec:function(e){e.session.unfold()},scrollIntoView:\"center\",readOnly:!0},{name:\"findnext\",description:\"Find next\",bindKey:o(\"Ctrl-K\",\"Command-G\"),exec:function(e){e.findNext()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"findprevious\",description:\"Find previous\",bindKey:o(\"Ctrl-Shift-K\",\"Command-Shift-G\"),exec:function(e){e.findPrevious()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"selectOrFindNext\",description:\"Select or find next\",bindKey:o(\"Alt-K\",\"Ctrl-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:\"selectOrFindPrevious\",description:\"Select or find previous\",bindKey:o(\"Alt-Shift-K\",\"Ctrl-Shift-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:\"find\",description:\"Find\",bindKey:o(\"Ctrl-F\",\"Command-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e)})},readOnly:!0},{name:\"overwrite\",description:\"Overwrite\",bindKey:\"Insert\",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:\"selecttostart\",description:\"Select to start\",bindKey:o(\"Ctrl-Shift-Home\",\"Command-Shift-Home|Command-Shift-Up\"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotostart\",description:\"Go to start\",bindKey:o(\"Ctrl-Home\",\"Command-Home|Command-Up\"),exec:function(e){e.navigateFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectup\",description:\"Select up\",bindKey:o(\"Shift-Up\",\"Shift-Up|Ctrl-Shift-P\"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golineup\",description:\"Go line up\",bindKey:o(\"Up\",\"Up|Ctrl-P\"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttoend\",description:\"Select to end\",bindKey:o(\"Ctrl-Shift-End\",\"Command-Shift-End|Command-Shift-Down\"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotoend\",description:\"Go to end\",bindKey:o(\"Ctrl-End\",\"Command-End|Command-Down\"),exec:function(e){e.navigateFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectdown\",description:\"Select down\",bindKey:o(\"Shift-Down\",\"Shift-Down|Ctrl-Shift-N\"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golinedown\",description:\"Go line down\",bindKey:o(\"Down\",\"Down|Ctrl-N\"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordleft\",description:\"Select word left\",bindKey:o(\"Ctrl-Shift-Left\",\"Option-Shift-Left\"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordleft\",description:\"Go to word left\",bindKey:o(\"Ctrl-Left\",\"Option-Left\"),exec:function(e){e.navigateWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolinestart\",description:\"Select to line start\",bindKey:o(\"Alt-Shift-Left\",\"Command-Shift-Left|Ctrl-Shift-A\"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolinestart\",description:\"Go to line start\",bindKey:o(\"Alt-Left|Home\",\"Command-Left|Home|Ctrl-A\"),exec:function(e){e.navigateLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectleft\",description:\"Select left\",bindKey:o(\"Shift-Left\",\"Shift-Left|Ctrl-Shift-B\"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoleft\",description:\"Go to left\",bindKey:o(\"Left\",\"Left|Ctrl-B\"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordright\",description:\"Select word right\",bindKey:o(\"Ctrl-Shift-Right\",\"Option-Shift-Right\"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordright\",description:\"Go to word right\",bindKey:o(\"Ctrl-Right\",\"Option-Right\"),exec:function(e){e.navigateWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolineend\",description:\"Select to line end\",bindKey:o(\"Alt-Shift-Right\",\"Command-Shift-Right|Shift-End|Ctrl-Shift-E\"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolineend\",description:\"Go to line end\",bindKey:o(\"Alt-Right|End\",\"Command-Right|End|Ctrl-E\"),exec:function(e){e.navigateLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectright\",description:\"Select right\",bindKey:o(\"Shift-Right\",\"Shift-Right\"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoright\",description:\"Go to right\",bindKey:o(\"Right\",\"Right|Ctrl-F\"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectpagedown\",description:\"Select page down\",bindKey:\"Shift-PageDown\",exec:function(e){e.selectPageDown()},readOnly:!0},{name:\"pagedown\",description:\"Page down\",bindKey:o(null,\"Option-PageDown\"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:\"gotopagedown\",description:\"Go to page down\",bindKey:o(\"PageDown\",\"PageDown|Ctrl-V\"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:\"selectpageup\",description:\"Select page up\",bindKey:\"Shift-PageUp\",exec:function(e){e.selectPageUp()},readOnly:!0},{name:\"pageup\",description:\"Page up\",bindKey:o(null,\"Option-PageUp\"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:\"gotopageup\",description:\"Go to page up\",bindKey:\"PageUp\",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:\"scrollup\",description:\"Scroll up\",bindKey:o(\"Ctrl-Up\",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"scrolldown\",description:\"Scroll down\",bindKey:o(\"Ctrl-Down\",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"selectlinestart\",description:\"Select line start\",bindKey:\"Shift-Home\",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectlineend\",description:\"Select line end\",bindKey:\"Shift-End\",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"togglerecording\",description:\"Toggle recording\",bindKey:o(\"Ctrl-Alt-E\",\"Command-Option-E\"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:\"replaymacro\",description:\"Replay macro\",bindKey:o(\"Ctrl-Shift-E\",\"Command-Shift-E\"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:\"jumptomatching\",description:\"Jump to matching\",bindKey:o(\"Ctrl-\\\\|Ctrl-P\",\"Command-\\\\\"),exec:function(e){e.jumpToMatching()},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"selecttomatching\",description:\"Select to matching\",bindKey:o(\"Ctrl-Shift-\\\\|Ctrl-Shift-P\",\"Command-Shift-\\\\\"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"expandToMatching\",description:\"Expand to matching\",bindKey:o(\"Ctrl-Shift-M\",\"Ctrl-Shift-M\"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"passKeysToBrowser\",description:\"Pass keys to browser\",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:\"copy\",description:\"Copy\",exec:function(e){},readOnly:!0},{name:\"cut\",description:\"Cut\",exec:function(e){var t=e.$copyWithEmptySelection&&e.selection.isEmpty(),n=t?e.selection.getLineRange():e.selection.getRange();e._emit(\"cut\",n),n.isEmpty()||e.session.remove(n),e.clearSelection()},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"paste\",description:\"Paste\",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:\"cursor\"},{name:\"removeline\",description:\"Remove line\",bindKey:o(\"Ctrl-D\",\"Command-D\"),exec:function(e){e.removeLines()},scrollIntoView:\"cursor\",multiSelectAction:\"forEachLine\"},{name:\"duplicateSelection\",description:\"Duplicate selection\",bindKey:o(\"Ctrl-Shift-D\",\"Command-Shift-D\"),exec:function(e){e.duplicateSelection()},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"sortlines\",description:\"Sort lines\",bindKey:o(\"Ctrl-Alt-S\",\"Command-Alt-S\"),exec:function(e){e.sortLines()},scrollIntoView:\"selection\",multiSelectAction:\"forEachLine\"},{name:\"togglecomment\",description:\"Toggle comment\",bindKey:o(\"Ctrl-/\",\"Command-/\"),exec:function(e){e.toggleCommentLines()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"toggleBlockComment\",description:\"Toggle block comment\",bindKey:o(\"Ctrl-Shift-/\",\"Command-Shift-/\"),exec:function(e){e.toggleBlockComment()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"modifyNumberUp\",description:\"Modify number up\",bindKey:o(\"Ctrl-Shift-Up\",\"Alt-Shift-Up\"),exec:function(e){e.modifyNumber(1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"modifyNumberDown\",description:\"Modify number down\",bindKey:o(\"Ctrl-Shift-Down\",\"Alt-Shift-Down\"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"replace\",description:\"Replace\",bindKey:o(\"Ctrl-H\",\"Command-Option-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e,!0)})}},{name:\"undo\",description:\"Undo\",bindKey:o(\"Ctrl-Z\",\"Command-Z\"),exec:function(e){e.undo()}},{name:\"redo\",description:\"Redo\",bindKey:o(\"Ctrl-Shift-Z|Ctrl-Y\",\"Command-Shift-Z|Command-Y\"),exec:function(e){e.redo()}},{name:\"copylinesup\",description:\"Copy lines up\",bindKey:o(\"Alt-Shift-Up\",\"Command-Option-Up\"),exec:function(e){e.copyLinesUp()},scrollIntoView:\"cursor\"},{name:\"movelinesup\",description:\"Move lines up\",bindKey:o(\"Alt-Up\",\"Option-Up\"),exec:function(e){e.moveLinesUp()},scrollIntoView:\"cursor\"},{name:\"copylinesdown\",description:\"Copy lines down\",bindKey:o(\"Alt-Shift-Down\",\"Command-Option-Down\"),exec:function(e){e.copyLinesDown()},scrollIntoView:\"cursor\"},{name:\"movelinesdown\",description:\"Move lines down\",bindKey:o(\"Alt-Down\",\"Option-Down\"),exec:function(e){e.moveLinesDown()},scrollIntoView:\"cursor\"},{name:\"del\",description:\"Delete\",bindKey:o(\"Delete\",\"Delete|Ctrl-D|Shift-Delete\"),exec:function(e){e.remove(\"right\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"backspace\",description:\"Backspace\",bindKey:o(\"Shift-Backspace|Backspace\",\"Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H\"),exec:function(e){e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"cut_or_delete\",description:\"Cut or delete\",bindKey:o(\"Shift-Delete\",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolinestart\",description:\"Remove to line start\",bindKey:o(\"Alt-Backspace\",\"Command-Backspace\"),exec:function(e){e.removeToLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolineend\",description:\"Remove to line end\",bindKey:o(\"Alt-Delete\",\"Ctrl-K|Command-Delete\"),exec:function(e){e.removeToLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolinestarthard\",description:\"Remove to line start hard\",bindKey:o(\"Ctrl-Shift-Backspace\",null),exec:function(e){var t=e.selection.getRange();t.start.column=0,e.session.remove(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolineendhard\",description:\"Remove to line end hard\",bindKey:o(\"Ctrl-Shift-Delete\",null),exec:function(e){var t=e.selection.getRange();t.end.column=Number.MAX_VALUE,e.session.remove(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordleft\",description:\"Remove word left\",bindKey:o(\"Ctrl-Backspace\",\"Alt-Backspace|Ctrl-Alt-Backspace\"),exec:function(e){e.removeWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordright\",description:\"Remove word right\",bindKey:o(\"Ctrl-Delete\",\"Alt-Delete\"),exec:function(e){e.removeWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"outdent\",description:\"Outdent\",bindKey:o(\"Shift-Tab\",\"Shift-Tab\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"indent\",description:\"Indent\",bindKey:o(\"Tab\",\"Tab\"),exec:function(e){e.indent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"blockoutdent\",description:\"Block outdent\",bindKey:o(\"Ctrl-[\",\"Ctrl-[\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"blockindent\",description:\"Block indent\",bindKey:o(\"Ctrl-]\",\"Ctrl-]\"),exec:function(e){e.blockIndent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"insertstring\",description:\"Insert string\",exec:function(e,t){e.insert(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"inserttext\",description:\"Insert text\",exec:function(e,t){e.insert(r.stringRepeat(t.text||\"\",t.times||1))},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"splitline\",description:\"Split line\",bindKey:o(null,\"Ctrl-O\"),exec:function(e){e.splitLine()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"transposeletters\",description:\"Transpose letters\",bindKey:o(\"Alt-Shift-X\",\"Ctrl-T\"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:\"cursor\"},{name:\"touppercase\",description:\"To uppercase\",bindKey:o(\"Ctrl-U\",\"Ctrl-U\"),exec:function(e){e.toUpperCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"tolowercase\",description:\"To lowercase\",bindKey:o(\"Ctrl-Shift-U\",\"Ctrl-Shift-U\"),exec:function(e){e.toLowerCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"autoindent\",description:\"Auto Indent\",bindKey:o(null,null),exec:function(e){e.autoIndent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"animate\"},{name:\"expandtoline\",description:\"Expand to line\",bindKey:o(\"Ctrl-Shift-L\",\"Command-Shift-L\"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"openlink\",bindKey:o(\"Ctrl+F3\",\"F3\"),exec:function(e){e.openLink()}},{name:\"joinlines\",description:\"Join lines\",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\\n\\s*/,\" \").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=\" \"+c),f+=c}i.row+1<e.session.doc.getLength()-1&&(f+=e.session.doc.getNewLineCharacter()),e.clearSelection(),e.session.doc.replace(new s(n.row,0,i.row+2,0),f),a>0?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:\"forEach\",readOnly:!0},{name:\"invertSelection\",description:\"Invert selection\",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o<r.length;o++)o==r.length-1&&(r[o].end.row!==t||r[o].end.column!==n)&&i.push(new s(r[o].end.row,r[o].end.column,t,n)),o===0?(r[o].start.row!==0||r[o].start.column!==0)&&i.push(new s(0,0,r[o].start.row,r[o].start.column)):i.push(new s(r[o-1].end.row,r[o-1].end.column,r[o].start.row,r[o].start.column));e.exitMultiSelectMode(),e.clearSelection();for(var o=0;o<i.length;o++)e.selection.addRange(i[o],!1)},readOnly:!0,scrollIntoView:\"none\"},{name:\"addLineAfter\",description:\"Add new line after the current line\",exec:function(e){e.selection.clearSelection(),e.navigateLineEnd(),e.insert(\"\\n\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"addLineBefore\",description:\"Add new line before the current line\",exec:function(e){e.selection.clearSelection();var t=e.getCursorPosition();e.selection.moveTo(t.row-1,Number.MAX_VALUE),e.insert(\"\\n\"),t.row===0&&e.navigateUp()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"openCommandPallete\",description:\"Open command palette\",bindKey:o(\"F1\",\"F1\"),exec:function(e){e.prompt({$type:\"commands\"})},readOnly:!0},{name:\"modeSelect\",description:\"Change language mode...\",bindKey:o(null,null),exec:function(e){e.prompt({$type:\"modes\"})},readOnly:!0}];for(var u=1;u<9;u++)t.commands.push({name:\"foldToLevel\"+u,description:\"Fold To Level \"+u,level:u,exec:function(e){e.session.foldToLevel(this.level)},scrollIntoView:\"center\",readOnly:!0})}),define(\"ace/line_widgets\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"./lib/dom\"),i=function(){function e(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on(\"change\",this.updateOnChange),this.session.on(\"changeFold\",this.updateOnFold),this.session.on(\"changeEditor\",this.$onChangeEditor)}return e.prototype.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},e.prototype.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},e.prototype.$onChangeEditor=function(e){this.attach(e.editor)},e.prototype.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on(\"beforeRender\",this.measureWidgets),e.renderer.on(\"afterRender\",this.renderWidgets))},e.prototype.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off(\"beforeRender\",this.measureWidgets),t.renderer.off(\"afterRender\",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},e.prototype.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action==\"add\";for(var u=i+1;u<s;u++)n[u]&&(n[u].hidden=o);n[s]&&(o?n[i]?n[s].hidden=o:n[i]=n[s]:(n[i]==n[s]&&(n[i]=undefined),n[s].hidden=o))},e.prototype.updateOnChange=function(e){var t=this.session.lineWidgets;if(!t)return;var n=e.start.row,r=e.end.row-n;if(r!==0)if(e.action==\"remove\"){var i=t.splice(n+1,r);!t[n]&&i[i.length-1]&&(t[n]=i.pop()),i.forEach(function(e){e&&this.removeLineWidget(e)},this),this.$updateRows()}else{var s=new Array(r);t[n]&&t[n].column!=null&&e.start.column>t[n].column&&n++,s.unshift(n,0),t.splice.apply(t,s),this.$updateRows()}},e.prototype.$updateRows=function(){var e=this.session.lineWidgets;if(!e)return;var t=!0;e.forEach(function(e,n){if(e){t=!1,e.row=n;while(e.$oldWidget)e.$oldWidget.row=n,e=e.$oldWidget}}),t&&(this.session.lineWidgets=null)},e.prototype.$registerLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var t=this.session.lineWidgets[e.row];return t&&(e.$oldWidget=t,t.el&&t.el.parentNode&&(t.el.parentNode.removeChild(t.el),t._inDocument=!1)),this.session.lineWidgets[e.row]=e,e},e.prototype.addLineWidget=function(e){this.$registerLineWidget(e),e.session=this.session;if(!this.editor)return e;var t=this.editor.renderer;e.html&&!e.el&&(e.el=r.createElement(\"div\"),e.el.innerHTML=e.html),e.text&&!e.el&&(e.el=r.createElement(\"div\"),e.el.textContent=e.text),e.el&&(r.addCssClass(e.el,\"ace_lineWidgetContainer\"),e.className&&r.addCssClass(e.el,e.className),e.el.style.position=\"absolute\",e.el.style.zIndex=5,t.container.appendChild(e.el),e._inDocument=!0,e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight==null&&(e.pixelHeight=e.el.offsetHeight)),e.rowCount==null&&(e.rowCount=e.pixelHeight/t.layerConfig.lineHeight);var n=this.session.getFoldAt(e.row,0);e.$fold=n;if(n){var i=this.session.lineWidgets;e.row==n.end.row&&!i[n.start.row]?i[n.start.row]=e:e.hidden=!0}return this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,t),this.onWidgetChanged(e),e},e.prototype.removeLineWidget=function(e){e._inDocument=!1,e.session=null,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el);if(e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}if(this.session.lineWidgets){var n=this.session.lineWidgets[e.row];if(n==e)this.session.lineWidgets[e.row]=e.$oldWidget,e.$oldWidget&&this.onWidgetChanged(e.$oldWidget);else while(n){if(n.$oldWidget==e){n.$oldWidget=e.$oldWidget;break}n=n.$oldWidget}}this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows()},e.prototype.getWidgetsAtRow=function(e){var t=this.session.lineWidgets,n=t&&t[e],r=[];while(n)r.push(n),n=n.$oldWidget;return r},e.prototype.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},e.prototype.measureWidgets=function(e,t){var n=this.session._changedWidgets,r=t.layerConfig;if(!n||!n.length)return;var i=Infinity;for(var s=0;s<n.length;s++){var o=n[s];if(!o||!o.el)continue;if(o.session!=this.session)continue;if(!o._inDocument){if(this.session.lineWidgets[o.row]!=o)continue;o._inDocument=!0,t.container.appendChild(o.el)}o.h=o.el.offsetHeight,o.fixedWidth||(o.w=o.el.offsetWidth,o.screenWidth=Math.ceil(o.w/r.characterWidth));var u=o.h/r.lineHeight;o.coverLine&&(u-=this.session.getRowLineCount(o.row),u<0&&(u=0)),o.rowCount!=u&&(o.rowCount=u,o.row<i&&(i=o.row))}i!=Infinity&&(this.session._emit(\"changeFold\",{data:{start:{row:i}}}),this.session.lineWidgetWidth=null),this.session._changedWidgets=[]},e.prototype.renderWidgets=function(e,t){var n=t.layerConfig,r=this.session.lineWidgets;if(!r)return;var i=Math.min(this.firstRow,n.firstRow),s=Math.max(this.lastRow,n.lastRow,r.length);while(i>0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+\"px\";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+\"px\";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+\"px\",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+\"px\"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+\"px\":u.el.style.right=\"\"}},e}();t.LineWidgets=i}),define(\"ace/keyboard/gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/mouse/default_gutter_handler\"],function(e,t,n){\"use strict\";var r=e(\"../lib/keys\"),i=e(\"../mouse/default_gutter_handler\").GutterTooltip,s=function(){function e(e){this.editor=e,this.gutterLayer=e.renderer.$gutterLayer,this.element=e.renderer.$gutter,this.lines=e.renderer.$gutterLayer.$lines,this.activeRowIndex=null,this.activeLane=null,this.annotationTooltip=new i(this.editor)}return e.prototype.addListener=function(){this.element.addEventListener(\"keydown\",this.$onGutterKeyDown.bind(this)),this.element.addEventListener(\"focusout\",this.$blurGutter.bind(this)),this.editor.on(\"mousewheel\",this.$blurGutter.bind(this))},e.prototype.removeListener=function(){this.element.removeEventListener(\"keydown\",this.$onGutterKeyDown.bind(this)),this.element.removeEventListener(\"focusout\",this.$blurGutter.bind(this)),this.editor.off(\"mousewheel\",this.$blurGutter.bind(this))},e.prototype.$onGutterKeyDown=function(e){if(this.annotationTooltip.isOpen){e.preventDefault(),e.keyCode===r.escape&&this.annotationTooltip.hide();return}if(e.target===this.element){if(e.keyCode!=r[\"enter\"])return;e.preventDefault();var t=this.editor.getCursorPosition().row;this.editor.isRowVisible(t)||this.editor.scrollToLine(t,!0,!0),setTimeout(function(){var e=this.$rowToRowIndex(this.gutterLayer.$cursorCell.row),t=this.$findNearestFoldWidget(e),n=this.$findNearestAnnotation(e);if(t===null&&n===null)return;if(t===null&&n!==null){this.activeRowIndex=n,this.activeLane=\"annotation\",this.$focusAnnotation(this.activeRowIndex);return}if(t!==null&&n===null){this.activeRowIndex=t,this.activeLane=\"fold\",this.$focusFoldWidget(this.activeRowIndex);return}if(Math.abs(n-e)<Math.abs(t-e)){this.activeRowIndex=n,this.activeLane=\"annotation\",this.$focusAnnotation(this.activeRowIndex);return}this.activeRowIndex=t,this.activeLane=\"fold\",this.$focusFoldWidget(this.activeRowIndex);return}.bind(this),10);return}if(e.keyCode===r.tab){e.preventDefault();return}if(e.keyCode===r.escape){e.preventDefault(),this.$blurGutter(),this.element.focus(),this.lane=null;return}if(e.keyCode===r.up){e.preventDefault();switch(this.activeLane){case\"fold\":this.$moveFoldWidgetUp();break;case\"annotation\":this.$moveAnnotationUp()}return}if(e.keyCode===r.down){e.preventDefault();switch(this.activeLane){case\"fold\":this.$moveFoldWidgetDown();break;case\"annotation\":this.$moveAnnotationDown()}return}e.keyCode===r.left&&(e.preventDefault(),this.$switchLane(\"annotation\")),e.keyCode===r.right&&(e.preventDefault(),this.$switchLane(\"fold\"));if(e.keyCode===r.enter||e.keyCode===r.space){e.preventDefault();switch(this.activeLane){case\"fold\":if(this.gutterLayer.session.foldWidgets[this.$rowIndexToRow(this.activeRowIndex)]===\"start\"){var n=this.$rowIndexToRow(this.activeRowIndex);this.editor.session.onFoldWidgetClick(this.$rowIndexToRow(this.activeRowIndex),e),setTimeout(function(){this.$rowIndexToRow(this.activeRowIndex)!==n&&(this.$blurFoldWidget(this.activeRowIndex),this.activeRowIndex=this.$rowToRowIndex(n),this.$focusFoldWidget(this.activeRowIndex))}.bind(this),10);break}if(this.gutterLayer.session.foldWidgets[this.$rowIndexToRow(this.activeRowIndex)]===\"end\")break;return;case\"annotation\":var i=this.lines.cells[this.activeRowIndex].element.childNodes[2],s=i.getBoundingClientRect(),o=this.annotationTooltip.getElement().style;o.left=s.right+\"px\",o.top=s.bottom+\"px\",this.annotationTooltip.showTooltip(this.$rowIndexToRow(this.activeRowIndex))}return}},e.prototype.$blurGutter=function(){if(this.activeRowIndex!==null)switch(this.activeLane){case\"fold\":this.$blurFoldWidget(this.activeRowIndex);break;case\"annotation\":this.$blurAnnotation(this.activeRowIndex)}this.annotationTooltip.isOpen&&this.annotationTooltip.hide();return},e.prototype.$isFoldWidgetVisible=function(e){var t=this.editor.isRowFullyVisible(this.$rowIndexToRow(e)),n=this.$getFoldWidget(e).style.display!==\"none\";return t&&n},e.prototype.$isAnnotationVisible=function(e){var t=this.editor.isRowFullyVisible(this.$rowIndexToRow(e)),n=this.$getAnnotation(e).style.display!==\"none\";return t&&n},e.prototype.$getFoldWidget=function(e){var t=this.lines.get(e),n=t.element;return n.childNodes[1]},e.prototype.$getAnnotation=function(e){var t=this.lines.get(e),n=t.element;return n.childNodes[2]},e.prototype.$findNearestFoldWidget=function(e){if(this.$isFoldWidgetVisible(e))return e;var t=0;while(e-t>0||e+t<this.lines.getLength()-1){t++;if(e-t>=0&&this.$isFoldWidgetVisible(e-t))return e-t;if(e+t<=this.lines.getLength()-1&&this.$isFoldWidgetVisible(e+t))return e+t}return null},e.prototype.$findNearestAnnotation=function(e){if(this.$isAnnotationVisible(e))return e;var t=0;while(e-t>0||e+t<this.lines.getLength()-1){t++;if(e-t>=0&&this.$isAnnotationVisible(e-t))return e-t;if(e+t<=this.lines.getLength()-1&&this.$isAnnotationVisible(e+t))return e+t}return null},e.prototype.$focusFoldWidget=function(e){if(e==null)return;var t=this.$getFoldWidget(e);t.classList.add(this.editor.renderer.keyboardFocusClassName),t.focus()},e.prototype.$focusAnnotation=function(e){if(e==null)return;var t=this.$getAnnotation(e);t.classList.add(this.editor.renderer.keyboardFocusClassName),t.setAttribute(\"role\",\"button\"),t.focus()},e.prototype.$blurFoldWidget=function(e){var t=this.$getFoldWidget(e);t.classList.remove(this.editor.renderer.keyboardFocusClassName),t.blur()},e.prototype.$blurAnnotation=function(e){var t=this.$getAnnotation(e);t.classList.remove(this.editor.renderer.keyboardFocusClassName),t.removeAttribute(\"role\"),t.blur()},e.prototype.$moveFoldWidgetUp=function(){var e=this.activeRowIndex;while(e>0){e--;if(this.$isFoldWidgetVisible(e)){this.$blurFoldWidget(this.activeRowIndex),this.activeRowIndex=e,this.$focusFoldWidget(this.activeRowIndex);return}}return},e.prototype.$moveFoldWidgetDown=function(){var e=this.activeRowIndex;while(e<this.lines.getLength()-1){e++;if(this.$isFoldWidgetVisible(e)){this.$blurFoldWidget(this.activeRowIndex),this.activeRowIndex=e,this.$focusFoldWidget(this.activeRowIndex);return}}return},e.prototype.$moveAnnotationUp=function(){var e=this.activeRowIndex;while(e>0){e--;if(this.$isAnnotationVisible(e)){this.$blurAnnotation(this.activeRowIndex),this.activeRowIndex=e,this.$focusAnnotation(this.activeRowIndex);return}}return},e.prototype.$moveAnnotationDown=function(){var e=this.activeRowIndex;while(e<this.lines.getLength()-1){e++;if(this.$isAnnotationVisible(e)){this.$blurAnnotation(this.activeRowIndex),this.activeRowIndex=e,this.$focusAnnotation(this.activeRowIndex);return}}return},e.prototype.$switchLane=function(e){switch(e){case\"annotation\":if(this.activeLane===\"annotation\")break;var t=this.$findNearestAnnotation(this.activeRowIndex);if(t==null)break;this.activeLane=\"annotation\",this.$blurFoldWidget(this.activeRowIndex),this.activeRowIndex=t,this.$focusAnnotation(this.activeRowIndex);break;case\"fold\":if(this.activeLane===\"fold\")break;var n=this.$findNearestFoldWidget(this.activeRowIndex);if(n==null)break;this.activeLane=\"fold\",this.$blurAnnotation(this.activeRowIndex),this.activeRowIndex=n,this.$focusFoldWidget(this.activeRowIndex)}return},e.prototype.$rowIndexToRow=function(e){var t=this.lines.get(e);return t?t.row:null},e.prototype.$rowToRowIndex=function(e){for(var t=0;t<this.lines.getLength();t++){var n=this.lines.get(t);if(n.row==e)return t}return null},e}();t.GutterKeyboardHandler=s}),define(\"ace/editor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/keyboard/textinput\",\"ace/mouse/mouse_handler\",\"ace/mouse/fold_handler\",\"ace/keyboard/keybinding\",\"ace/edit_session\",\"ace/search\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/commands/command_manager\",\"ace/commands/default_commands\",\"ace/config\",\"ace/token_iterator\",\"ace/line_widgets\",\"ace/keyboard/gutter_handler\",\"ace/config\",\"ace/clipboard\",\"ace/lib/keys\"],function(e,t,n){\"use strict\";var r=this&&this.__values||function(e){var t=typeof Symbol==\"function\"&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&typeof e.length==\"number\")return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")},i=e(\"./lib/oop\"),s=e(\"./lib/dom\"),o=e(\"./lib/lang\"),u=e(\"./lib/useragent\"),a=e(\"./keyboard/textinput\").TextInput,f=e(\"./mouse/mouse_handler\").MouseHandler,l=e(\"./mouse/fold_handler\").FoldHandler,c=e(\"./keyboard/keybinding\").KeyBinding,h=e(\"./edit_session\").EditSession,p=e(\"./search\").Search,d=e(\"./range\").Range,v=e(\"./lib/event_emitter\").EventEmitter,m=e(\"./commands/command_manager\").CommandManager,g=e(\"./commands/default_commands\").commands,y=e(\"./config\"),b=e(\"./token_iterator\").TokenIterator,w=e(\"./line_widgets\").LineWidgets,E=e(\"./keyboard/gutter_handler\").GutterKeyboardHandler,S=e(\"./config\").nls,x=e(\"./clipboard\"),T=e(\"./lib/keys\"),N=function(){function e(t,n,r){this.$toDestroy=[];var i=t.getContainerElement();this.container=i,this.renderer=t,this.id=\"editor\"+ ++e.$uid,this.commands=new m(u.isMac?\"mac\":\"win\",g),typeof document==\"object\"&&(this.textInput=new a(t.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.$mouseHandler=new f(this),new l(this)),this.keyBinding=new c(this),this.$search=(new p).set({wrap:!0}),this.$historyTracker=this.$historyTracker.bind(this),this.commands.on(\"exec\",this.$historyTracker),this.$initOperationListeners(),this._$emitInputEvent=o.delayedCall(function(){this._signal(\"input\",{}),this.session&&!this.session.destroyed&&this.session.bgTokenizer.scheduleStart()}.bind(this)),this.on(\"change\",function(e,t){t._$emitInputEvent.schedule(31)}),this.setSession(n||r&&r.session||new h(\"\")),y.resetOptions(this),r&&this.setOptions(r),y._signal(\"editor\",this)}return e.prototype.$initOperationListeners=function(){this.commands.on(\"exec\",this.startOperation.bind(this),!0),this.commands.on(\"afterExec\",this.endOperation.bind(this),!0),this.$opResetTimer=o.delayedCall(this.endOperation.bind(this,!0)),this.on(\"change\",function(){this.curOp||(this.startOperation(),this.curOp.selectionBefore=this.$lastSel),this.curOp.docChanged=!0}.bind(this),!0),this.on(\"changeSelection\",function(){this.curOp||(this.startOperation(),this.curOp.selectionBefore=this.$lastSel),this.curOp.selectionChanged=!0}.bind(this),!0)},e.prototype.startOperation=function(e){if(this.curOp){if(!e||this.curOp.command)return;this.prevOp=this.curOp}e||(this.previousCommand=null,e={}),this.$opResetTimer.schedule(),this.curOp=this.session.curOp={command:e.command||{},args:e.args,scrollTop:this.renderer.scrollTop},this.curOp.selectionBefore=this.selection.toJSON()},e.prototype.endOperation=function(e){if(this.curOp&&this.session){if(e&&e.returnValue===!1||!this.session)return this.curOp=null;if(e==1&&this.curOp.command&&this.curOp.command.name==\"mouse\")return;this._signal(\"beforeEndOperation\");if(!this.curOp)return;var t=this.curOp.command,n=t&&t.scrollIntoView;if(n){switch(n){case\"center-animate\":n=\"animate\";case\"center\":this.renderer.scrollCursorIntoView(null,.5);break;case\"animate\":case\"cursor\":this.renderer.scrollCursorIntoView();break;case\"selectionPart\":var r=this.selection.getRange(),i=this.renderer.layerConfig;(r.start.row>=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n==\"animate\"&&this.renderer.animateScrolling(this.curOp.scrollTop)}var s=this.selection.toJSON();this.curOp.selectionAfter=s,this.$lastSel=this.selection.toJSON(),this.session.getUndoManager().addSelection(s),this.prevOp=this.curOp,this.curOp=null}},e.prototype.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name==\"insertstring\"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\\s/.test(i)||/\\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!=\"always\"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},e.prototype.setKeyboardHandler=function(e,t){if(e&&typeof e==\"string\"&&e!=\"ace\"){this.$keybindingId=e;var n=this;y.loadModule([\"keybinding\",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},e.prototype.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},e.prototype.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off(\"change\",this.$onDocumentChange),this.session.off(\"changeMode\",this.$onChangeMode),this.session.off(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.session.off(\"changeTabSize\",this.$onChangeTabSize),this.session.off(\"changeWrapLimit\",this.$onChangeWrapLimit),this.session.off(\"changeWrapMode\",this.$onChangeWrapMode),this.session.off(\"changeFold\",this.$onChangeFold),this.session.off(\"changeFrontMarker\",this.$onChangeFrontMarker),this.session.off(\"changeBackMarker\",this.$onChangeBackMarker),this.session.off(\"changeBreakpoint\",this.$onChangeBreakpoint),this.session.off(\"changeAnnotation\",this.$onChangeAnnotation),this.session.off(\"changeOverwrite\",this.$onCursorChange),this.session.off(\"changeScrollTop\",this.$onScrollTopChange),this.session.off(\"changeScrollLeft\",this.$onScrollLeftChange);var n=this.session.getSelection();n.off(\"changeCursor\",this.$onCursorChange),n.off(\"changeSelection\",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on(\"change\",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on(\"changeMode\",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on(\"changeTabSize\",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on(\"changeWrapLimit\",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on(\"changeWrapMode\",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on(\"changeFold\",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on(\"changeFrontMarker\",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on(\"changeBackMarker\",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on(\"changeBreakpoint\",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on(\"changeAnnotation\",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on(\"changeOverwrite\",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on(\"changeScrollTop\",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on(\"changeScrollLeft\",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on(\"changeCursor\",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on(\"changeSelection\",this.$onSelectionChange),this.onChangeMode(),this.onCursorChange(),this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal(\"changeSession\",{session:e,oldSession:t}),this.curOp=null,t&&t._signal(\"changeEditor\",{oldEditor:this}),e&&e._signal(\"changeEditor\",{editor:this}),e&&!e.destroyed&&e.bgTokenizer.scheduleStart()},e.prototype.getSession=function(){return this.session},e.prototype.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},e.prototype.getValue=function(){return this.session.getValue()},e.prototype.getSelection=function(){return this.selection},e.prototype.resize=function(e){this.renderer.onResize(e)},e.prototype.setTheme=function(e,t){this.renderer.setTheme(e,t)},e.prototype.getTheme=function(){return this.renderer.getTheme()},e.prototype.setStyle=function(e){this.renderer.setStyle(e)},e.prototype.unsetStyle=function(e){this.renderer.unsetStyle(e)},e.prototype.getFontSize=function(){return this.getOption(\"fontSize\")||s.computedStyle(this.container).fontSize},e.prototype.setFontSize=function(e){this.setOption(\"fontSize\",e)},e.prototype.$highlightBrackets=function(){if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||t.destroyed)return;t.$bracketHighlight&&(t.$bracketHighlight.markerIds.forEach(function(e){t.removeMarker(e)}),t.$bracketHighlight=null);var n=e.getCursorPosition(),r=e.getKeyboardHandler(),i=r&&r.$getDirectionForHighlight&&r.$getDirectionForHighlight(e),s=t.getMatchingBracketRanges(n,i);if(!s){var o=new b(t,n.row,n.column),u=o.getCurrentToken();if(u&&/\\b(?:tag-open|tag-name)/.test(u.type)){var a=t.getMatchingTags(n);a&&(s=[a.openTagName,a.closeTagName])}}!s&&t.$mode.getMatching&&(s=t.$mode.getMatching(e.session));if(!s){e.getHighlightIndentGuides()&&e.renderer.$textLayer.$highlightIndentGuide();return}var f=\"ace_bracket\";Array.isArray(s)?s.length==1&&(f=\"ace_error_bracket\"):s=[s],s.length==2&&(d.comparePoints(s[0].end,s[1].start)==0?s=[d.fromPoints(s[0].start,s[1].end)]:d.comparePoints(s[0].start,s[1].end)==0&&(s=[d.fromPoints(s[1].start,s[0].end)])),t.$bracketHighlight={ranges:s,markerIds:s.map(function(e){return t.addMarker(e,f,\"text\")})},e.getHighlightIndentGuides()&&e.renderer.$textLayer.$highlightIndentGuide()},50)},e.prototype.focus=function(){this.textInput.focus()},e.prototype.isFocused=function(){return this.textInput.isFocused()},e.prototype.blur=function(){this.textInput.blur()},e.prototype.onFocus=function(e){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit(\"focus\",e)},e.prototype.onBlur=function(e){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit(\"blur\",e)},e.prototype.$cursorChange=function(){this.renderer.updateCursor(),this.$highlightBrackets(),this.$updateHighlightActiveLine()},e.prototype.onDocumentChange=function(e){var t=this.session.$useWrapMode,n=e.start.row==e.end.row?e.end.row:Infinity;this.renderer.updateLines(e.start.row,n,t),this._signal(\"change\",e),this.$cursorChange()},e.prototype.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},e.prototype.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},e.prototype.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},e.prototype.onCursorChange=function(){this.$cursorChange(),this._signal(\"changeSelection\")},e.prototype.$updateHighlightActiveLine=function(){var e=this.getSession(),t;if(this.$highlightActiveLine){if(this.$selectionStyle!=\"line\"||!this.selection.isMultiLine())t=this.getCursorPosition();this.renderer.theme&&this.renderer.theme.$selectionColorConflict&&!this.selection.isEmpty()&&(t=!1),this.renderer.$maxLines&&this.session.getLength()===1&&!(this.renderer.$minLines>1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new d(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,\"ace_active-line\",\"screenLine\"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal(\"changeBackMarker\"))},e.prototype.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,\"ace_selection\",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal(\"changeSelection\")},e.prototype.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column,r=t.end.column,i=e.getLine(t.start.row),s=i.substring(n,r);if(s.length>5e3||!/[\\w\\d]/.test(s))return;var o=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:s}),u=i.substring(n-1,r+1);if(!o.test(u))return;return o},e.prototype.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},e.prototype.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},e.prototype.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},e.prototype.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},e.prototype.onChangeMode=function(e){this.renderer.updateText(),this._emit(\"changeMode\",e)},e.prototype.onChangeWrapLimit=function(){this.renderer.updateFull()},e.prototype.onChangeWrapMode=function(){this.renderer.onResize(!0)},e.prototype.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},e.prototype.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},e.prototype.getCopyText=function(){var e=this.getSelectedText(),t=this.session.doc.getNewLineCharacter(),n=!1;if(!e&&this.$copyWithEmptySelection){n=!0;var r=this.selection.getAllRanges();for(var i=0;i<r.length;i++){var s=r[i];if(i&&r[i-1].start.row==s.start.row)continue;e+=this.session.getLine(s.start.row)+t}}var o={text:e};return this._signal(\"copy\",o),x.lineMode=n?o.text:!1,o.text},e.prototype.onCopy=function(){this.commands.exec(\"copy\",this)},e.prototype.onCut=function(){this.commands.exec(\"cut\",this)},e.prototype.onPaste=function(e,t){var n={text:e,event:t};this.commands.exec(\"paste\",this,n)},e.prototype.$handlePaste=function(e){typeof e==\"string\"&&(e={text:e}),this._signal(\"paste\",e);var t=e.text,n=t===x.lineMode,r=this.session;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)n?r.insert({row:this.selection.lead.row,column:0},t):this.insert(t);else if(n)this.selection.rangeList.ranges.forEach(function(e){r.insert({row:e.start.row,column:0},t)});else{var i=t.split(/\\r\\n|\\r|\\n/),s=this.selection.rangeList.ranges,o=i.length==2&&(!i[0]||!i[1]);if(i.length!=s.length||o)return this.commands.exec(\"insertstring\",this,t);for(var u=s.length;u--;){var a=s[u];a.isEmpty()||r.remove(a),r.insert(a.start,i[u])}}},e.prototype.execCommand=function(e,t){return this.commands.exec(e,this,t)},e.prototype.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),\"insertion\",this,n,e);s&&(e!==s.text&&(this.inVirtualSelectionMode||(this.session.mergeUndoDeltas=!1,this.mergeNextCommand=!1)),e=s.text)}e==\"\t\"&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()&&e.indexOf(\"\\n\")==-1){var o=new d.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e==\"\\n\"||e==\"\\r\\n\"){var u=n.getLine(i.row);if(i.column>u.search(/\\S|$/)){var a=u.substr(i.column).search(/\\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e);n.insert(i,e),s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new d(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new d(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(this.$enableAutoIndent){if(n.getDocument().isNewLine(e)){var h=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},h)}c&&r.autoOutdent(l,n,i.row)}},e.prototype.autoIndent=function(){var e=this.session,t=e.getMode(),n,r;if(this.selection.isEmpty())n=0,r=e.doc.getLength()-1;else{var i=this.getSelectionRange();n=i.start.row,r=i.end.row}var s=\"\",o=\"\",u=\"\",a,f,l,c=e.getTabString();for(var h=n;h<=r;h++)h>0&&(s=e.getState(h-1),o=e.getLine(h-1),u=t.getNextLineIndent(s,o,c)),a=e.getLine(h),f=t.$getIndent(a),u!==f&&(f.length>0&&(l=new d(h,0,h,f.length),e.remove(l)),u.length>0&&e.insert({row:h,column:0},u)),t.autoOutdent(s,e,h)},e.prototype.onTextInput=function(e,t){if(!t)return this.keyBinding.onTextInput(e);this.startOperation({command:{name:\"insertstring\"}});var n=this.applyComposition.bind(this,e,t);this.selection.rangeCount?this.forEachSelection(n):n(),this.endOperation()},e.prototype.applyComposition=function(e,t){if(t.extendLeft||t.extendRight){var n=this.selection.getRange();n.start.column-=t.extendLeft,n.end.column+=t.extendRight,n.start.column<0&&(n.start.row--,n.start.column+=this.session.getLine(n.start.row).length+1),this.selection.setRange(n),!e&&!n.isEmpty()&&this.remove()}(e||!this.selection.isEmpty())&&this.insert(e,!0);if(t.restoreStart||t.restoreEnd){var n=this.selection.getRange();n.start.column-=t.restoreStart,n.end.column-=t.restoreEnd,this.selection.setRange(n)}},e.prototype.onCommandKey=function(e,t,n){return this.keyBinding.onCommandKey(e,t,n)},e.prototype.setOverwrite=function(e){this.session.setOverwrite(e)},e.prototype.getOverwrite=function(){return this.session.getOverwrite()},e.prototype.toggleOverwrite=function(){this.session.toggleOverwrite()},e.prototype.setScrollSpeed=function(e){this.setOption(\"scrollSpeed\",e)},e.prototype.getScrollSpeed=function(){return this.getOption(\"scrollSpeed\")},e.prototype.setDragDelay=function(e){this.setOption(\"dragDelay\",e)},e.prototype.getDragDelay=function(){return this.getOption(\"dragDelay\")},e.prototype.setSelectionStyle=function(e){this.setOption(\"selectionStyle\",e)},e.prototype.getSelectionStyle=function(){return this.getOption(\"selectionStyle\")},e.prototype.setHighlightActiveLine=function(e){this.setOption(\"highlightActiveLine\",e)},e.prototype.getHighlightActiveLine=function(){return this.getOption(\"highlightActiveLine\")},e.prototype.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},e.prototype.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},e.prototype.setHighlightSelectedWord=function(e){this.setOption(\"highlightSelectedWord\",e)},e.prototype.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},e.prototype.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},e.prototype.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},e.prototype.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},e.prototype.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},e.prototype.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},e.prototype.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},e.prototype.setHighlightIndentGuides=function(e){this.renderer.setHighlightIndentGuides(e)},e.prototype.getHighlightIndentGuides=function(){return this.renderer.getHighlightIndentGuides()},e.prototype.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},e.prototype.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},e.prototype.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},e.prototype.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},e.prototype.setReadOnly=function(e){this.setOption(\"readOnly\",e)},e.prototype.getReadOnly=function(){return this.getOption(\"readOnly\")},e.prototype.setBehavioursEnabled=function(e){this.setOption(\"behavioursEnabled\",e)},e.prototype.getBehavioursEnabled=function(){return this.getOption(\"behavioursEnabled\")},e.prototype.setWrapBehavioursEnabled=function(e){this.setOption(\"wrapBehavioursEnabled\",e)},e.prototype.getWrapBehavioursEnabled=function(){return this.getOption(\"wrapBehavioursEnabled\")},e.prototype.setShowFoldWidgets=function(e){this.setOption(\"showFoldWidgets\",e)},e.prototype.getShowFoldWidgets=function(){return this.getOption(\"showFoldWidgets\")},e.prototype.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},e.prototype.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},e.prototype.remove=function(e){this.selection.isEmpty()&&(e==\"left\"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,\"deletion\",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]==\"\\n\"){var o=n.getLine(t.end.row);/^\\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},e.prototype.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},e.prototype.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},e.prototype.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.selection.isEmpty()&&this.selection.selectLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},e.prototype.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},e.prototype.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert(\"\\n\"),this.moveCursorToPosition(e)},e.prototype.setGhostText=function(e,t){this.session.widgetManager||(this.session.widgetManager=new w(this.session),this.session.widgetManager.attach(this)),this.renderer.setGhostText(e,t)},e.prototype.removeGhostText=function(){if(!this.session.widgetManager)return;this.renderer.removeGhostText()},e.prototype.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;t<n.length?(r=n.charAt(t)+n.charAt(t-1),i=new d(e.row,t-1,e.row,t+1)):(r=n.charAt(t-1)+n.charAt(t-2),i=new d(e.row,t-2,e.row,t)),this.session.replace(i,r),this.session.selection.moveToPosition(i.end)},e.prototype.toLowerCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toLowerCase()),this.selection.setSelectionRange(e)},e.prototype.toUpperCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toUpperCase()),this.selection.setSelectionRange(e)},e.prototype.indent=function(){var e=this.session,t=this.getSelectionRange();if(t.start.row<t.end.row){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"\t\");return}if(t.start.column<t.end.column){var r=e.getTextRange(t);if(!/^\\s+$/.test(r)){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"\t\");return}}var i=e.getLine(t.start.row),s=t.start,u=e.getTabSize(),a=e.documentToScreenColumn(s.row,s.column);if(this.session.getUseSoftTabs())var f=u-a%u,l=o.stringRepeat(\" \",f);else{var f=a%u;while(i[t.start.column-1]==\" \"&&f)t.start.column--,f--;this.selection.setSelectionRange(t),l=\"\t\"}return this.insert(l)},e.prototype.blockIndent=function(){var e=this.$getSelectedRows();this.session.indentRows(e.first,e.last,\"\t\")},e.prototype.blockOutdent=function(){var e=this.session.getSelection();this.session.outdentRows(e.getRange())},e.prototype.sortLines=function(){var e=this.$getSelectedRows(),t=this.session,n=[];for(var r=e.first;r<=e.last;r++)n.push(t.getLine(r));n.sort(function(e,t){return e.toLowerCase()<t.toLowerCase()?-1:e.toLowerCase()>t.toLowerCase()?1:0});var i=new d(0,0,0,0);for(var r=e.first;r<=e.last;r++){var s=t.getLine(r);i.start.row=r,i.end.row=r,i.end.column=s.length,t.replace(i,n[r-e.first])}},e.prototype.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},e.prototype.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},e.prototype.getNumberAt=function(e,t){var n=/[\\-]?[0-9]+(?:\\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex<t){var i=n.exec(r);if(i.index<=t&&i.index+i[0].length>=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},e.prototype.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new d(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(\".\")>=0?s.start+s.value.indexOf(\".\")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n<o?e*=Math.pow(10,s.end-n-1):e*=Math.pow(10,s.end-n),a+=e,a/=Math.pow(10,u);var f=a.toFixed(u),l=new d(t,s.start,t,s.end);this.session.replace(l,f),this.moveCursorTo(t,Math.max(s.start+1,n+f.length-s.value.length))}}else this.toggleWord()},e.prototype.toggleWord=function(){var e=this.selection.getCursor().row,t=this.selection.getCursor().column;this.selection.selectWord();var n=this.getSelectedText(),r=this.selection.getWordRange().start.column,i=n.replace(/([a-z]+|[A-Z]+)(?=[A-Z_]|$)/g,\"$1 \").split(/\\s/),s=t-r-1;s<0&&(s=0);var u=0,a=0,f=this;n.match(/[A-Za-z0-9_]+/)&&i.forEach(function(t,i){a=u+t.length,s>=u&&s<=a&&(n=t,f.selection.clearSelection(),f.moveCursorTo(e,u+r),f.selection.selectTo(e,a+r)),u=a});var l=this.$toggleWordPairs,c;for(var h=0;h<l.length;h++){var p=l[h];for(var d=0;d<=1;d++){var v=+!d,m=n.match(new RegExp(\"^\\\\s?_?(\"+o.escapeRegExp(p[d])+\")\\\\s?$\",\"i\"));if(m){var g=n.match(new RegExp(\"([_]|^|\\\\s)(\"+o.escapeRegExp(m[1])+\")($|\\\\s)\",\"g\"));g&&(c=n.replace(new RegExp(o.escapeRegExp(p[d]),\"i\"),function(e){var t=p[v];return e.toUpperCase()==e?t=t.toUpperCase():e.charAt(0).toUpperCase()==e.charAt(0)&&(t=t.substr(0,0)+p[v].charAt(0).toUpperCase()+t.substr(1)),t}),this.insert(c),c=\"\")}}}},e.prototype.findLinkAt=function(e,t){var n,i,s=this.session.getLine(e),o=s.split(/((?:https?|ftp):\\/\\/[\\S]+)/),u=t;u<0&&(u=0);var a=0,f=0,l;try{for(var c=r(o),h=c.next();!h.done;h=c.next()){var p=h.value;f=a+p.length;if(u>=a&&u<=f&&p.match(/((?:https?|ftp):\\/\\/[\\S]+)/)){l=p.replace(/[\\s:.,'\";}\\]]+$/,\"\");break}a=f}}catch(d){n={error:d}}finally{try{h&&!h.done&&(i=c.return)&&i.call(c)}finally{if(n)throw n.error}}return l},e.prototype.openLink=function(){var e=this.selection.getCursor(),t=this.findLinkAt(e.row,e.column);return t&&window.open(t,\"_blank\"),t!=null},e.prototype.removeLines=function(){var e=this.$getSelectedRows();this.session.removeFullLines(e.first,e.last),this.clearSelection()},e.prototype.duplicateSelection=function(){var e=this.selection,t=this.session,n=e.getRange(),r=e.isBackwards();if(n.isEmpty()){var i=n.start.row;t.duplicateLines(i,i)}else{var s=r?n.start:n.end,o=t.insert(s,t.getTextRange(n),!1);n.start=s,n.end=o,e.setSelectionRange(n,r)}},e.prototype.moveLinesDown=function(){this.$moveLines(1,!1)},e.prototype.moveLinesUp=function(){this.$moveLines(-1,!1)},e.prototype.moveText=function(e,t,n){return this.session.moveText(e,t,n)},e.prototype.copyLinesUp=function(){this.$moveLines(-1,!0)},e.prototype.copyLinesDown=function(){this.$moveLines(1,!0)},e.prototype.$moveLines=function(e,t){var n,r,i=this.selection;if(!i.inMultiSelectMode||this.inVirtualSelectionMode){var s=i.toOrientedRange();n=this.$getSelectedRows(s),r=this.session.$moveLines(n.first,n.last,t?0:e),t&&e==-1&&(r=0),s.moveBy(r,0),i.fromOrientedRange(s)}else{var o=i.rangeList.ranges;i.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;var u=0,a=0,f=o.length;for(var l=0;l<f;l++){var c=l;o[l].moveBy(u,0),n=this.$getSelectedRows(o[l]);var h=n.first,p=n.last;while(++l<f){a&&o[l].moveBy(a,0);var d=this.$getSelectedRows(o[l]);if(t&&d.first!=p)break;if(!t&&d.first>p+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},e.prototype.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},e.prototype.onCompositionStart=function(e){this.renderer.showComposition(e)},e.prototype.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},e.prototype.onCompositionEnd=function(){this.renderer.hideComposition()},e.prototype.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},e.prototype.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},e.prototype.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},e.prototype.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},e.prototype.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},e.prototype.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection());var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},e.prototype.selectPageDown=function(){this.$moveByPage(1,!0)},e.prototype.selectPageUp=function(){this.$moveByPage(-1,!0)},e.prototype.gotoPageDown=function(){this.$moveByPage(1,!1)},e.prototype.gotoPageUp=function(){this.$moveByPage(-1,!1)},e.prototype.scrollPageDown=function(){this.$moveByPage(1)},e.prototype.scrollPageUp=function(){this.$moveByPage(-1)},e.prototype.scrollToRow=function(e){this.renderer.scrollToRow(e)},e.prototype.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},e.prototype.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},e.prototype.getCursorPosition=function(){return this.selection.getCursor()},e.prototype.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},e.prototype.getSelectionRange=function(){return this.selection.getRange()},e.prototype.selectAll=function(){this.selection.selectAll()},e.prototype.clearSelection=function(){this.selection.clearSelection()},e.prototype.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},e.prototype.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},e.prototype.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new b(this.session,n.row,n.column),i=r.getCurrentToken(),s=0;i&&i.type.indexOf(\"tag-name\")!==-1&&(i=r.stepBackward());var o=i||r.stepForward();if(!o)return;var u,a=!1,f={},l=n.column-o.start,c,h={\")\":\"(\",\"(\":\"(\",\"]\":\"[\",\"[\":\"[\",\"{\":\"{\",\"}\":\"{\"};do{if(o.value.match(/[{}()\\[\\]]/g))for(;l<o.value.length&&!a;l++){if(!h[o.value[l]])continue;c=h[o.value[l]]+\".\"+o.type.replace(\"rparen\",\"lparen\"),isNaN(f[c])&&(f[c]=0);switch(o.value[l]){case\"(\":case\"[\":case\"{\":f[c]++;break;case\")\":case\"]\":case\"}\":f[c]--,f[c]===-1&&(u=\"bracket\",a=!0)}}else o.type.indexOf(\"tag-name\")!==-1&&(isNaN(f[o.value])&&(f[o.value]=0),i.value===\"<\"&&s>1?f[o.value]++:i.value===\"</\"&&f[o.value]--,f[o.value]===-1&&(u=\"tag\",a=!0));a||(i=o,s++,o=r.stepForward(),l=0)}while(o&&!a);if(!u)return;var p,v;if(u===\"bracket\"){p=this.session.getBracketRange(n);if(!p){p=new d(r.getCurrentTokenRow(),r.getCurrentTokenColumn()+l-1,r.getCurrentTokenRow(),r.getCurrentTokenColumn()+l-1),v=p.start;if(t||v.row===n.row&&Math.abs(v.column-n.column)<2)p=this.session.getBracketRange(v)}}else if(u===\"tag\"){if(!o||o.type.indexOf(\"tag-name\")===-1)return;p=new d(r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2,r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2);if(p.compare(n.row,n.column)===0){var m=this.session.getMatchingTags(n);m&&(m.openTag.contains(n.row,n.column)?(p=m.closeTag,v=p.start):(p=m.openTag,m.closeTag.start.row===n.row&&m.closeTag.start.column===n.column?v=p.end:v=p.start))}v=v||p.start}v=p&&p.cursor||v,v&&(e?p&&t?this.selection.setRange(p):p&&p.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(v.row,v.column):this.selection.moveTo(v.row,v.column))},e.prototype.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.exitMultiSelectMode&&this.exitMultiSelectMode(),this.moveCursorTo(e-1,t||0),this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},e.prototype.navigateTo=function(e,t){this.selection.moveTo(e,t)},e.prototype.navigateUp=function(e){if(this.selection.isMultiLine()&&!this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(-e||-1,0)},e.prototype.navigateDown=function(e){if(this.selection.isMultiLine()&&this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(e||1,0)},e.prototype.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},e.prototype.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},e.prototype.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},e.prototype.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},e.prototype.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},e.prototype.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},e.prototype.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},e.prototype.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},e.prototype.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end),r):r},e.prototype.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;var i=this.getSelectionRange();this.selection.moveTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),r},e.prototype.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},e.prototype.getLastSearchOptions=function(){return this.$search.getOptions()},e.prototype.find=function(e,t,n){t||(t={}),typeof e==\"string\"||e instanceof RegExp?t.needle=e:typeof e==\"object\"&&i.mixin(t,e);var r=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(r)||this.$search.$options.needle,e||(r=this.session.getWordRange(r.start.row,r.start.column),e=this.session.getTextRange(r)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:r});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?r.start=r.end:r.end=r.start,this.selection.setRange(r)},e.prototype.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},e.prototype.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},e.prototype.revealRange=function(e,t){this.session.unfold(e),this.selection.setSelectionRange(e);var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},e.prototype.undo=function(){this.session.getUndoManager().undo(this.session),this.renderer.scrollCursorIntoView(null,.5)},e.prototype.redo=function(){this.session.getUndoManager().redo(this.session),this.renderer.scrollCursorIntoView(null,.5)},e.prototype.destroy=function(){this.$toDestroy&&(this.$toDestroy.forEach(function(e){e.destroy()}),this.$toDestroy=null),this.$mouseHandler&&this.$mouseHandler.destroy(),this.renderer.destroy(),this._signal(\"destroy\",this),this.session&&this.session.destroy(),this._$emitInputEvent&&this._$emitInputEvent.cancel(),this.removeAllListeners()},e.prototype.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement(\"div\"));var i=this.$scrollAnchor;i.style.cssText=\"position:absolute\",this.container.insertBefore(i,this.container.firstChild);var s=this.on(\"changeSelection\",function(){r=!0}),o=this.renderer.on(\"beforeRender\",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on(\"afterRender\",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.top<o.height&&s.top+t.top+o.lineHeight>window.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+\"px\",i.style.left=s.left+\"px\",i.style.height=o.lineHeight+\"px\",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off(\"changeSelection\",s),this.renderer.off(\"afterRender\",u),this.renderer.off(\"beforeRender\",o)}},e.prototype.$resetCursorStyle=function(){var e=this.$cursorStyle||\"ace\",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!=\"wide\",s.setCssClass(t.element,\"ace_slim-cursors\",/slim/.test(e))},e.prototype.prompt=function(e,t,n){var r=this;y.loadModule(\"ace/ext/prompt\",function(i){i.prompt(r,e,t,n)})},e}();N.$uid=0,N.prototype.curOp=null,N.prototype.prevOp={},N.prototype.$mergeableCommands=[\"backspace\",\"del\",\"insertstring\"],N.prototype.$toggleWordPairs=[[\"first\",\"last\"],[\"true\",\"false\"],[\"yes\",\"no\"],[\"width\",\"height\"],[\"top\",\"bottom\"],[\"right\",\"left\"],[\"on\",\"off\"],[\"x\",\"y\"],[\"get\",\"set\"],[\"max\",\"min\"],[\"horizontal\",\"vertical\"],[\"show\",\"hide\"],[\"add\",\"remove\"],[\"up\",\"down\"],[\"before\",\"after\"],[\"even\",\"odd\"],[\"in\",\"out\"],[\"inside\",\"outside\"],[\"next\",\"previous\"],[\"increase\",\"decrease\"],[\"attach\",\"detach\"],[\"&&\",\"||\"],[\"==\",\"!=\"]],i.implement(N.prototype,v),y.defineOptions(N.prototype,\"editor\",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal(\"changeSelectionStyle\",{data:e})},initialValue:\"line\"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.textInput.setReadOnly(e),this.$resetCursorStyle()},initialValue:!1},copyWithEmptySelection:{set:function(e){this.textInput.setCopyWithEmptySelection(e)},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:[\"ace\",\"slim\",\"smooth\",\"wide\"],initialValue:\"ace\"},mergeUndoDeltas:{values:[!1,!0,\"always\"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},enableAutoIndent:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.$keybindingId},handlesSet:!0},value:{set:function(e){this.session.setValue(e)},get:function(){return this.getValue()},handlesSet:!0,hidden:!0},session:{set:function(e){this.setSession(e)},get:function(){return this.session},handlesSet:!0,hidden:!0},showLineNumbers:{set:function(e){this.renderer.$gutterLayer.setShowLineNumbers(e),this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER),e&&this.$relativeLineNumbers?C.attach(this):C.detach(this)},initialValue:!0},relativeLineNumbers:{set:function(e){this.$showLineNumbers&&e?C.attach(this):C.detach(this)}},placeholder:{set:function(e){this.$updatePlaceholder||(this.$updatePlaceholder=function(){var e=this.session&&(this.renderer.$composition||this.session.getLength()>1||this.session.getLine(0).length>0);if(e&&this.renderer.placeholderNode)this.renderer.off(\"afterRender\",this.$updatePlaceholder),s.removeCssClass(this.container,\"ace_hasPlaceholder\"),this.renderer.placeholderNode.remove(),this.renderer.placeholderNode=null;else if(!e&&!this.renderer.placeholderNode){this.renderer.on(\"afterRender\",this.$updatePlaceholder),s.addCssClass(this.container,\"ace_hasPlaceholder\");var t=s.createElement(\"div\");t.className=\"ace_placeholder\",t.textContent=this.$placeholder||\"\",this.renderer.placeholderNode=t,this.renderer.content.appendChild(this.renderer.placeholderNode)}else!e&&this.renderer.placeholderNode&&(this.renderer.placeholderNode.textContent=this.$placeholder||\"\")}.bind(this),this.on(\"input\",this.$updatePlaceholder)),this.$updatePlaceholder()}},enableKeyboardAccessibility:{set:function(e){var t={name:\"blurTextInput\",description:\"Set focus to the editor content div to allow tabbing through the page\",bindKey:\"Esc\",exec:function(e){e.blur(),e.renderer.scroller.focus()},readOnly:!0},n=function(e){if(e.target==this.renderer.scroller&&e.keyCode===T.enter){e.preventDefault();var t=this.getCursorPosition().row;this.isRowVisible(t)||this.scrollToLine(t,!0,!0),this.focus()}},r;e?(this.renderer.enableKeyboardAccessibility=!0,this.renderer.keyboardFocusClassName=\"ace_keyboard-focus\",this.textInput.getElement().setAttribute(\"tabindex\",-1),this.renderer.scroller.setAttribute(\"tabindex\",0),this.renderer.scroller.setAttribute(\"role\",\"group\"),this.renderer.scroller.setAttribute(\"aria-roledescription\",S(\"editor\")),this.renderer.scroller.classList.add(this.renderer.keyboardFocusClassName),this.renderer.scroller.setAttribute(\"aria-label\",S(\"Editor content, press Enter to start editing, press Escape to exit\")),this.renderer.scroller.addEventListener(\"keyup\",n.bind(this)),this.commands.addCommand(t),this.renderer.$gutter.setAttribute(\"tabindex\",0),this.renderer.$gutter.setAttribute(\"aria-hidden\",!1),this.renderer.$gutter.setAttribute(\"role\",\"group\"),this.renderer.$gutter.setAttribute(\"aria-roledescription\",S(\"editor\")),this.renderer.$gutter.setAttribute(\"aria-label\",S(\"Editor gutter, press Enter to interact with controls using arrow keys, press Escape to exit\")),this.renderer.$gutter.classList.add(this.renderer.keyboardFocusClassName),this.renderer.content.setAttribute(\"aria-hidden\",!0),r||(r=new E(this)),r.addListener()):(this.renderer.enableKeyboardAccessibility=!1,this.textInput.getElement().setAttribute(\"tabindex\",0),this.renderer.scroller.setAttribute(\"tabindex\",-1),this.renderer.scroller.removeAttribute(\"role\"),this.renderer.scroller.removeAttribute(\"aria-roledescription\"),this.renderer.scroller.classList.remove(this.renderer.keyboardFocusClassName),this.renderer.scroller.removeAttribute(\"aria-label\"),this.renderer.scroller.removeEventListener(\"keyup\",n.bind(this)),this.commands.removeCommand(t),this.renderer.content.removeAttribute(\"aria-hidden\"),this.renderer.$gutter.setAttribute(\"tabindex\",-1),this.renderer.$gutter.setAttribute(\"aria-hidden\",!0),this.renderer.$gutter.removeAttribute(\"role\"),this.renderer.$gutter.removeAttribute(\"aria-roledescription\"),this.renderer.$gutter.removeAttribute(\"aria-label\"),this.renderer.$gutter.classList.remove(this.renderer.keyboardFocusClassName),r&&r.removeListener())},initialValue:!1},customScrollbar:\"renderer\",hScrollBarAlwaysVisible:\"renderer\",vScrollBarAlwaysVisible:\"renderer\",highlightGutterLine:\"renderer\",animatedScroll:\"renderer\",showInvisibles:\"renderer\",showPrintMargin:\"renderer\",printMarginColumn:\"renderer\",printMargin:\"renderer\",fadeFoldWidgets:\"renderer\",showFoldWidgets:\"renderer\",displayIndentGuides:\"renderer\",highlightIndentGuides:\"renderer\",showGutter:\"renderer\",fontSize:\"renderer\",fontFamily:\"renderer\",maxLines:\"renderer\",minLines:\"renderer\",scrollPastEnd:\"renderer\",fixedWidthGutter:\"renderer\",theme:\"renderer\",hasCssTransforms:\"renderer\",maxPixelHeight:\"renderer\",useTextareaForIME:\"renderer\",useResizeObserver:\"renderer\",useSvgGutterIcons:\"renderer\",showFoldedAnnotations:\"renderer\",scrollSpeed:\"$mouseHandler\",dragDelay:\"$mouseHandler\",dragEnabled:\"$mouseHandler\",focusTimeout:\"$mouseHandler\",tooltipFollowsMouse:\"$mouseHandler\",firstLineNumber:\"session\",overwrite:\"session\",newLineMode:\"session\",useWorker:\"session\",useSoftTabs:\"session\",navigateWithinSoftTabs:\"session\",tabSize:\"session\",wrap:\"session\",indentedSoftWrap:\"session\",foldStyle:\"session\",mode:\"session\"});var C={getText:function(e,t){return(Math.abs(e.selection.lead.row-t)||t+1+(t<9?\"\\u00b7\":\"\"))+\"\"},getWidth:function(e,t,n){return Math.max(t.toString().length,(n.lastRow+1).toString().length,2)*n.characterWidth},update:function(e,t){t.renderer.$loop.schedule(t.renderer.CHANGE_GUTTER)},attach:function(e){e.renderer.$gutterLayer.$renderer=this,e.on(\"changeSelection\",this.update),this.update(null,e)},detach:function(e){e.renderer.$gutterLayer.$renderer==this&&(e.renderer.$gutterLayer.$renderer=null),e.off(\"changeSelection\",this.update),this.update(null,e)}};t.Editor=N}),define(\"ace/undomanager\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";function i(e,t){for(var n=t;n--;){var r=e[n];if(r&&!r[0].ignore){while(n<t-1){var i=d(e[n],e[n+1]);e[n]=i[0],e[n+1]=i[1],n++}return!0}}}function a(e){var t=e.action==\"insert\",n=e.start,r=e.end,i=(r.row-n.row)*(t?1:-1),s=(r.column-n.column)*(t?1:-1);t&&(r=n);for(var o in this.marks){var a=this.marks[o],f=u(a,n);if(f<0)continue;if(f===0&&t){if(a.bias!=1){a.bias==-1;continue}f=1}var l=t?f:u(a,r);if(l>0){a.row+=i,a.column+=a.row==r.row?s:0;continue}!t&&l<=0&&(a.row=n.row,a.column=n.column,l===0&&(a.bias=1))}}function f(e){return{row:e.row,column:e.column}}function l(e){return{start:f(e.start),end:f(e.end),action:e.action,lines:e.lines.slice()}}function c(e){e=e||this;if(Array.isArray(e))return e.map(c).join(\"\\n\");var t=\"\";e.action?(t=e.action==\"insert\"?\"+\":\"-\",t+=\"[\"+e.lines+\"]\"):e.value&&(Array.isArray(e.value)?t=e.value.map(h).join(\"\\n\"):t=h(e.value)),e.start&&(t+=h(e));if(e.id||e.rev)t+=\"\t(\"+(e.id||e.rev)+\")\";return t}function h(e){return e.start.row+\":\"+e.start.column+\"=>\"+e.end.row+\":\"+e.end.column}function p(e,t){var n=e.action==\"insert\",r=t.action==\"insert\";if(n&&r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.start,e.start)<=0))return null;m(e,t,1)}else if(n&&!r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.end,e.start)<=0))return null;m(e,t,-1)}else if(!n&&r)if(o(t.start,e.start)>=0)m(t,e,1);else{if(!(o(t.start,e.start)<=0))return null;m(e,t,1)}else if(!n&&!r)if(o(t.start,e.start)>=0)m(t,e,1);else{if(!(o(t.end,e.start)<=0))return null;m(e,t,-1)}return[t,e]}function d(e,t){for(var n=e.length;n--;)for(var r=0;r<t.length;r++)if(!p(e[n],t[r])){while(n<e.length){while(r--)p(t[r],e[n]);r=t.length,n++}return[e,t]}return e.selectionBefore=t.selectionBefore=e.selectionAfter=t.selectionAfter=null,[t,e]}function v(e,t){var n=e.action==\"insert\",r=t.action==\"insert\";if(n&&r)o(e.start,t.start)<0?m(t,e,1):m(e,t,1);else if(n&&!r)o(e.start,t.end)>=0?m(e,t,-1):o(e.start,t.start)<=0?m(t,e,1):(m(e,s.fromPoints(t.start,e.start),-1),m(t,e,1));else if(!n&&r)o(t.start,e.end)>=0?m(t,e,-1):o(t.start,e.start)<=0?m(e,t,1):(m(t,s.fromPoints(e.start,t.start),-1),m(e,t,1));else if(!n&&!r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.end,e.start)<=0)){var i,u;return o(e.start,t.start)<0&&(i=e,e=y(e,t.start)),o(e.end,t.end)>0&&(u=y(e,t.end)),g(t.end,e.start,e.end,-1),u&&!i&&(e.lines=u.lines,e.start=u.start,e.end=u.end,u=e),[t,i,u].filter(Boolean)}m(e,t,-1)}return[t,e]}function m(e,t,n){g(e.start,t.start,t.end,n),g(e.end,t.start,t.end,n)}function g(e,t,n,r){e.row==(r==1?t:n).row&&(e.column+=r*(n.column-t.column)),e.row+=r*(n.row-t.row)}function y(e,t){var n=e.lines,r=e.end;e.end=f(t);var i=e.end.row-e.start.row,s=n.splice(i,n.length),o=i?t.column:t.column-e.start.column;n.push(s[0].substring(0,o)),s[0]=s[0].substr(o);var u={start:f(t),end:r,lines:s,action:e.action};return u}function b(e,t){t=l(t);for(var n=e.length;n--;){var r=e[n];for(var i=0;i<r.length;i++){var s=r[i],o=v(s,t);t=o[0],o.length!=2&&(o[2]?(r.splice(i+1,1,o[1],o[2]),i++):o[1]||(r.splice(i,1),i--))}r.length||e.splice(n,1)}return e}function w(e,t){for(var n=0;n<t.length;n++){var r=t[n];for(var i=0;i<r.length;i++)b(e,r[i])}}var r=function(){function e(){this.$maxRev=0,this.$fromUndo=!1,this.$undoDepth=Infinity,this.reset()}return e.prototype.addSession=function(e){this.$session=e},e.prototype.add=function(e,t,n){if(this.$fromUndo)return;if(e==this.$lastDelta)return;this.$keepRedoStack||(this.$redoStack.length=0);if(t===!1||!this.lastDeltas){this.lastDeltas=[];var r=this.$undoStack.length;r>this.$undoDepth-1&&this.$undoStack.splice(0,r-this.$undoDepth+1),this.$undoStack.push(this.lastDeltas),e.id=this.$rev=++this.$maxRev}if(e.action==\"remove\"||e.action==\"insert\")this.$lastDelta=e;this.lastDeltas.push(e)},e.prototype.addSelection=function(e,t){this.selections.push({value:e,rev:t||this.$rev})},e.prototype.startNewGroup=function(){return this.lastDeltas=null,this.$rev},e.prototype.markIgnored=function(e,t){t==null&&(t=this.$rev+1);var n=this.$undoStack;for(var r=n.length;r--;){var i=n[r][0];if(i.id<=e)break;i.id<t&&(i.ignore=!0)}this.lastDeltas=null},e.prototype.getSelection=function(e,t){var n=this.selections;for(var r=n.length;r--;){var i=n[r];if(i.rev<e)return t&&(i=n[r+1]),i}},e.prototype.getRevision=function(){return this.$rev},e.prototype.getDeltas=function(e,t){t==null&&(t=this.$rev+1);var n=this.$undoStack,r=null,i=0;for(var s=n.length;s--;){var o=n[s][0];o.id<t&&!r&&(r=s+1);if(o.id<=e){i=s+1;break}}return n.slice(i,r)},e.prototype.getChangedRanges=function(e,t){t==null&&(t=this.$rev+1)},e.prototype.getChangedLines=function(e,t){t==null&&(t=this.$rev+1)},e.prototype.undo=function(e,t){this.lastDeltas=null;var n=this.$undoStack;if(!i(n,n.length))return;e||(e=this.$session),this.$redoStackBaseRev!==this.$rev&&this.$redoStack.length&&(this.$redoStack=[]),this.$fromUndo=!0;var r=n.pop(),s=null;return r&&(s=e.undoChanges(r,t),this.$redoStack.push(r),this.$syncRev()),this.$fromUndo=!1,s},e.prototype.redo=function(e,t){this.lastDeltas=null,e||(e=this.$session),this.$fromUndo=!0;if(this.$redoStackBaseRev!=this.$rev){var n=this.getDeltas(this.$redoStackBaseRev,this.$rev+1);w(this.$redoStack,n),this.$redoStackBaseRev=this.$rev,this.$redoStack.forEach(function(e){e[0].id=++this.$maxRev},this)}var r=this.$redoStack.pop(),i=null;return r&&(i=e.redoChanges(r,t),this.$undoStack.push(r),this.$syncRev()),this.$fromUndo=!1,i},e.prototype.$syncRev=function(){var e=this.$undoStack,t=e[e.length-1],n=t&&t[0].id||0;this.$redoStackBaseRev=n,this.$rev=n},e.prototype.reset=function(){this.lastDeltas=null,this.$lastDelta=null,this.$undoStack=[],this.$redoStack=[],this.$rev=0,this.mark=0,this.$redoStackBaseRev=this.$rev,this.selections=[]},e.prototype.canUndo=function(){return this.$undoStack.length>0},e.prototype.canRedo=function(){return this.$redoStack.length>0},e.prototype.bookmark=function(e){e==undefined&&(e=this.$rev),this.mark=e},e.prototype.isAtBookmark=function(){return this.$rev===this.mark},e.prototype.toJSON=function(){},e.prototype.fromJSON=function(){},e.prototype.$prettyPrint=function(e){return e?c(e):c(this.$undoStack)+\"\\n---\\n\"+c(this.$redoStack)},e}();r.prototype.hasUndo=r.prototype.canUndo,r.prototype.hasRedo=r.prototype.canRedo,r.prototype.isClean=r.prototype.isAtBookmark,r.prototype.markClean=r.prototype.bookmark;var s=e(\"./range\").Range,o=s.comparePoints,u=s.comparePoints;t.UndoManager=r}),define(\"ace/layer/lines\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=function(){function e(e,t){this.element=e,this.canvasHeight=t||5e5,this.element.style.height=this.canvasHeight*2+\"px\",this.cells=[],this.cellCache=[],this.$offsetCoefficient=0}return e.prototype.moveContainer=function(e){r.translate(this.element,0,-(e.firstRowScreen*e.lineHeight%this.canvasHeight)-e.offset*this.$offsetCoefficient)},e.prototype.pageChanged=function(e,t){return Math.floor(e.firstRowScreen*e.lineHeight/this.canvasHeight)!==Math.floor(t.firstRowScreen*t.lineHeight/this.canvasHeight)},e.prototype.computeLineTop=function(e,t,n){var r=t.firstRowScreen*t.lineHeight,i=Math.floor(r/this.canvasHeight),s=n.documentToScreenRow(e,0)*t.lineHeight;return s-i*this.canvasHeight},e.prototype.computeLineHeight=function(e,t,n){return t.lineHeight*n.getRowLineCount(e)},e.prototype.getLength=function(){return this.cells.length},e.prototype.get=function(e){return this.cells[e]},e.prototype.shift=function(){this.$cacheCell(this.cells.shift())},e.prototype.pop=function(){this.$cacheCell(this.cells.pop())},e.prototype.push=function(e){if(Array.isArray(e)){this.cells.push.apply(this.cells,e);var t=r.createFragment(this.element);for(var n=0;n<e.length;n++)t.appendChild(e[n].element);this.element.appendChild(t)}else this.cells.push(e),this.element.appendChild(e.element)},e.prototype.unshift=function(e){if(Array.isArray(e)){this.cells.unshift.apply(this.cells,e);var t=r.createFragment(this.element);for(var n=0;n<e.length;n++)t.appendChild(e[n].element);this.element.firstChild?this.element.insertBefore(t,this.element.firstChild):this.element.appendChild(t)}else this.cells.unshift(e),this.element.insertAdjacentElement(\"afterbegin\",e.element)},e.prototype.last=function(){return this.cells.length?this.cells[this.cells.length-1]:null},e.prototype.$cacheCell=function(e){if(!e)return;e.element.remove(),this.cellCache.push(e)},e.prototype.createCell=function(e,t,n,i){var s=this.cellCache.pop();if(!s){var o=r.createElement(\"div\");i&&i(o),this.element.appendChild(o),s={element:o,text:\"\",row:e}}return s.row=e,s},e}();t.Lines=i}),define(\"ace/layer/gutter\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/layer/lines\",\"ace/config\"],function(e,t,n){\"use strict\";function l(e){var t=document.createTextNode(\"\");e.appendChild(t);var n=r.createElement(\"span\");e.appendChild(n);var i=r.createElement(\"span\");e.appendChild(i);var s=r.createElement(\"span\");return i.appendChild(s),e}var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/lang\"),o=e(\"../lib/event_emitter\").EventEmitter,u=e(\"./lines\").Lines,a=e(\"../config\").nls,f=function(){function e(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_gutter-layer\",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$lines=new u(this.element),this.$lines.$offsetCoefficient=1}return e.prototype.setSession=function(e){this.session&&this.session.off(\"change\",this.$updateAnnotations),this.session=e,e&&e.on(\"change\",this.$updateAnnotations)},e.prototype.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.addGutterDecoration\"),this.session.addGutterDecoration(e,t)},e.prototype.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.removeGutterDecoration\"),this.session.removeGutterDecoration(e,t)},e.prototype.setAnnotations=function(e){this.$annotations=[];for(var t=0;t<e.length;t++){var n=e[t],r=n.row,i=this.$annotations[r];i||(i=this.$annotations[r]={text:[],type:[]});var o=n.text,u=n.type;o=o?s.escapeHTML(o):n.html||\"\",i.text.indexOf(o)===-1&&(i.text.push(o),i.type.push(u));var a=n.className;a?i.className=a:u==\"error\"?i.className=\" ace_error\":u==\"warning\"&&i.className!=\" ace_error\"?i.className=\" ace_warning\":u==\"info\"&&!i.className&&(i.className=\" ace_info\")}},e.prototype.$updateAnnotations=function(e){if(!this.$annotations.length)return;var t=e.start.row,n=e.end.row-t;if(n!==0)if(e.action==\"remove\")this.$annotations.splice(t,n+1,null);else{var r=new Array(n+1);r.unshift(t,1),this.$annotations.splice.apply(this.$annotations,r)}},e.prototype.update=function(e){this.config=e;var t=this.session,n=e.firstRow,r=Math.min(e.lastRow+e.gutterOffset,t.getLength()-1);this.oldLastRow=r,this.config=e,this.$lines.moveContainer(e),this.$updateCursorRow();var i=t.getNextFoldLine(n),s=i?i.start.row:Infinity,o=null,u=-1,a=n;for(;;){a>s&&(a=i.end.row+1,i=t.getNextFoldLine(a,i),s=i?i.start.row:Infinity);if(a>r){while(this.$lines.getLength()>u+1)this.$lines.pop();break}o=this.$lines.get(++u),o?o.row=a:(o=this.$lines.createCell(a,e,this.session,l),this.$lines.push(o)),this.$renderCell(o,e,i,a),a++}this._signal(\"afterRender\"),this.$updateGutterWidth(e)},e.prototype.$updateGutterWidth=function(e){var t=this.session,n=t.gutterRenderer||this.$renderer,r=t.$firstLineNumber,i=this.$lines.last()?this.$lines.last().text:\"\";if(this.$fixedWidth||t.$useWrapMode)i=t.getLength()+r-1;var s=n?n.getWidth(t,i,e):i.toString().length*e.characterWidth,o=this.$padding||this.$computePadding();s+=o.left+o.right,s!==this.gutterWidth&&!isNaN(s)&&(this.gutterWidth=s,this.element.parentNode.style.width=this.element.style.width=Math.ceil(this.gutterWidth)+\"px\",this._signal(\"changeGutterWidth\",s))},e.prototype.$updateCursorRow=function(){if(!this.$highlightGutterLine)return;var e=this.session.selection.getCursor();if(this.$cursorRow===e.row)return;this.$cursorRow=e.row},e.prototype.updateLineHighlight=function(){if(!this.$highlightGutterLine)return;var e=this.session.selection.cursor.row;this.$cursorRow=e;if(this.$cursorCell&&this.$cursorCell.row==e)return;this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace(\"ace_gutter-active-line \",\"\"));var t=this.$lines.cells;this.$cursorCell=null;for(var n=0;n<t.length;n++){var r=t[n];if(r.row>=this.$cursorRow){if(r.row>this.$cursorRow){var i=this.session.getFoldLine(this.$cursorRow);if(!(n>0&&i&&i.start.row==t[n-1].row))break;r=t[n-1]}r.element.className=\"ace_gutter-active-line \"+r.element.className,this.$cursorCell=r;break}}},e.prototype.scrollLines=function(e){var t=this.config;this.config=e,this.$updateCursorRow();if(this.$lines.pageChanged(t,e))return this.update(e);this.$lines.moveContainer(e);var n=Math.min(e.lastRow+e.gutterOffset,this.session.getLength()-1),r=this.oldLastRow;this.oldLastRow=n;if(!t||r<e.firstRow)return this.update(e);if(n<t.firstRow)return this.update(e);if(t.firstRow<e.firstRow)for(var i=this.session.getFoldedRowCount(t.firstRow,e.firstRow-1);i>0;i--)this.$lines.shift();if(r>n)for(var i=this.session.getFoldedRowCount(n+1,r);i>0;i--)this.$lines.pop();e.firstRow<t.firstRow&&this.$lines.unshift(this.$renderLines(e,e.firstRow,t.firstRow-1)),n>r&&this.$lines.push(this.$renderLines(e,r+1,n)),this.updateLineHighlight(),this._signal(\"afterRender\"),this.$updateGutterWidth(e)},e.prototype.$renderLines=function(e,t,n){var r=[],i=t,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>n)break;var u=this.$lines.createCell(i,e,this.session,l);this.$renderCell(u,e,s,i),r.push(u),i++}return r},e.prototype.$renderCell=function(e,t,n,i){var s=e.element,o=this.session,u=s.childNodes[0],f=s.childNodes[1],l=s.childNodes[2],c=l.firstChild,h=o.$firstLineNumber,p=o.$breakpoints,d=o.$decorations,v=o.gutterRenderer||this.$renderer,m=this.$showFoldWidgets&&o.foldWidgets,g=n?n.start.row:Number.MAX_VALUE,y=t.lineHeight+\"px\",b=this.$useSvgGutterIcons?\"ace_gutter-cell_svg-icons \":\"ace_gutter-cell \",w=this.$useSvgGutterIcons?\"ace_icon_svg\":\"ace_icon\",E=(v?v.getText(o,i):i+h).toString();this.$highlightGutterLine&&(i==this.$cursorRow||n&&i<this.$cursorRow&&i>=g&&this.$cursorRow<=n.end.row)&&(b+=\"ace_gutter-active-line \",this.$cursorCell!=e&&(this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace(\"ace_gutter-active-line \",\"\")),this.$cursorCell=e)),p[i]&&(b+=p[i]),d[i]&&(b+=d[i]),this.$annotations[i]&&i!==g&&(b+=this.$annotations[i].className),s.className!=b&&(s.className=b);if(m){var S=m[i];S==null&&(S=m[i]=o.getFoldWidget(i))}if(S){var b=\"ace_fold-widget ace_\"+S;if(S==\"start\"&&i==g&&i<n.end.row){b+=\" ace_closed\";var x,T=!1;for(var N=i+1;N<=n.end.row;N++){if(!this.$annotations[N])continue;if(this.$annotations[N].className===\" ace_error\"){T=!0,x=\" ace_error_fold\";break}if(this.$annotations[N].className===\" ace_warning\"){T=!0,x=\" ace_warning_fold\";continue}}s.className+=x}else b+=\" ace_open\";f.className!=b&&(f.className=b),r.setStyle(f.style,\"height\",y),r.setStyle(f.style,\"display\",\"inline-block\"),f.setAttribute(\"role\",\"button\"),f.setAttribute(\"tabindex\",\"-1\");var n=o.getFoldLine(E-1);n?(f.setAttribute(\"aria-label\",a(\"Unfold rows $0 to $1\",[E,n.end.row+1])),f.setAttribute(\"title\",a(\"Unfold code\"))):(f.setAttribute(\"aria-label\",a(\"Fold at row $0\",[E])),f.setAttribute(\"title\",a(\"Fold code\")))}else f&&(r.setStyle(f.style,\"display\",\"none\"),f.setAttribute(\"tabindex\",\"0\"),f.removeAttribute(\"role\"),f.removeAttribute(\"aria-label\"));return T&&this.$showFoldedAnnotations?(l.className=\"ace_gutter_annotation\",c.className=w,c.className+=x,r.setStyle(c.style,\"height\",y),r.setStyle(l.style,\"display\",\"block\"),r.setStyle(l.style,\"height\",y),l.setAttribute(\"aria-label\",a(\"Read annotations row $0\",[E])),l.setAttribute(\"tabindex\",\"-1\"),l.setAttribute(\"role\",\"button\")):this.$annotations[i]?(l.className=\"ace_gutter_annotation\",c.className=w,this.$useSvgGutterIcons?c.className+=this.$annotations[i].className:s.classList.add(this.$annotations[i].className.replace(\" \",\"\")),r.setStyle(c.style,\"height\",y),r.setStyle(l.style,\"display\",\"block\"),r.setStyle(l.style,\"height\",y),l.setAttribute(\"aria-label\",a(\"Read annotations row $0\",[E])),l.setAttribute(\"tabindex\",\"-1\"),l.setAttribute(\"role\",\"button\")):(r.setStyle(l.style,\"display\",\"none\"),l.removeAttribute(\"aria-label\"),l.removeAttribute(\"role\"),l.setAttribute(\"tabindex\",\"0\")),E!==u.data&&(u.data=E),r.setStyle(e.element.style,\"height\",this.$lines.computeLineHeight(i,t,o)+\"px\"),r.setStyle(e.element.style,\"top\",this.$lines.computeLineTop(i,t,o)+\"px\"),e.text=E,l.style.display===\"none\"&&f.style.display===\"none\"?e.element.setAttribute(\"aria-hidden\",!0):e.element.setAttribute(\"aria-hidden\",!1),e},e.prototype.setHighlightGutterLine=function(e){this.$highlightGutterLine=e},e.prototype.setShowLineNumbers=function(e){this.$renderer=!e&&{getWidth:function(){return 0},getText:function(){return\"\"}}},e.prototype.getShowLineNumbers=function(){return this.$showLineNumbers},e.prototype.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,\"ace_folding-enabled\"):r.removeCssClass(this.element,\"ace_folding-enabled\"),this.$showFoldWidgets=e,this.$padding=null},e.prototype.getShowFoldWidgets=function(){return this.$showFoldWidgets},e.prototype.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=(parseInt(e.borderLeftWidth)||0)+(parseInt(e.paddingLeft)||0)+1,this.$padding.right=(parseInt(e.borderRightWidth)||0)+(parseInt(e.paddingRight)||0),this.$padding},e.prototype.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.x<t.left+n.left)return\"markers\";if(this.$showFoldWidgets&&e.x>n.right-t.right)return\"foldWidgets\"},e}();f.prototype.$fixedWidth=!1,f.prototype.$highlightGutterLine=!0,f.prototype.$renderer=\"\",f.prototype.$showLineNumbers=!0,f.prototype.$showFoldWidgets=!0,i.implement(f.prototype,o),t.Gutter=f}),define(\"ace/layer/marker\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";function o(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}var r=e(\"../range\").Range,i=e(\"../lib/dom\"),s=function(){function e(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_layer ace_marker-layer\",e.appendChild(this.element)}return e.prototype.setPadding=function(e){this.$padding=e},e.prototype.setSession=function(e){this.session=e},e.prototype.setMarkers=function(e){this.markers=e},e.prototype.elt=function(e,t){var n=this.i!=-1&&this.element.childNodes[this.i];n?this.i++:(n=document.createElement(\"div\"),this.element.appendChild(n),this.i=-1),n.style.cssText=t,n.className=e},e.prototype.update=function(e){if(!e)return;this.config=e,this.i=0;var t;for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+i.start.column*e.characterWidth;r.renderer(t,i,o,s,e)}else r.type==\"fullLine\"?this.drawFullLineMarker(t,i,r.clazz,e):r.type==\"screenLine\"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type==\"text\"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.drawSingleLineMarker(t,i,r.clazz+\" ace_start\"+\" ace_br15\",e)}if(this.i!=-1)while(this.i<this.element.childElementCount)this.element.removeChild(this.element.lastChild)},e.prototype.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},e.prototype.drawTextMarker=function(e,t,n,i,s){var u=this.session,a=t.start.row,f=t.end.row,l=a,c=0,h=0,p=u.getScreenLastRowColumn(l),d=new r(l,t.start.column,l,h);for(;l<=f;l++)d.start.row=d.end.row=l,d.start.column=l==a?t.start.column:u.getRowWrapIndent(l),d.end.column=p,c=h,h=p,p=l+1<f?u.getScreenLastRowColumn(l+1):l==f?0:t.end.column,this.drawSingleLineMarker(e,d,n+(l==a?\" ace_start\":\"\")+\" ace_br\"+o(l==a||l==a+1&&t.start.column,c<h,h>p,l==f),i,l==f?0:1,s)},e.prototype.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth;i=i||\"\";if(this.session.$bidiHandler.isBidiRow(t.start.row)){var f=t.clone();f.end.row=f.start.row,f.end.column=this.session.getLine(f.start.row).length,this.drawBidiSingleLineMarker(e,f,n+\" ace_br1 ace_start\",r,null,i)}else this.elt(n+\" ace_br1 ace_start\",\"height:\"+o+\"px;\"+\"right:0;\"+\"top:\"+u+\"px;left:\"+a+\"px;\"+(i||\"\"));if(this.session.$bidiHandler.isBidiRow(t.end.row)){var f=t.clone();f.start.row=f.end.row,f.start.column=0,this.drawBidiSingleLineMarker(e,f,n+\" ace_br12\",r,null,i)}else{u=this.$getTop(t.end.row,r);var l=t.end.column*r.characterWidth;this.elt(n+\" ace_br12\",\"height:\"+o+\"px;\"+\"width:\"+l+\"px;\"+\"top:\"+u+\"px;\"+\"left:\"+s+\"px;\"+(i||\"\"))}o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var c=(t.start.column?1:0)|(t.end.column?0:8);this.elt(n+(c?\" ace_br\"+c:\"\"),\"height:\"+o+\"px;\"+\"right:0;\"+\"top:\"+u+\"px;\"+\"left:\"+s+\"px;\"+(i||\"\"))},e.prototype.drawSingleLineMarker=function(e,t,n,r,i,s){if(this.session.$bidiHandler.isBidiRow(t.start.row))return this.drawBidiSingleLineMarker(e,t,n,r,i,s);var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;this.elt(n,\"height:\"+o+\"px;\"+\"width:\"+u+\"px;\"+\"top:\"+a+\"px;\"+\"left:\"+f+\"px;\"+(s||\"\"))},e.prototype.drawBidiSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=this.$getTop(t.start.row,r),a=this.$padding,f=this.session.$bidiHandler.getSelections(t.start.column,t.end.column);f.forEach(function(e){this.elt(n,\"height:\"+o+\"px;\"+\"width:\"+(e.width+(i||0))+\"px;\"+\"top:\"+u+\"px;\"+\"left:\"+(a+e.left)+\"px;\"+(s||\"\"))},this)},e.prototype.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),this.elt(n,\"height:\"+o+\"px;\"+\"top:\"+s+\"px;\"+\"left:0;right:0;\"+(i||\"\"))},e.prototype.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;this.elt(n,\"height:\"+o+\"px;\"+\"top:\"+s+\"px;\"+\"left:0;right:0;\"+(i||\"\"))},e}();s.prototype.$padding=0,t.Marker=s}),define(\"ace/layer/text\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/layer/lines\",\"ace/lib/event_emitter\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"./lines\").Lines,u=e(\"../lib/event_emitter\").EventEmitter,a=e(\"../config\").nls,f=function(){function e(e){this.dom=i,this.element=this.dom.createElement(\"div\"),this.element.className=\"ace_layer ace_text-layer\",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this),this.$lines=new o(this.element)}return e.prototype.$updateEolChar=function(){var e=this.session.doc,t=e.getNewLineCharacter()==\"\\n\"&&e.getNewLineMode()!=\"windows\",n=t?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=n)return this.EOL_CHAR=n,!0},e.prototype.setPadding=function(e){this.$padding=e,this.element.style.margin=\"0 \"+e+\"px\"},e.prototype.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},e.prototype.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},e.prototype.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on(\"changeCharacterSize\",function(e){this._signal(\"changeCharacterSize\",e)}.bind(this)),this.$pollSizeChanges()},e.prototype.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},e.prototype.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},e.prototype.setSession=function(e){this.session=e,e&&this.$computeTabString()},e.prototype.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,typeof e==\"string\"?(this.showSpaces=/tab/i.test(e),this.showTabs=/space/i.test(e),this.showEOL=/eol/i.test(e)):this.showSpaces=this.showTabs=this.showEOL=e,this.$computeTabString(),!0)},e.prototype.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},e.prototype.setHighlightIndentGuides=function(e){return this.$highlightIndentGuides===e?!1:(this.$highlightIndentGuides=e,e)},e.prototype.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n<e+1;n++)if(this.showTabs){var r=this.dom.createElement(\"span\");r.className=\"ace_invisible ace_invisible_tab\",r.textContent=s.stringRepeat(this.TAB_CHAR,n),t.push(r)}else t.push(this.dom.createTextNode(s.stringRepeat(\" \",n),this.element));if(this.displayIndentGuides){this.$indentGuideRe=/\\s\\S| \\t|\\t |\\s$/;var i=\"ace_indent-guide\",o=this.showSpaces?\" ace_invisible ace_invisible_space\":\"\",u=this.showSpaces?s.stringRepeat(this.SPACE_CHAR,this.tabSize):s.stringRepeat(\" \",this.tabSize),a=this.showTabs?\" ace_invisible ace_invisible_tab\":\"\",f=this.showTabs?s.stringRepeat(this.TAB_CHAR,this.tabSize):u,r=this.dom.createElement(\"span\");r.className=i+o,r.textContent=u,this.$tabStrings[\" \"]=r;var r=this.dom.createElement(\"span\");r.className=i+a,r.textContent=f,this.$tabStrings[\"\t\"]=r}},e.prototype.updateLines=function(e,t,n){if(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)return this.update(e);this.config=e;var r=Math.max(t,e.firstRow),i=Math.min(n,e.lastRow),s=this.element.childNodes,o=0;for(var u=e.firstRow;u<r;u++){var a=this.session.getFoldLine(u);if(a){if(a.containsRow(r)){r=a.start.row;break}u=a.end.row}o++}var f=!1,u=r,a=this.session.getNextFoldLine(u),l=a?a.start.row:Infinity;for(;;){u>l&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),l=a?a.start.row:Infinity);if(u>i)break;var c=s[o++];if(c){this.dom.removeChildren(c),this.$renderLine(c,u,u==l?a:!1),f&&(c.style.top=this.$lines.computeLineTop(u,e,this.session)+\"px\");var h=e.lineHeight*this.session.getRowLength(u)+\"px\";c.style.height!=h&&(f=!0,c.style.height=h)}u++}if(f)while(o<this.$lines.cells.length){var p=this.$lines.cells[o++];p.element.style.top=this.$lines.computeLineTop(p.row,e,this.session)+\"px\"}},e.prototype.scrollLines=function(e){var t=this.config;this.config=e;if(this.$lines.pageChanged(t,e))return this.update(e);this.$lines.moveContainer(e);var n=e.lastRow,r=t?t.lastRow:-1;if(!t||r<e.firstRow)return this.update(e);if(n<t.firstRow)return this.update(e);if(!t||t.lastRow<e.firstRow)return this.update(e);if(e.lastRow<t.firstRow)return this.update(e);if(t.firstRow<e.firstRow)for(var i=this.session.getFoldedRowCount(t.firstRow,e.firstRow-1);i>0;i--)this.$lines.shift();if(t.lastRow>e.lastRow)for(var i=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);i>0;i--)this.$lines.pop();e.firstRow<t.firstRow&&this.$lines.unshift(this.$renderLinesFragment(e,e.firstRow,t.firstRow-1)),e.lastRow>t.lastRow&&this.$lines.push(this.$renderLinesFragment(e,t.lastRow+1,e.lastRow)),this.$highlightIndentGuide()},e.prototype.$renderLinesFragment=function(e,t,n){var r=[],s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=this.$lines.createCell(s,e,this.session),f=a.element;this.dom.removeChildren(f),i.setStyle(f.style,\"height\",this.$lines.computeLineHeight(s,e,this.session)+\"px\"),i.setStyle(f.style,\"top\",this.$lines.computeLineTop(s,e,this.session)+\"px\"),this.$renderLine(f,s,s==u?o:!1),this.$useLineGroups()?f.className=\"ace_line_group\":f.className=\"ace_line\",r.push(a),s++}return r},e.prototype.update=function(e){this.$lines.moveContainer(e),this.config=e;var t=e.firstRow,n=e.lastRow,r=this.$lines;while(r.getLength())r.pop();r.push(this.$renderLinesFragment(e,t,n))},e.prototype.$renderToken=function(e,t,n,r){var i=this,o=/(\\t)|( +)|([\\x00-\\x1f\\x80-\\xa0\\xad\\u1680\\u180E\\u2000-\\u200f\\u2028\\u2029\\u202F\\u205F\\uFEFF\\uFFF9-\\uFFFC\\u2066\\u2067\\u2068\\u202A\\u202B\\u202D\\u202E\\u202C\\u2069]+)|(\\u3000)|([\\u1100-\\u115F\\u11A3-\\u11A7\\u11FA-\\u11FF\\u2329-\\u232A\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u2FF0-\\u2FFB\\u3001-\\u303E\\u3041-\\u3096\\u3099-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u3190-\\u31BA\\u31C0-\\u31E3\\u31F0-\\u321E\\u3220-\\u3247\\u3250-\\u32FE\\u3300-\\u4DBF\\u4E00-\\uA48C\\uA490-\\uA4C6\\uA960-\\uA97C\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFAFF\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE66\\uFE68-\\uFE6B\\uFF01-\\uFF60\\uFFE0-\\uFFE6]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF])/g,u=this.dom.createFragment(this.element),f,l=0;while(f=o.exec(r)){var c=f[1],h=f[2],p=f[3],d=f[4],v=f[5];if(!i.showSpaces&&h)continue;var m=l!=f.index?r.slice(l,f.index):\"\";l=f.index+f[0].length,m&&u.appendChild(this.dom.createTextNode(m,this.element));if(c){var g=i.session.getScreenTabSize(t+f.index);u.appendChild(i.$tabStrings[g].cloneNode(!0)),t+=g-1}else if(h)if(i.showSpaces){var y=this.dom.createElement(\"span\");y.className=\"ace_invisible ace_invisible_space\",y.textContent=s.stringRepeat(i.SPACE_CHAR,h.length),u.appendChild(y)}else u.appendChild(this.com.createTextNode(h,this.element));else if(p){var y=this.dom.createElement(\"span\");y.className=\"ace_invisible ace_invisible_space ace_invalid\",y.textContent=s.stringRepeat(i.SPACE_CHAR,p.length),u.appendChild(y)}else if(d){t+=1;var y=this.dom.createElement(\"span\");y.style.width=i.config.characterWidth*2+\"px\",y.className=i.showSpaces?\"ace_cjk ace_invisible ace_invisible_space\":\"ace_cjk\",y.textContent=i.showSpaces?i.SPACE_CHAR:d,u.appendChild(y)}else if(v){t+=1;var y=this.dom.createElement(\"span\");y.style.width=i.config.characterWidth*2+\"px\",y.className=\"ace_cjk\",y.textContent=v,u.appendChild(y)}}u.appendChild(this.dom.createTextNode(l?r.slice(l):r,this.element));if(!this.$textToken[n.type]){var b=\"ace_\"+n.type.replace(/\\./g,\" ace_\"),y=this.dom.createElement(\"span\");n.type==\"fold\"&&(y.style.width=n.value.length*this.config.characterWidth+\"px\",y.setAttribute(\"title\",a(\"Unfold code\"))),y.className=b,y.appendChild(u),e.appendChild(y)}else e.appendChild(u);return t+r.length},e.prototype.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);if(r<=0||r>=n)return t;if(t[0]==\" \"){r-=r%this.tabSize;var i=r/this.tabSize;for(var s=0;s<i;s++)e.appendChild(this.$tabStrings[\" \"].cloneNode(!0));return this.$highlightIndentGuide(),t.substr(r)}if(t[0]==\"\t\"){for(var s=0;s<r;s++)e.appendChild(this.$tabStrings[\"\t\"].cloneNode(!0));return this.$highlightIndentGuide(),t.substr(r)}return this.$highlightIndentGuide(),t},e.prototype.$highlightIndentGuide=function(){if(!this.$highlightIndentGuides||!this.displayIndentGuides)return;this.$highlightIndentGuideMarker={indentLevel:undefined,start:undefined,end:undefined,dir:undefined};var e=this.session.doc.$lines;if(!e)return;var t=this.session.selection.getCursor(),n=/^\\s*/.exec(this.session.doc.getLine(t.row))[0].length,r=Math.floor(n/this.tabSize);this.$highlightIndentGuideMarker={indentLevel:r,start:t.row};var i=this.session.$bracketHighlight;if(i){var s=this.session.$bracketHighlight.ranges;for(var o=0;o<s.length;o++)if(t.row!==s[o].start.row){this.$highlightIndentGuideMarker.end=s[o].start.row,t.row>s[o].start.row?this.$highlightIndentGuideMarker.dir=-1:this.$highlightIndentGuideMarker.dir=1;break}}if(!this.$highlightIndentGuideMarker.end&&e[t.row]!==\"\"&&t.column===e[t.row].length){this.$highlightIndentGuideMarker.dir=1;for(var o=t.row+1;o<e.length;o++){var u=e[o],a=/^\\s*/.exec(u)[0].length;if(u!==\"\"){this.$highlightIndentGuideMarker.end=o;if(a<=n)break}}}this.$renderHighlightIndentGuide()},e.prototype.$clearActiveIndentGuide=function(){var e=this.$lines.cells;for(var t=0;t<e.length;t++){var n=e[t],r=n.element.childNodes;if(r.length>0)for(var i=0;i<r.length;i++)if(r[i].classList&&r[i].classList.contains(\"ace_indent-guide-active\")){r[i].classList.remove(\"ace_indent-guide-active\");break}}},e.prototype.$setIndentGuideActive=function(e,t){var n=this.session.doc.getLine(e.row);if(n!==\"\"){var r=e.element.childNodes;if(r){var i=r[t-1];i&&i.classList&&i.classList.contains(\"ace_indent-guide\")&&i.classList.add(\"ace_indent-guide-active\")}}},e.prototype.$renderHighlightIndentGuide=function(){if(!this.$lines)return;var e=this.$lines.cells;this.$clearActiveIndentGuide();var t=this.$highlightIndentGuideMarker.indentLevel;if(t!==0)if(this.$highlightIndentGuideMarker.dir===1)for(var n=0;n<e.length;n++){var r=e[n];if(this.$highlightIndentGuideMarker.end&&r.row>=this.$highlightIndentGuideMarker.start+1){if(r.row>=this.$highlightIndentGuideMarker.end)break;this.$setIndentGuideActive(r,t)}}else for(var n=e.length-1;n>=0;n--){var r=e[n];if(this.$highlightIndentGuideMarker.end&&r.row<this.$highlightIndentGuideMarker.start){if(r.row<=this.$highlightIndentGuideMarker.end)break;this.$setIndentGuideActive(r,t)}}},e.prototype.$createLineElement=function(e){var t=this.dom.createElement(\"div\");return t.className=\"ace_line\",t.style.height=this.config.lineHeight+\"px\",t},e.prototype.$renderWrappedLine=function(e,t,n){var r=0,i=0,o=n[0],u=0,a=this.$createLineElement();e.appendChild(a);for(var f=0;f<t.length;f++){var l=t[f],c=l.value;if(f==0&&this.displayIndentGuides){r=c.length,c=this.renderIndentGuide(a,c,o);if(!c)continue;r-=c.length}if(r+c.length<o)u=this.$renderToken(a,u,l,c),r+=c.length;else{while(r+c.length>=o)u=this.$renderToken(a,u,l,c.substring(0,o-r)),c=c.substring(o-r),r=o,a=this.$createLineElement(),e.appendChild(a),a.appendChild(this.dom.createTextNode(s.stringRepeat(\"\\u00a0\",n.indent),this.element)),i++,u=0,o=n[i]||Number.MAX_VALUE;c.length!=0&&(r+=c.length,u=this.$renderToken(a,u,l,c))}}n[n.length-1]>this.MAX_LINE_LENGTH&&this.$renderOverflowMessage(a,u,null,\"\",!0)},e.prototype.$renderSimpleLine=function(e,t){var n=0;for(var r=0;r<t.length;r++){var i=t[r],s=i.value;if(r==0&&this.displayIndentGuides){s=this.renderIndentGuide(e,s);if(!s)continue}if(n+s.length>this.MAX_LINE_LENGTH)return this.$renderOverflowMessage(e,n,i,s);n=this.$renderToken(e,n,i,s)}},e.prototype.$renderOverflowMessage=function(e,t,n,r,i){n&&this.$renderToken(e,t,n,r.slice(0,this.MAX_LINE_LENGTH-t));var s=this.dom.createElement(\"span\");s.className=\"ace_inline_button ace_keyword ace_toggle_wrap\",s.textContent=i?\"<hide>\":\"<click to see more...>\",e.appendChild(s)},e.prototype.$renderLine=function(e,t,n){!n&&n!=0&&(n=this.session.getFoldLine(t));if(n)var r=this.$getFoldLineTokens(t,n);else var r=this.session.getTokens(t);var i=e;if(r.length){var s=this.session.getRowSplitData(t);if(s&&s.length){this.$renderWrappedLine(e,r,s);var i=e.lastChild}else{var i=e;this.$useLineGroups()&&(i=this.$createLineElement(),e.appendChild(i)),this.$renderSimpleLine(i,r)}}else this.$useLineGroups()&&(i=this.$createLineElement(),e.appendChild(i));if(this.showEOL&&i){n&&(t=n.end.row);var o=this.dom.createElement(\"span\");o.className=\"ace_invisible ace_invisible_eol\",o.textContent=t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,i.appendChild(o)}},e.prototype.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.length<t){s+=e[i].value.length,i++;if(i==e.length)return}if(s!=t){var o=e[i].value.substring(t-s);o.length>n-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(s<n&&i<e.length){var o=e[i].value;o.length+s>n?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:\"fold\",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},e.prototype.$useLineGroups=function(){return this.session.getUseWrapMode()},e}();f.prototype.$textToken={text:!0,rparen:!0,lparen:!0},f.prototype.EOF_CHAR=\"\\u00b6\",f.prototype.EOL_CHAR_LF=\"\\u00ac\",f.prototype.EOL_CHAR_CRLF=\"\\u00a4\",f.prototype.EOL_CHAR=f.prototype.EOL_CHAR_LF,f.prototype.TAB_CHAR=\"\\u2014\",f.prototype.SPACE_CHAR=\"\\u00b7\",f.prototype.$padding=0,f.prototype.MAX_LINE_LENGTH=1e4,f.prototype.showInvisibles=!1,f.prototype.showSpaces=!1,f.prototype.showTabs=!1,f.prototype.showEOL=!1,f.prototype.displayIndentGuides=!0,f.prototype.$highlightIndentGuides=!0,f.prototype.$tabStrings=[],f.prototype.destroy={},f.prototype.onChangeTabSize=f.prototype.$computeTabString,r.implement(f.prototype,u),t.Text=f}),define(\"ace/layer/cursor\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=function(){function e(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_cursor-layer\",e.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,\"ace_hidden-cursors\"),this.$updateCursors=this.$updateOpacity.bind(this)}return e.prototype.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)r.setStyle(t[n].style,\"opacity\",e?\"\":\"0\")},e.prototype.$startCssAnimation=function(){var e=this.cursors;for(var t=e.length;t--;)e[t].style.animationDuration=this.blinkInterval+\"ms\";this.$isAnimating=!0,setTimeout(function(){this.$isAnimating&&r.addCssClass(this.element,\"ace_animate-blinking\")}.bind(this))},e.prototype.$stopCssAnimation=function(){this.$isAnimating=!1,r.removeCssClass(this.element,\"ace_animate-blinking\")},e.prototype.setPadding=function(e){this.$padding=e},e.prototype.setSession=function(e){this.session=e},e.prototype.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},e.prototype.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},e.prototype.setSmoothBlinking=function(e){e!=this.smoothBlinking&&(this.smoothBlinking=e,r.setCssClass(this.element,\"ace_smooth-blinking\",e),this.$updateCursors(!0),this.restartTimer())},e.prototype.addCursor=function(){var e=r.createElement(\"div\");return e.className=\"ace_cursor\",this.element.appendChild(e),this.cursors.push(e),e},e.prototype.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},e.prototype.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},e.prototype.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},e.prototype.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.$stopCssAnimation(),this.smoothBlinking&&(this.$isSmoothBlinking=!1,r.removeCssClass(this.element,\"ace_smooth-blinking\")),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible){this.$stopCssAnimation();return}this.smoothBlinking&&(this.$isSmoothBlinking=!0,setTimeout(function(){this.$isSmoothBlinking&&r.addCssClass(this.element,\"ace_smooth-blinking\")}.bind(this)));if(r.HAS_CSS_ANIMATION)this.$startCssAnimation();else{var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()}},e.prototype.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+(this.session.$bidiHandler.isBidiRow(n.row,e.row)?this.session.$bidiHandler.getPosLeft(n.column):n.column*this.config.characterWidth),i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},e.prototype.isCursorInView=function(e,t){return e.top>=0&&e.top<t.maxHeight},e.prototype.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,i=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=0,s=t.length;n<s;n++){var o=this.getPixelPosition(t[n].cursor,!0);if((o.top>e.height+e.offset||o.top<0)&&n>1)continue;var u=this.cursors[i++]||this.addCursor(),a=u.style;this.drawCursor?this.drawCursor(u,o,e,t[n],this.session):this.isCursorInView(o,e)?(r.setStyle(a,\"display\",\"block\"),r.translate(u,o.left,o.top),r.setStyle(a,\"width\",Math.round(e.characterWidth)+\"px\"),r.setStyle(a,\"height\",e.lineHeight+\"px\")):r.setStyle(a,\"display\",\"none\")}while(this.cursors.length>i)this.removeCursor();var f=this.session.getOverwrite();this.$setOverwrite(f),this.$pixelPos=o,this.restartTimer()},e.prototype.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,\"ace_overwrite-cursors\"):r.removeCssClass(this.element,\"ace_overwrite-cursors\"))},e.prototype.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)},e}();i.prototype.$padding=0,i.prototype.drawCursor=null,t.Cursor=i}),define(\"ace/scrollbar\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=e(\"./lib/oop\"),s=e(\"./lib/dom\"),o=e(\"./lib/event\"),u=e(\"./lib/event_emitter\").EventEmitter,a=32768,f=function(){function e(e,t){this.element=s.createElement(\"div\"),this.element.className=\"ace_scrollbar ace_scrollbar\"+t,this.inner=s.createElement(\"div\"),this.inner.className=\"ace_scrollbar-inner\",this.inner.textContent=\"\\u00a0\",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,o.addListener(this.element,\"scroll\",this.onScroll.bind(this)),o.addListener(this.element,\"mousedown\",o.preventDefault)}return e.prototype.setVisible=function(e){this.element.style.display=e?\"\":\"none\",this.isVisible=e,this.coeff=1},e}();i.implement(f.prototype,u);var l=function(e){function t(t,n){var r=e.call(this,t,\"-v\")||this;return r.scrollTop=0,r.scrollHeight=0,n.$scrollbarWidth=r.width=s.scrollbarWidth(t.ownerDocument),r.inner.style.width=r.element.style.width=(r.width||15)+5+\"px\",r.$minWidth=0,r}return r(t,e),t.prototype.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit(\"scroll\",{data:this.scrollTop})}this.skipEvent=!1},t.prototype.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},t.prototype.setHeight=function(e){this.element.style.height=e+\"px\"},t.prototype.setScrollHeight=function(e){this.scrollHeight=e,e>a?(this.coeff=a/e,e=a):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+\"px\"},t.prototype.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)},t}(f);l.prototype.setInnerHeight=l.prototype.setScrollHeight;var c=function(e){function t(t,n){var r=e.call(this,t,\"-h\")||this;return r.scrollLeft=0,r.height=n.$scrollbarWidth,r.inner.style.height=r.element.style.height=(r.height||15)+5+\"px\",r}return r(t,e),t.prototype.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit(\"scroll\",{data:this.scrollLeft})),this.skipEvent=!1},t.prototype.getHeight=function(){return this.isVisible?this.height:0},t.prototype.setWidth=function(e){this.element.style.width=e+\"px\"},t.prototype.setInnerWidth=function(e){this.inner.style.width=e+\"px\"},t.prototype.setScrollWidth=function(e){this.inner.style.width=e+\"px\"},t.prototype.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)},t}(f);t.ScrollBar=l,t.ScrollBarV=l,t.ScrollBarH=c,t.VScrollBar=l,t.HScrollBar=c}),define(\"ace/scrollbar_custom\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=this&&this.__extends||function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){function r(){this.constructor=t}if(typeof n!=\"function\"&&n!==null)throw new TypeError(\"Class extends value \"+String(n)+\" is not a constructor or null\");e(t,n),t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=e(\"./lib/oop\"),s=e(\"./lib/dom\"),o=e(\"./lib/event\"),u=e(\"./lib/event_emitter\").EventEmitter;s.importCssString(\".ace_editor>.ace_sb-v div, .ace_editor>.ace_sb-h div{\\n  position: absolute;\\n  background: rgba(128, 128, 128, 0.6);\\n  -moz-box-sizing: border-box;\\n  box-sizing: border-box;\\n  border: 1px solid #bbb;\\n  border-radius: 2px;\\n  z-index: 8;\\n}\\n.ace_editor>.ace_sb-v, .ace_editor>.ace_sb-h {\\n  position: absolute;\\n  z-index: 6;\\n  background: none;\\n  overflow: hidden!important;\\n}\\n.ace_editor>.ace_sb-v {\\n  z-index: 6;\\n  right: 0;\\n  top: 0;\\n  width: 12px;\\n}\\n.ace_editor>.ace_sb-v div {\\n  z-index: 8;\\n  right: 0;\\n  width: 100%;\\n}\\n.ace_editor>.ace_sb-h {\\n  bottom: 0;\\n  left: 0;\\n  height: 12px;\\n}\\n.ace_editor>.ace_sb-h div {\\n  bottom: 0;\\n  height: 100%;\\n}\\n.ace_editor>.ace_sb_grabbed {\\n  z-index: 8;\\n  background: #000;\\n}\",\"ace_scrollbar.css\",!1);var a=function(){function e(e,t){this.element=s.createElement(\"div\"),this.element.className=\"ace_sb\"+t,this.inner=s.createElement(\"div\"),this.inner.className=\"\",this.element.appendChild(this.inner),this.VScrollWidth=12,this.HScrollHeight=12,e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,o.addMultiMouseDownListener(this.element,[500,300,300],this,\"onMouseDown\")}return e.prototype.setVisible=function(e){this.element.style.display=e?\"\":\"none\",this.isVisible=e,this.coeff=1},e}();i.implement(a.prototype,u);var f=function(e){function t(t,n){var r=e.call(this,t,\"-v\")||this;return r.scrollTop=0,r.scrollHeight=0,r.parent=t,r.width=r.VScrollWidth,r.renderer=n,r.inner.style.width=r.element.style.width=(r.width||15)+\"px\",r.$minWidth=0,r}return r(t,e),t.prototype.onMouseDown=function(e,t){if(e!==\"mousedown\")return;if(o.getButton(t)!==0||t.detail===2)return;if(t.target===this.inner){var n=this,r=t.clientY,i=function(e){r=e.clientY},s=function(){clearInterval(l)},u=t.clientY,a=this.thumbTop,f=function(){if(r===undefined)return;var e=n.scrollTopFromThumbTop(a+r-u);if(e===n.scrollTop)return;n._emit(\"scroll\",{data:e})};o.capture(this.inner,i,s);var l=setInterval(f,20);return o.preventDefault(t)}var c=t.clientY-this.element.getBoundingClientRect().top-this.thumbHeight/2;return this._emit(\"scroll\",{data:this.scrollTopFromThumbTop(c)}),o.preventDefault(t)},t.prototype.getHeight=function(){return this.height},t.prototype.scrollTopFromThumbTop=function(e){var t=e*(this.pageHeight-this.viewHeight)/(this.slideHeight-this.thumbHeight);return t>>=0,t<0?t=0:t>this.pageHeight-this.viewHeight&&(t=this.pageHeight-this.viewHeight),t},t.prototype.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},t.prototype.setHeight=function(e){this.height=Math.max(0,e),this.slideHeight=this.height,this.viewHeight=this.height,this.setScrollHeight(this.pageHeight,!0)},t.prototype.setScrollHeight=function(e,t){if(this.pageHeight===e&&!t)return;this.pageHeight=e,this.thumbHeight=this.slideHeight*this.viewHeight/this.pageHeight,this.thumbHeight>this.slideHeight&&(this.thumbHeight=this.slideHeight),this.thumbHeight<15&&(this.thumbHeight=15),this.inner.style.height=this.thumbHeight+\"px\",this.scrollTop>this.pageHeight-this.viewHeight&&(this.scrollTop=this.pageHeight-this.viewHeight,this.scrollTop<0&&(this.scrollTop=0),this._emit(\"scroll\",{data:this.scrollTop}))},t.prototype.setScrollTop=function(e){this.scrollTop=e,e<0&&(e=0),this.thumbTop=e*(this.slideHeight-this.thumbHeight)/(this.pageHeight-this.viewHeight),this.inner.style.top=this.thumbTop+\"px\"},t}(a);f.prototype.setInnerHeight=f.prototype.setScrollHeight;var l=function(e){function t(t,n){var r=e.call(this,t,\"-h\")||this;return r.scrollLeft=0,r.scrollWidth=0,r.height=r.HScrollHeight,r.inner.style.height=r.element.style.height=(r.height||12)+\"px\",r.renderer=n,r}return r(t,e),t.prototype.onMouseDown=function(e,t){if(e!==\"mousedown\")return;if(o.getButton(t)!==0||t.detail===2)return;if(t.target===this.inner){var n=this,r=t.clientX,i=function(e){r=e.clientX},s=function(){clearInterval(l)},u=t.clientX,a=this.thumbLeft,f=function(){if(r===undefined)return;var e=n.scrollLeftFromThumbLeft(a+r-u);if(e===n.scrollLeft)return;n._emit(\"scroll\",{data:e})};o.capture(this.inner,i,s);var l=setInterval(f,20);return o.preventDefault(t)}var c=t.clientX-this.element.getBoundingClientRect().left-this.thumbWidth/2;return this._emit(\"scroll\",{data:this.scrollLeftFromThumbLeft(c)}),o.preventDefault(t)},t.prototype.getHeight=function(){return this.isVisible?this.height:0},t.prototype.scrollLeftFromThumbLeft=function(e){var t=e*(this.pageWidth-this.viewWidth)/(this.slideWidth-this.thumbWidth);return t>>=0,t<0?t=0:t>this.pageWidth-this.viewWidth&&(t=this.pageWidth-this.viewWidth),t},t.prototype.setWidth=function(e){this.width=Math.max(0,e),this.element.style.width=this.width+\"px\",this.slideWidth=this.width,this.viewWidth=this.width,this.setScrollWidth(this.pageWidth,!0)},t.prototype.setScrollWidth=function(e,t){if(this.pageWidth===e&&!t)return;this.pageWidth=e,this.thumbWidth=this.slideWidth*this.viewWidth/this.pageWidth,this.thumbWidth>this.slideWidth&&(this.thumbWidth=this.slideWidth),this.thumbWidth<15&&(this.thumbWidth=15),this.inner.style.width=this.thumbWidth+\"px\",this.scrollLeft>this.pageWidth-this.viewWidth&&(this.scrollLeft=this.pageWidth-this.viewWidth,this.scrollLeft<0&&(this.scrollLeft=0),this._emit(\"scroll\",{data:this.scrollLeft}))},t.prototype.setScrollLeft=function(e){this.scrollLeft=e,e<0&&(e=0),this.thumbLeft=e*(this.slideWidth-this.thumbWidth)/(this.pageWidth-this.viewWidth),this.inner.style.left=this.thumbLeft+\"px\"},t}(a);l.prototype.setInnerWidth=l.prototype.setScrollWidth,t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define(\"ace/renderloop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"./lib/event\"),i=function(){function e(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.$recursionLimit=2,this.window=t||window;var n=this;this._flush=function(e){n.pending=!1;var t=n.changes;t&&(r.blockIdle(100),n.changes=0,n.onRender(t));if(n.changes){if(n.$recursionLimit--<0)return;n.schedule()}else n.$recursionLimit=2}}return e.prototype.schedule=function(e){this.changes=this.changes|e,this.changes&&!this.pending&&(r.nextFrame(this._flush),this.pending=!0)},e.prototype.clear=function(e){var t=this.changes;return this.changes=0,t},e}();t.RenderLoop=i}),define(\"ace/layer/font_metrics\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(e,t,n){var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"../lib/event\"),u=e(\"../lib/useragent\"),a=e(\"../lib/event_emitter\").EventEmitter,f=512,l=typeof ResizeObserver==\"function\",c=200,h=function(){function e(e){this.el=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),this.$measureNode.textContent=s.stringRepeat(\"X\",f),this.$characterSize={width:0,height:0},l?this.$addObserver():this.checkForSizeChanges()}return e.prototype.$setMeasureNodeStyles=function(e,t){e.width=e.height=\"auto\",e.left=e.top=\"0px\",e.visibility=\"hidden\",e.position=\"absolute\",e.whiteSpace=\"pre\",u.isIE<8?e[\"font-family\"]=\"inherit\":e.font=\"inherit\",e.overflow=t?\"hidden\":\"visible\"},e.prototype.checkForSizeChanges=function(e){e===undefined&&(e=this.$measureSizes());if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight=\"bold\";var t=this.$measureSizes();this.$measureNode.style.fontWeight=\"\",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit(\"changeCharacterSize\",{data:e})}},e.prototype.$addObserver=function(){var e=this;this.$observer=new window.ResizeObserver(function(t){e.checkForSizeChanges()}),this.$observer.observe(this.$measureNode)},e.prototype.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer||this.$observer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=o.onIdle(function t(){e.checkForSizeChanges(),o.onIdle(t,500)},500)},e.prototype.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},e.prototype.$measureSizes=function(e){var t={height:(e||this.$measureNode).clientHeight,width:(e||this.$measureNode).clientWidth/f};return t.width===0||t.height===0?null:t},e.prototype.$measureCharWidth=function(e){this.$main.textContent=s.stringRepeat(e,f);var t=this.$main.getBoundingClientRect();return t.width/f},e.prototype.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},e.prototype.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$observer&&this.$observer.disconnect(),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)},e.prototype.$getZoom=function(e){return!e||!e.parentElement?1:(window.getComputedStyle(e).zoom||1)*this.$getZoom(e.parentElement)},e.prototype.$initTransformMeasureNodes=function(){var e=function(e,t){return[\"div\",{style:\"position: absolute;top:\"+e+\"px;left:\"+t+\"px;\"}]};this.els=i.buildDom([e(0,0),e(c,0),e(0,c),e(c,c)],this.el)},e.prototype.transformCoordinates=function(e,t){function r(e,t,n){var r=e[1]*t[0]-e[0]*t[1];return[(-t[1]*n[0]+t[0]*n[1])/r,(+e[1]*n[0]-e[0]*n[1])/r]}function i(e,t){return[e[0]-t[0],e[1]-t[1]]}function s(e,t){return[e[0]+t[0],e[1]+t[1]]}function o(e,t){return[e*t[0],e*t[1]]}function u(e){var t=e.getBoundingClientRect();return[t.left,t.top]}if(e){var n=this.$getZoom(this.el);e=o(1/n,e)}this.els||this.$initTransformMeasureNodes();var a=u(this.els[0]),f=u(this.els[1]),l=u(this.els[2]),h=u(this.els[3]),p=r(i(h,f),i(h,l),i(s(f,l),s(h,a))),d=o(1+p[0],i(f,a)),v=o(1+p[1],i(l,a));if(t){var m=t,g=p[0]*m[0]/c+p[1]*m[1]/c+1,y=s(o(m[0],d),o(m[1],v));return s(o(1/g/c,y),a)}var b=i(e,a),w=r(i(d,o(p[0],b)),i(v,o(p[1],b)),b);return o(c,w)},e}();h.prototype.$characterSize={width:0,height:0},r.implement(h.prototype,a),t.FontMetrics=h}),define(\"ace/css/editor.css\",[\"require\",\"exports\",\"module\"],function(e,t,n){n.exports='\\n.ace_br1 {border-top-left-radius    : 3px;}\\n.ace_br2 {border-top-right-radius   : 3px;}\\n.ace_br3 {border-top-left-radius    : 3px; border-top-right-radius:    3px;}\\n.ace_br4 {border-bottom-right-radius: 3px;}\\n.ace_br5 {border-top-left-radius    : 3px; border-bottom-right-radius: 3px;}\\n.ace_br6 {border-top-right-radius   : 3px; border-bottom-right-radius: 3px;}\\n.ace_br7 {border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px;}\\n.ace_br8 {border-bottom-left-radius : 3px;}\\n.ace_br9 {border-top-left-radius    : 3px; border-bottom-left-radius:  3px;}\\n.ace_br10{border-top-right-radius   : 3px; border-bottom-left-radius:  3px;}\\n.ace_br11{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-left-radius:  3px;}\\n.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\\n.ace_br13{border-top-left-radius    : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\\n.ace_br14{border-top-right-radius   : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\\n.ace_br15{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\\n\\n\\n.ace_editor {\\n    position: relative;\\n    overflow: hidden;\\n    padding: 0;\\n    font: 12px/normal \\'Monaco\\', \\'Menlo\\', \\'Ubuntu Mono\\', \\'Consolas\\', \\'Source Code Pro\\', \\'source-code-pro\\', monospace;\\n    direction: ltr;\\n    text-align: left;\\n    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\\n}\\n\\n.ace_scroller {\\n    position: absolute;\\n    overflow: hidden;\\n    top: 0;\\n    bottom: 0;\\n    background-color: inherit;\\n    -ms-user-select: none;\\n    -moz-user-select: none;\\n    -webkit-user-select: none;\\n    user-select: none;\\n    cursor: text;\\n}\\n\\n.ace_content {\\n    position: absolute;\\n    box-sizing: border-box;\\n    min-width: 100%;\\n    contain: style size layout;\\n    font-variant-ligatures: no-common-ligatures;\\n}\\n\\n.ace_keyboard-focus:focus {\\n    box-shadow: inset 0 0 0 2px #5E9ED6;\\n    outline: none;\\n}\\n\\n.ace_dragging .ace_scroller:before{\\n    position: absolute;\\n    top: 0;\\n    left: 0;\\n    right: 0;\\n    bottom: 0;\\n    content: \\'\\';\\n    background: rgba(250, 250, 250, 0.01);\\n    z-index: 1000;\\n}\\n.ace_dragging.ace_dark .ace_scroller:before{\\n    background: rgba(0, 0, 0, 0.01);\\n}\\n\\n.ace_gutter {\\n    position: absolute;\\n    overflow : hidden;\\n    width: auto;\\n    top: 0;\\n    bottom: 0;\\n    left: 0;\\n    cursor: default;\\n    z-index: 4;\\n    -ms-user-select: none;\\n    -moz-user-select: none;\\n    -webkit-user-select: none;\\n    user-select: none;\\n    contain: style size layout;\\n}\\n\\n.ace_gutter-active-line {\\n    position: absolute;\\n    left: 0;\\n    right: 0;\\n}\\n\\n.ace_scroller.ace_scroll-left:after {\\n    content: \"\";\\n    position: absolute;\\n    top: 0;\\n    right: 0;\\n    bottom: 0;\\n    left: 0;\\n    box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\\n    pointer-events: none;\\n}\\n\\n.ace_gutter-cell, .ace_gutter-cell_svg-icons {\\n    position: absolute;\\n    top: 0;\\n    left: 0;\\n    right: 0;\\n    padding-left: 19px;\\n    padding-right: 6px;\\n    background-repeat: no-repeat;\\n}\\n\\n.ace_gutter-cell_svg-icons .ace_gutter_annotation {\\n    margin-left: -14px;\\n    float: left;\\n}\\n\\n.ace_gutter-cell .ace_gutter_annotation {\\n    margin-left: -19px;\\n    float: left;\\n}\\n\\n.ace_gutter-cell.ace_error, .ace_icon.ace_error, .ace_icon.ace_error_fold {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\\n    background-repeat: no-repeat;\\n    background-position: 2px center;\\n}\\n\\n.ace_gutter-cell.ace_warning, .ace_icon.ace_warning, .ace_icon.ace_warning_fold {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\\n    background-repeat: no-repeat;\\n    background-position: 2px center;\\n}\\n\\n.ace_gutter-cell.ace_info, .ace_icon.ace_info {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\\n    background-repeat: no-repeat;\\n    background-position: 2px center;\\n}\\n.ace_dark .ace_gutter-cell.ace_info, .ace_dark .ace_icon.ace_info {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\\n}\\n\\n.ace_icon_svg.ace_error {\\n    -webkit-mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJyZWQiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KPGNpcmNsZSBmaWxsPSJub25lIiBjeD0iOCIgY3k9IjgiIHI9IjciIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGxpbmUgeDE9IjExIiB5MT0iNSIgeDI9IjUiIHkyPSIxMSIvPgo8bGluZSB4MT0iMTEiIHkxPSIxMSIgeDI9IjUiIHkyPSI1Ii8+CjwvZz4KPC9zdmc+\");\\n    background-color: crimson;\\n}\\n.ace_icon_svg.ace_warning {\\n    -webkit-mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJkYXJrb3JhbmdlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+Cjxwb2x5Z29uIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGZpbGw9Im5vbmUiIHBvaW50cz0iOCAxIDE1IDE1IDEgMTUgOCAxIi8+CjxyZWN0IHg9IjgiIHk9IjEyIiB3aWR0aD0iMC4wMSIgaGVpZ2h0PSIwLjAxIi8+CjxsaW5lIHgxPSI4IiB5MT0iNiIgeDI9IjgiIHkyPSIxMCIvPgo8L2c+Cjwvc3ZnPg==\");\\n    background-color: darkorange;\\n}\\n.ace_icon_svg.ace_info {\\n    -webkit-mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJibHVlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CjxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjgiIGN5PSI4IiByPSI3IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjxwb2x5bGluZSBwb2ludHM9IjggMTEgOCA4Ii8+Cjxwb2x5bGluZSBwb2ludHM9IjkgOCA2IDgiLz4KPGxpbmUgeDE9IjEwIiB5MT0iMTEiIHgyPSI2IiB5Mj0iMTEiLz4KPHJlY3QgeD0iOCIgeT0iNSIgd2lkdGg9IjAuMDEiIGhlaWdodD0iMC4wMSIvPgo8L2c+Cjwvc3ZnPg==\");\\n    background-color: royalblue;\\n}\\n\\n.ace_icon_svg.ace_error_fold {\\n    -webkit-mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSI+CiAgPHBhdGggZD0ibSAxOC45Mjk4NTEsNy44Mjk4MDc2IGMgMC4xNDYzNTMsNi4zMzc0NjA0IC02LjMyMzE0Nyw3Ljc3Nzg0NDQgLTcuNDc3OTEyLDcuNzc3ODQ0NCAtMi4xMDcyNzI2LC0wLjEyODc1IDUuMTE3Njc4LDAuMzU2MjQ5IDUuMDUxNjk4LC03Ljg3MDA2MTggLTAuNjA0NjcyLC04LjAwMzk3MzQ5IC03LjA3NzI3MDYsLTcuNTYzMTE4OSAtNC44NTczLC03LjQzMDM5NTU2IDEuNjA2LC0wLjExNTE0MjI1IDYuODk3NDg1LDEuMjYyNTQ1OTYgNy4yODM1MTQsNy41MjI2MTI5NiB6IiBmaWxsPSJjcmltc29uIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibSA4LjExNDc1NjIsMi4wNTI5ODI4IGMgMy4zNDkxNjk4LDAgNi4wNjQxMzI4LDIuNjc2ODYyNyA2LjA2NDEzMjgsNS45Nzg5NTMgMCwzLjMwMjExMjIgLTIuNzE0OTYzLDUuOTc4OTIwMiAtNi4wNjQxMzI4LDUuOTc4OTIwMiAtMy4zNDkxNDczLDAgLTYuMDY0MTc3MiwtMi42NzY4MDggLTYuMDY0MTc3MiwtNS45Nzg5MjAyIDAuMDA1MzksLTMuMjk5ODg2MSAyLjcxNzI2NTYsLTUuOTczNjQwOCA2LjA2NDE3NzIsLTUuOTc4OTUzIHogbSAwLC0xLjczNTgyNzE5IGMgLTQuMzIxNDgzNiwwIC03LjgyNDc0MDM4LDMuNDU0MDE4NDkgLTcuODI0NzQwMzgsNy43MTQ3ODAxOSAwLDQuMjYwNzI4MiAzLjUwMzI1Njc4LDcuNzE0NzQ1MiA3LjgyNDc0MDM4LDcuNzE0NzQ1MiA0LjMyMTQ0OTgsMCA3LjgyNDY5OTgsLTMuNDU0MDE3IDcuODI0Njk5OCwtNy43MTQ3NDUyIDAsLTIuMDQ2MDkxNCAtMC44MjQzOTIsLTQuMDA4MzY3MiAtMi4yOTE3NTYsLTUuNDU1MTc0NiBDIDEyLjE4MDIyNSwxLjEyOTk2NDggMTAuMTkwMDEzLDAuMzE3MTU1NjEgOC4xMTQ3NTYyLDAuMzE3MTU1NjEgWiBNIDYuOTM3NDU2Myw4LjI0MDU5ODUgNC42NzE4Njg1LDEwLjQ4NTg1MiA2LjAwODY4MTQsMTEuODc2NzI4IDguMzE3MDAzNSw5LjYwMDc5MTEgMTAuNjI1MzM3LDExLjg3NjcyOCAxMS45NjIxMzgsMTAuNDg1ODUyIDkuNjk2NTUwOCw4LjI0MDU5ODUgMTEuOTYyMTM4LDYuMDA2ODA2NiAxMC41NzMyNDYsNC42Mzc0MzM1IDguMzE3MDAzNSw2Ljg3MzQyOTcgNi4wNjA3NjA3LDQuNjM3NDMzNSA0LjY3MTg2ODUsNi4wMDY4MDY2IFoiIGZpbGw9ImNyaW1zb24iIHN0cm9rZS13aWR0aD0iMiIvPgo8L3N2Zz4=\");\\n    background-color: crimson;\\n}\\n.ace_icon_svg.ace_warning_fold {\\n    -webkit-mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC43NzY5IDE0LjczMzdMOC42NTE5MiAyLjQ4MzY5QzguMzI5NDYgMS44Mzg3NyA3LjQwOTEzIDEuODM4NzcgNy4wODY2NyAyLjQ4MzY5TDAuOTYxNjY5IDE0LjczMzdDMC42NzA3NzUgMTUuMzE1NSAxLjA5MzgzIDE2IDEuNzQ0MjkgMTZIMTMuOTk0M0MxNC42NDQ4IDE2IDE1LjA2NzggMTUuMzE1NSAxNC43NzY5IDE0LjczMzdaTTMuMTYwMDcgMTQuMjVMNy44NjkyOSA0LjgzMTU2TDEyLjU3ODUgMTQuMjVIMy4xNjAwN1pNOC43NDQyOSAxMS42MjVWMTMuMzc1SDYuOTk0MjlWMTEuNjI1SDguNzQ0MjlaTTYuOTk0MjkgMTAuNzVWNy4yNUg4Ljc0NDI5VjEwLjc1SDYuOTk0MjlaIiBmaWxsPSIjRUM3MjExIi8+CjxwYXRoIGQ9Ik0xMS4xOTkxIDIuOTUyMzhDMTAuODgwOSAyLjMxNDY3IDEwLjM1MzcgMS44MDUyNiA5LjcwNTUgMS41MDlMMTEuMDQxIDEuMDY5NzhDMTEuNjg4MyAwLjk0OTgxNCAxMi4zMzcgMS4yNzI2MyAxMi42MzE3IDEuODYxNDFMMTcuNjEzNiAxMS44MTYxQzE4LjM1MjcgMTMuMjkyOSAxNy41OTM4IDE1LjA4MDQgMTYuMDE4IDE1LjU3NDVDMTYuNDA0NCAxNC40NTA3IDE2LjMyMzEgMTMuMjE4OCAxNS43OTI0IDEyLjE1NTVMMTEuMTk5MSAyLjk1MjM4WiIgZmlsbD0iI0VDNzIxMSIvPgo8L3N2Zz4=\");\\n    background-color: darkorange;\\n}\\n\\n.ace_scrollbar {\\n    contain: strict;\\n    position: absolute;\\n    right: 0;\\n    bottom: 0;\\n    z-index: 6;\\n}\\n\\n.ace_scrollbar-inner {\\n    position: absolute;\\n    cursor: text;\\n    left: 0;\\n    top: 0;\\n}\\n\\n.ace_scrollbar-v{\\n    overflow-x: hidden;\\n    overflow-y: scroll;\\n    top: 0;\\n}\\n\\n.ace_scrollbar-h {\\n    overflow-x: scroll;\\n    overflow-y: hidden;\\n    left: 0;\\n}\\n\\n.ace_print-margin {\\n    position: absolute;\\n    height: 100%;\\n}\\n\\n.ace_text-input {\\n    position: absolute;\\n    z-index: 0;\\n    width: 0.5em;\\n    height: 1em;\\n    opacity: 0;\\n    background: transparent;\\n    -moz-appearance: none;\\n    appearance: none;\\n    border: none;\\n    resize: none;\\n    outline: none;\\n    overflow: hidden;\\n    font: inherit;\\n    padding: 0 1px;\\n    margin: 0 -1px;\\n    contain: strict;\\n    -ms-user-select: text;\\n    -moz-user-select: text;\\n    -webkit-user-select: text;\\n    user-select: text;\\n    /*with `pre-line` chrome inserts &nbsp; instead of space*/\\n    white-space: pre!important;\\n}\\n.ace_text-input.ace_composition {\\n    background: transparent;\\n    color: inherit;\\n    z-index: 1000;\\n    opacity: 1;\\n}\\n.ace_composition_placeholder { color: transparent }\\n.ace_composition_marker { \\n    border-bottom: 1px solid;\\n    position: absolute;\\n    border-radius: 0;\\n    margin-top: 1px;\\n}\\n\\n[ace_nocontext=true] {\\n    transform: none!important;\\n    filter: none!important;\\n    clip-path: none!important;\\n    mask : none!important;\\n    contain: none!important;\\n    perspective: none!important;\\n    mix-blend-mode: initial!important;\\n    z-index: auto;\\n}\\n\\n.ace_layer {\\n    z-index: 1;\\n    position: absolute;\\n    overflow: hidden;\\n    /* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/\\n    word-wrap: normal;\\n    white-space: pre;\\n    height: 100%;\\n    width: 100%;\\n    box-sizing: border-box;\\n    /* setting pointer-events: auto; on node under the mouse, which changes\\n        during scroll, will break mouse wheel scrolling in Safari */\\n    pointer-events: none;\\n}\\n\\n.ace_gutter-layer {\\n    position: relative;\\n    width: auto;\\n    text-align: right;\\n    pointer-events: auto;\\n    height: 1000000px;\\n    contain: style size layout;\\n}\\n\\n.ace_text-layer {\\n    font: inherit !important;\\n    position: absolute;\\n    height: 1000000px;\\n    width: 1000000px;\\n    contain: style size layout;\\n}\\n\\n.ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group {\\n    contain: style size layout;\\n    position: absolute;\\n    top: 0;\\n    left: 0;\\n    right: 0;\\n}\\n\\n.ace_hidpi .ace_text-layer,\\n.ace_hidpi .ace_gutter-layer,\\n.ace_hidpi .ace_content,\\n.ace_hidpi .ace_gutter {\\n    contain: strict;\\n}\\n.ace_hidpi .ace_text-layer > .ace_line, \\n.ace_hidpi .ace_text-layer > .ace_line_group {\\n    contain: strict;\\n}\\n\\n.ace_cjk {\\n    display: inline-block;\\n    text-align: center;\\n}\\n\\n.ace_cursor-layer {\\n    z-index: 4;\\n}\\n\\n.ace_cursor {\\n    z-index: 4;\\n    position: absolute;\\n    box-sizing: border-box;\\n    border-left: 2px solid;\\n    /* workaround for smooth cursor repaintng whole screen in chrome */\\n    transform: translatez(0);\\n}\\n\\n.ace_multiselect .ace_cursor {\\n    border-left-width: 1px;\\n}\\n\\n.ace_slim-cursors .ace_cursor {\\n    border-left-width: 1px;\\n}\\n\\n.ace_overwrite-cursors .ace_cursor {\\n    border-left-width: 0;\\n    border-bottom: 1px solid;\\n}\\n\\n.ace_hidden-cursors .ace_cursor {\\n    opacity: 0.2;\\n}\\n\\n.ace_hasPlaceholder .ace_hidden-cursors .ace_cursor {\\n    opacity: 0;\\n}\\n\\n.ace_smooth-blinking .ace_cursor {\\n    transition: opacity 0.18s;\\n}\\n\\n.ace_animate-blinking .ace_cursor {\\n    animation-duration: 1000ms;\\n    animation-timing-function: step-end;\\n    animation-name: blink-ace-animate;\\n    animation-iteration-count: infinite;\\n}\\n\\n.ace_animate-blinking.ace_smooth-blinking .ace_cursor {\\n    animation-duration: 1000ms;\\n    animation-timing-function: ease-in-out;\\n    animation-name: blink-ace-animate-smooth;\\n}\\n    \\n@keyframes blink-ace-animate {\\n    from, to { opacity: 1; }\\n    60% { opacity: 0; }\\n}\\n\\n@keyframes blink-ace-animate-smooth {\\n    from, to { opacity: 1; }\\n    45% { opacity: 1; }\\n    60% { opacity: 0; }\\n    85% { opacity: 0; }\\n}\\n\\n.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\\n    position: absolute;\\n    z-index: 3;\\n}\\n\\n.ace_marker-layer .ace_selection {\\n    position: absolute;\\n    z-index: 5;\\n}\\n\\n.ace_marker-layer .ace_bracket {\\n    position: absolute;\\n    z-index: 6;\\n}\\n\\n.ace_marker-layer .ace_error_bracket {\\n    position: absolute;\\n    border-bottom: 1px solid #DE5555;\\n    border-radius: 0;\\n}\\n\\n.ace_marker-layer .ace_active-line {\\n    position: absolute;\\n    z-index: 2;\\n}\\n\\n.ace_marker-layer .ace_selected-word {\\n    position: absolute;\\n    z-index: 4;\\n    box-sizing: border-box;\\n}\\n\\n.ace_line .ace_fold {\\n    box-sizing: border-box;\\n\\n    display: inline-block;\\n    height: 11px;\\n    margin-top: -2px;\\n    vertical-align: middle;\\n\\n    background-image:\\n        url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\\n        url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\\n    background-repeat: no-repeat, repeat-x;\\n    background-position: center center, top left;\\n    color: transparent;\\n\\n    border: 1px solid black;\\n    border-radius: 2px;\\n\\n    cursor: pointer;\\n    pointer-events: auto;\\n}\\n\\n.ace_dark .ace_fold {\\n}\\n\\n.ace_fold:hover{\\n    background-image:\\n        url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\\n        url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\\n}\\n\\n.ace_tooltip {\\n    background-color: #f5f5f5;\\n    border: 1px solid gray;\\n    border-radius: 1px;\\n    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\\n    color: black;\\n    max-width: 100%;\\n    padding: 3px 4px;\\n    position: fixed;\\n    z-index: 999999;\\n    box-sizing: border-box;\\n    cursor: default;\\n    white-space: pre;\\n    word-wrap: break-word;\\n    line-height: normal;\\n    font-style: normal;\\n    font-weight: normal;\\n    letter-spacing: normal;\\n    pointer-events: none;\\n}\\n\\n.ace_tooltip.ace_dark {\\n    background-color: #636363;\\n    color: #fff;\\n}\\n\\n.ace_tooltip:focus {\\n    outline: 1px solid #5E9ED6;\\n}\\n\\n.ace_icon {\\n    display: inline-block;\\n    width: 18px;\\n    vertical-align: top;\\n}\\n\\n.ace_icon_svg {\\n    display: inline-block;\\n    width: 12px;\\n    vertical-align: top;\\n    -webkit-mask-repeat: no-repeat;\\n    -webkit-mask-size: 12px;\\n    -webkit-mask-position: center;\\n}\\n\\n.ace_folding-enabled > .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell_svg-icons {\\n    padding-right: 13px;\\n}\\n\\n.ace_fold-widget {\\n    box-sizing: border-box;\\n\\n    margin: 0 -12px 0 1px;\\n    display: none;\\n    width: 11px;\\n    vertical-align: top;\\n\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\\n    background-repeat: no-repeat;\\n    background-position: center;\\n\\n    border-radius: 3px;\\n    \\n    border: 1px solid transparent;\\n    cursor: pointer;\\n}\\n\\n.ace_folding-enabled .ace_fold-widget {\\n    display: inline-block;   \\n}\\n\\n.ace_fold-widget.ace_end {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\\n}\\n\\n.ace_fold-widget.ace_closed {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\\n}\\n\\n.ace_fold-widget:hover {\\n    border: 1px solid rgba(0, 0, 0, 0.3);\\n    background-color: rgba(255, 255, 255, 0.2);\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\\n}\\n\\n.ace_fold-widget:active {\\n    border: 1px solid rgba(0, 0, 0, 0.4);\\n    background-color: rgba(0, 0, 0, 0.05);\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\\n}\\n/**\\n * Dark version for fold widgets\\n */\\n.ace_dark .ace_fold-widget {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\\n}\\n.ace_dark .ace_fold-widget.ace_end {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\\n}\\n.ace_dark .ace_fold-widget.ace_closed {\\n    background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\\n}\\n.ace_dark .ace_fold-widget:hover {\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n    background-color: rgba(255, 255, 255, 0.1);\\n}\\n.ace_dark .ace_fold-widget:active {\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n}\\n\\n.ace_inline_button {\\n    border: 1px solid lightgray;\\n    display: inline-block;\\n    margin: -1px 8px;\\n    padding: 0 5px;\\n    pointer-events: auto;\\n    cursor: pointer;\\n}\\n.ace_inline_button:hover {\\n    border-color: gray;\\n    background: rgba(200,200,200,0.2);\\n    display: inline-block;\\n    pointer-events: auto;\\n}\\n\\n.ace_fold-widget.ace_invalid {\\n    background-color: #FFB4B4;\\n    border-color: #DE5555;\\n}\\n\\n.ace_fade-fold-widgets .ace_fold-widget {\\n    transition: opacity 0.4s ease 0.05s;\\n    opacity: 0;\\n}\\n\\n.ace_fade-fold-widgets:hover .ace_fold-widget {\\n    transition: opacity 0.05s ease 0.05s;\\n    opacity:1;\\n}\\n\\n.ace_underline {\\n    text-decoration: underline;\\n}\\n\\n.ace_bold {\\n    font-weight: bold;\\n}\\n\\n.ace_nobold .ace_bold {\\n    font-weight: normal;\\n}\\n\\n.ace_italic {\\n    font-style: italic;\\n}\\n\\n\\n.ace_error-marker {\\n    background-color: rgba(255, 0, 0,0.2);\\n    position: absolute;\\n    z-index: 9;\\n}\\n\\n.ace_highlight-marker {\\n    background-color: rgba(255, 255, 0,0.2);\\n    position: absolute;\\n    z-index: 8;\\n}\\n\\n.ace_mobile-menu {\\n    position: absolute;\\n    line-height: 1.5;\\n    border-radius: 4px;\\n    -ms-user-select: none;\\n    -moz-user-select: none;\\n    -webkit-user-select: none;\\n    user-select: none;\\n    background: white;\\n    box-shadow: 1px 3px 2px grey;\\n    border: 1px solid #dcdcdc;\\n    color: black;\\n}\\n.ace_dark > .ace_mobile-menu {\\n    background: #333;\\n    color: #ccc;\\n    box-shadow: 1px 3px 2px grey;\\n    border: 1px solid #444;\\n\\n}\\n.ace_mobile-button {\\n    padding: 2px;\\n    cursor: pointer;\\n    overflow: hidden;\\n}\\n.ace_mobile-button:hover {\\n    background-color: #eee;\\n    opacity:1;\\n}\\n.ace_mobile-button:active {\\n    background-color: #ddd;\\n}\\n\\n.ace_placeholder {\\n    font-family: arial;\\n    transform: scale(0.9);\\n    transform-origin: left;\\n    white-space: pre;\\n    opacity: 0.7;\\n    margin: 0 10px;\\n}\\n\\n.ace_ghost_text {\\n    opacity: 0.5;\\n    font-style: italic;\\n    white-space: pre;\\n}'}),define(\"ace/layer/decorators\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/event_emitter\").EventEmitter,o=function(){function e(e,t){this.canvas=r.createElement(\"canvas\"),this.renderer=t,this.pixelRatio=1,this.maxHeight=t.layerConfig.maxHeight,this.lineHeight=t.layerConfig.lineHeight,this.canvasHeight=e.parent.scrollHeight,this.heightRatio=this.canvasHeight/this.maxHeight,this.canvasWidth=e.width,this.minDecorationHeight=2*this.pixelRatio|0,this.halfMinDecorationHeight=this.minDecorationHeight/2|0,this.canvas.width=this.canvasWidth,this.canvas.height=this.canvasHeight,this.canvas.style.top=\"0px\",this.canvas.style.right=\"0px\",this.canvas.style.zIndex=\"7px\",this.canvas.style.position=\"absolute\",this.colors={},this.colors.dark={error:\"rgba(255, 18, 18, 1)\",warning:\"rgba(18, 136, 18, 1)\",info:\"rgba(18, 18, 136, 1)\"},this.colors.light={error:\"rgb(255,51,51)\",warning:\"rgb(32,133,72)\",info:\"rgb(35,68,138)\"},e.element.appendChild(this.canvas)}return e.prototype.$updateDecorators=function(e){function i(e,t){return e.priority<t.priority?-1:e.priority>t.priority?1:0}var t=this.renderer.theme.isDark===!0?this.colors.dark:this.colors.light;if(e){this.maxHeight=e.maxHeight,this.lineHeight=e.lineHeight,this.canvasHeight=e.height;var n=(e.lastRow+1)*this.lineHeight;n<this.canvasHeight?this.heightRatio=1:this.heightRatio=this.canvasHeight/this.maxHeight}var r=this.canvas.getContext(\"2d\"),s=this.renderer.session.$annotations;r.clearRect(0,0,this.canvas.width,this.canvas.height);if(s){var o={info:1,warning:2,error:3};s.forEach(function(e){e.priority=o[e.type]||null}),s=s.sort(i);var u=this.renderer.session.$foldData;for(var a=0;a<s.length;a++){var f=s[a].row,l=this.compensateFoldRows(f,u),c=Math.round((f-l)*this.lineHeight*this.heightRatio),h=Math.round((f-l)*this.lineHeight*this.heightRatio),p=Math.round(((f-l)*this.lineHeight+this.lineHeight)*this.heightRatio),d=p-h;if(d<this.minDecorationHeight){var v=(h+p)/2|0;v<this.halfMinDecorationHeight?v=this.halfMinDecorationHeight:v+this.halfMinDecorationHeight>this.canvasHeight&&(v=this.canvasHeight-this.halfMinDecorationHeight),h=Math.round(v-this.halfMinDecorationHeight),p=Math.round(v+this.halfMinDecorationHeight)}r.fillStyle=t[s[a].type]||null,r.fillRect(0,c,this.canvasWidth,p-h)}}var m=this.renderer.session.selection.getCursor();if(m){var l=this.compensateFoldRows(m.row,u),c=Math.round((m.row-l)*this.lineHeight*this.heightRatio);r.fillStyle=\"rgba(0, 0, 0, 0.5)\",r.fillRect(0,c,this.canvasWidth,2)}},e.prototype.compensateFoldRows=function(e,t){var n=0;if(t&&t.length>0)for(var r=0;r<t.length;r++)e>t[r].start.row&&e<t[r].end.row?n+=e-t[r].start.row:e>=t[r].end.row&&(n+=t[r].end.row-t[r].start.row);return n},e}();i.implement(o.prototype,s),t.Decorator=o}),define(\"ace/virtual_renderer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/config\",\"ace/layer/gutter\",\"ace/layer/marker\",\"ace/layer/text\",\"ace/layer/cursor\",\"ace/scrollbar\",\"ace/scrollbar\",\"ace/scrollbar_custom\",\"ace/scrollbar_custom\",\"ace/renderloop\",\"ace/layer/font_metrics\",\"ace/lib/event_emitter\",\"ace/css/editor.css\",\"ace/layer/decorators\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./lib/lang\"),o=e(\"./config\"),u=e(\"./layer/gutter\").Gutter,a=e(\"./layer/marker\").Marker,f=e(\"./layer/text\").Text,l=e(\"./layer/cursor\").Cursor,c=e(\"./scrollbar\").HScrollBar,h=e(\"./scrollbar\").VScrollBar,p=e(\"./scrollbar_custom\").HScrollBar,d=e(\"./scrollbar_custom\").VScrollBar,v=e(\"./renderloop\").RenderLoop,m=e(\"./layer/font_metrics\").FontMetrics,g=e(\"./lib/event_emitter\").EventEmitter,y=e(\"./css/editor.css\"),b=e(\"./layer/decorators\").Decorator,w=e(\"./lib/useragent\");i.importCssString(y,\"ace_editor.css\",!1);var E=function(){function e(e,t){var n=this;this.container=e||i.createElement(\"div\"),i.addCssClass(this.container,\"ace_editor\"),i.HI_DPI&&i.addCssClass(this.container,\"ace_hidpi\"),this.setTheme(t),o.get(\"useStrictCSP\")==null&&o.set(\"useStrictCSP\",!1),this.$gutter=i.createElement(\"div\"),this.$gutter.className=\"ace_gutter\",this.container.appendChild(this.$gutter),this.$gutter.setAttribute(\"aria-hidden\",!0),this.scroller=i.createElement(\"div\"),this.scroller.className=\"ace_scroller\",this.container.appendChild(this.scroller),this.content=i.createElement(\"div\"),this.content.className=\"ace_content\",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on(\"changeGutterWidth\",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);var r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.on(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.on(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new m(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.on(\"changeCharacterSize\",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal(\"changeCharacterSize\",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.margin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$keepTextAreaAtCursor=!w.isIOS,this.$loop=new v(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),this.$addResizeObserver(),o.resetOptions(this),o._signal(\"renderer\",this)}return e.prototype.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle(\"ace_nobold\",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin(),i.setStyle(this.scroller.style,\"line-height\",this.lineHeight+\"px\")},e.prototype.setSession=function(e){this.session&&this.session.doc.off(\"changeNewLineMode\",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on(\"changeNewLineMode\",this.onChangeNewLineMode)},e.prototype.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRow<t&&(this.$changedLines.lastRow=t)):this.$changedLines={firstRow:e,lastRow:t};if(this.$changedLines.lastRow<this.layerConfig.firstRow){if(!n)return;this.$changedLines.lastRow=this.layerConfig.lastRow}if(this.$changedLines.firstRow>this.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},e.prototype.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar(),this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR)},e.prototype.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},e.prototype.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},e.prototype.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},e.prototype.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},e.prototype.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},e.prototype.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);this.$resizeTimer&&this.$resizeTimer.cancel();if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.$customScrollbar&&this.$updateCustomScrollbar(!0)},e.prototype.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var s=0,o=this.$size,u={width:o.width,height:o.height,scrollerHeight:o.scrollerHeight,scrollerWidth:o.scrollerWidth};r&&(e||o.height!=r)&&(o.height=r,s|=this.CHANGE_SIZE,o.scrollerHeight=o.height,this.$horizScroll&&(o.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.setHeight(o.scrollerHeight),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+\"px\",s|=this.CHANGE_SCROLL);if(n&&(e||o.width!=n)){s|=this.CHANGE_SIZE,o.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,i.setStyle(this.scrollBarH.element.style,\"left\",t+\"px\"),i.setStyle(this.scroller.style,\"left\",t+this.margin.left+\"px\"),o.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()-this.margin.h),i.setStyle(this.$gutter.style,\"left\",this.margin.left+\"px\");var a=this.scrollBarV.getWidth()+\"px\";i.setStyle(this.scrollBarH.element.style,\"right\",a),i.setStyle(this.scroller.style,\"right\",a),i.setStyle(this.scroller.style,\"bottom\",this.scrollBarH.getHeight()),this.scrollBarH.setWidth(o.scrollerWidth);if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)s|=this.CHANGE_FULL}return o.$dirty=!n||!r,s&&this._signal(\"resize\",u),s},e.prototype.onGutterResize=function(e){var t=this.$showGutter?e:0;t!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,t,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):this.$computeLayerConfig()},e.prototype.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},e.prototype.setAnimatedScroll=function(e){this.setOption(\"animatedScroll\",e)},e.prototype.getAnimatedScroll=function(){return this.$animatedScroll},e.prototype.setShowInvisibles=function(e){this.setOption(\"showInvisibles\",e),this.session.$bidiHandler.setShowInvisibles(e)},e.prototype.getShowInvisibles=function(){return this.getOption(\"showInvisibles\")},e.prototype.getDisplayIndentGuide=function(){return this.getOption(\"displayIndentGuides\")},e.prototype.setDisplayIndentGuides=function(e){this.setOption(\"displayIndentGuides\",e)},e.prototype.getHighlightIndentGuides=function(){return this.getOption(\"highlightIndentGuides\")},e.prototype.setHighlightIndentGuides=function(e){this.setOption(\"highlightIndentGuides\",e)},e.prototype.setShowPrintMargin=function(e){this.setOption(\"showPrintMargin\",e)},e.prototype.getShowPrintMargin=function(){return this.getOption(\"showPrintMargin\")},e.prototype.setPrintMarginColumn=function(e){this.setOption(\"printMarginColumn\",e)},e.prototype.getPrintMarginColumn=function(){return this.getOption(\"printMarginColumn\")},e.prototype.getShowGutter=function(){return this.getOption(\"showGutter\")},e.prototype.setShowGutter=function(e){return this.setOption(\"showGutter\",e)},e.prototype.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},e.prototype.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},e.prototype.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},e.prototype.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},e.prototype.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement(\"div\");e.className=\"ace_layer ace_print-margin-layer\",this.$printMarginEl=i.createElement(\"div\"),this.$printMarginEl.className=\"ace_print-margin\",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=Math.round(this.characterWidth*this.$printMarginColumn+this.$padding)+\"px\",t.visibility=this.$showPrintMargin?\"visible\":\"hidden\",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},e.prototype.getContainerElement=function(){return this.container},e.prototype.getMouseEventTarget=function(){return this.scroller},e.prototype.getTextAreaContainer=function(){return this.container},e.prototype.$moveTextAreaToCursor=function(){if(this.$isMousePressed)return;var e=this.textarea.style,t=this.$composition;if(!this.$keepTextAreaAtCursor&&!t){i.translate(this.textarea,-100,0);return}var n=this.$cursorLayer.$pixelPos;if(!n)return;t&&t.markerRange&&(n=this.$cursorLayer.getPixelPosition(t.markerRange.start,!0));var r=this.layerConfig,s=n.top,o=n.left;s-=r.offset;var u=t&&t.useTextareaForIME||w.isMobile?this.lineHeight:1;if(s<0||s>r.height-u){i.translate(this.textarea,0,0);return}var a=1,f=this.$size.height-u;if(!t)s+=this.lineHeight;else if(t.useTextareaForIME){var l=this.textarea.value;a=this.characterWidth*this.session.$getStringScreenWidth(l)[0]}else s+=this.lineHeight+2;o-=this.scrollLeft,o>this.$size.scrollerWidth-a&&(o=this.$size.scrollerWidth-a),o+=this.gutterWidth+this.margin.left,i.setStyle(e,\"height\",u+\"px\"),i.setStyle(e,\"width\",a+\"px\"),i.translate(this.textarea,Math.min(o,this.$size.scrollerWidth-a),Math.min(s,f))},e.prototype.getFirstVisibleRow=function(){return this.layerConfig.firstRow},e.prototype.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},e.prototype.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},e.prototype.getLastVisibleRow=function(){return this.layerConfig.lastRow},e.prototype.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},e.prototype.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},e.prototype.setMargin=function(e,t,n,r){var i=this.margin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,this.$updateCachedSize(!0,this.gutterWidth,this.$size.width,this.$size.height),this.updateFull()},e.prototype.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},e.prototype.setHScrollBarAlwaysVisible=function(e){this.setOption(\"hScrollBarAlwaysVisible\",e)},e.prototype.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},e.prototype.setVScrollBarAlwaysVisible=function(e){this.setOption(\"vScrollBarAlwaysVisible\",e)},e.prototype.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},e.prototype.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},e.prototype.freeze=function(){this.$frozen=!0},e.prototype.unfreeze=function(){this.$frozen=!1},e.prototype.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal(\"beforeRender\",e),this.session&&this.session.$bidiHandler&&this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig()|this.$loop.clear();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-Math.max(this.layerConfig.firstRow,0))*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig()|this.$loop.clear())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),i.translate(this.content,-this.scrollLeft,-n.offset);var s=n.width+2*this.$padding+\"px\",o=n.minHeight+\"px\";i.setStyle(this.content.style,\"width\",s),i.setStyle(this.content.style,\"height\",o)}e&this.CHANGE_H_SCROLL&&(i.translate(this.content,-this.scrollLeft,-n.offset),this.scroller.className=this.scrollLeft<=0?\"ace_scroller \":\"ace_scroller ace_scroll-left \",this.enableKeyboardAccessibility&&(this.scroller.className+=this.keyboardFocusClassName));if(e&this.CHANGE_FULL){this.$changedLines=null,this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this._signal(\"afterRender\",e);return}if(e&this.CHANGE_SCROLL){this.$changedLines=null,e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&(e&this.CHANGE_GUTTER||e&this.CHANGE_LINES?this.$gutterLayer.update(n):this.$gutterLayer.scrollLines(n)),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this._signal(\"afterRender\",e);return}e&this.CHANGE_TEXT?(this.$changedLines=null,this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n)):e&this.CHANGE_LINES?((this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n)):e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER?(this.$showGutter&&this.$gutterLayer.update(n),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n)):e&this.CHANGE_CURSOR&&(this.$highlightGutterLine&&this.$gutterLayer.updateLineHighlight(n),this.$customScrollbar&&this.$scrollDecorator.$updateDecorators(n)),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal(\"afterRender\",e)},e.prototype.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=n<=2*this.lineHeight,i=!r&&e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||i!=this.$vScroll){i!=this.$vScroll&&(this.$vScroll=i,this.scrollBarV.setVisible(i));var s=this.container.clientWidth;this.container.style.height=n+\"px\",this.$updateCachedSize(!0,this.$gutterWidth,s,n),this.desiredHeight=n,this._signal(\"autosize\")}},e.prototype.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=t.scrollerHeight+this.lineHeight,l=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=l;var c=this.scrollMargin;this.session.setScrollTop(Math.max(-c.top,Math.min(this.scrollTop,i-t.scrollerHeight+c.bottom))),this.session.setScrollLeft(Math.max(-c.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+c.right)));var h=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+l<0||this.scrollTop>c.top),p=a!==h;p&&(this.$vScroll=h,this.scrollBarV.setVisible(h));var d=this.scrollTop%this.lineHeight,v=Math.ceil(f/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-d)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),f=t.scrollerHeight+e.getRowLength(g)*w+b,d=this.scrollTop-y*w;var S=0;if(this.layerConfig.width!=s||u)S=this.CHANGE_H_SCROLL;if(u||p)S|=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal(\"scrollbarVisibilityChanged\"),p&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:f,maxHeight:i,offset:d,gutterOffset:w?Math.max(0,Math.ceil((d+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},this.session.$bidiHandler&&this.session.$bidiHandler.setContentWidth(s-this.$padding),S},e.prototype.$updateLines=function(){if(!this.$changedLines)return;var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(t<n.firstRow)return;if(t===Infinity){this.$showGutter&&this.$gutterLayer.update(n),this.$textLayer.update(n);return}return this.$textLayer.updateLines(n,e,t),!0},e.prototype.$getLongestLine=function(){var e=this.session.getScreenWidth();return this.showInvisibles&&!this.session.$useWrapMode&&(e+=1),this.$textLayer&&e>this.$textLayer.MAX_LINE_LENGTH&&(e=this.$textLayer.MAX_LINE_LENGTH+30),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(e*this.characterWidth))},e.prototype.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},e.prototype.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},e.prototype.addGutterDecoration=function(e,t){this.$gutterLayer.addGutterDecoration(e,t)},e.prototype.removeGutterDecoration=function(e,t){this.$gutterLayer.removeGutterDecoration(e,t)},e.prototype.updateBreakpoints=function(e){this.$loop.schedule(this.CHANGE_GUTTER)},e.prototype.setAnnotations=function(e){this.$gutterLayer.setAnnotations(e),this.$loop.schedule(this.CHANGE_GUTTER)},e.prototype.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},e.prototype.hideCursor=function(){this.$cursorLayer.hideCursor()},e.prototype.showCursor=function(){this.$cursorLayer.showCursor()},e.prototype.scrollSelectionIntoView=function(e,t,n){this.scrollCursorIntoView(e,n),this.scrollCursorIntoView(t,n)},e.prototype.scrollCursorIntoView=function(e,t,n){if(this.$size.scrollerHeight===0)return;var r=this.$cursorLayer.getPixelPosition(e),i=r.left,s=r.top,o=n&&n.top||0,u=n&&n.bottom||0;this.$scrollAnimation&&(this.$stopAnimation=!0);var a=this.$scrollAnimation?this.session.getScrollTop():this.scrollTop;a+o>s?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-u<s+this.lineHeight&&(t&&a+this.$size.scrollerHeight-u<s-this.lineHeight&&(s+=t*this.$size.scrollerHeight),this.session.setScrollTop(s+this.lineHeight+u-this.$size.scrollerHeight));var f=this.scrollLeft,l=2*this.layerConfig.characterWidth;i-l<f?(i-=l,i<this.$padding+l&&(i=-this.scrollMargin.left),this.session.setScrollLeft(i)):(i+=l,f+this.$size.scrollerWidth<i+this.characterWidth?this.session.setScrollLeft(Math.round(i+this.characterWidth-this.$size.scrollerWidth)):f<=this.$padding&&i-f<this.characterWidth&&this.session.setScrollLeft(0))},e.prototype.getScrollTop=function(){return this.session.getScrollTop()},e.prototype.getScrollLeft=function(){return this.session.getScrollLeft()},e.prototype.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},e.prototype.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},e.prototype.scrollToRow=function(e){this.session.setScrollTop(e*this.lineHeight)},e.prototype.alignCursor=function(e,t){typeof e==\"number\"&&(e={row:e,column:0});var n=this.$cursorLayer.getPixelPosition(e),r=this.$size.scrollerHeight-this.lineHeight,i=n.top-r*(t||0);return this.session.setScrollTop(i),i},e.prototype.$calcSteps=function(e,t){var n=0,r=this.STEPS,i=[],s=function(e,t,n){return n*(Math.pow(e-1,3)+1)+t};for(n=0;n<r;++n)i.push(s(n/this.STEPS,e,t-e));return i},e.prototype.scrollToLine=function(e,t,n,r){var i=this.$cursorLayer.getPixelPosition({row:e,column:0}),s=i.top;t&&(s-=this.$size.scrollerHeight/2);var o=this.scrollTop;this.session.setScrollTop(s),n!==!1&&this.animateScrolling(o,r)},e.prototype.animateScrolling=function(e,t){function o(){r.$timer=clearInterval(r.$timer),r.$scrollAnimation=null,r.$stopAnimation=!1,t&&t()}var n=this.scrollTop;if(!this.$animatedScroll)return;var r=this;if(e==n)return;if(this.$scrollAnimation){var i=this.$scrollAnimation.steps;if(i.length){e=i[0];if(e==n)return}}var s=r.$calcSteps(e,n);this.$scrollAnimation={from:e,to:n,steps:s},clearInterval(this.$timer),r.session.setScrollTop(s.shift()),r.session.$scrollTop=n,this.$timer=setInterval(function(){if(r.$stopAnimation){o();return}if(!r.session)return clearInterval(r.$timer);s.length?(r.session.setScrollTop(s.shift()),r.session.$scrollTop=n):n!=null?(r.session.$scrollTop=-1,r.session.setScrollTop(n),n=null):o()},10)},e.prototype.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},e.prototype.scrollToX=function(e){this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},e.prototype.scrollTo=function(e,t){this.session.setScrollTop(t),this.session.setScrollLeft(e)},e.prototype.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},e.prototype.isScrollableBy=function(e,t){if(t<0&&this.session.getScrollTop()>=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},e.prototype.pixelToScreenCoordinates=function(e,t){var n;if(this.$hasCssTransforms){n={top:0,left:0};var r=this.$fontMetrics.transformCoordinates([e,t]);e=r[1]-this.gutterWidth-this.margin.left,t=r[0]}else n=this.scroller.getBoundingClientRect();var i=e+this.scrollLeft-n.left-this.$padding,s=i/this.characterWidth,o=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),u=this.$blockCursor?Math.floor(s):Math.round(s);return{row:o,column:u,side:s-u>0?1:-1,offsetX:i}},e.prototype.screenToTextCoordinates=function(e,t){var n;if(this.$hasCssTransforms){n={top:0,left:0};var r=this.$fontMetrics.transformCoordinates([e,t]);e=r[1]-this.gutterWidth-this.margin.left,t=r[0]}else n=this.scroller.getBoundingClientRect();var i=e+this.scrollLeft-n.left-this.$padding,s=i/this.characterWidth,o=this.$blockCursor?Math.floor(s):Math.round(s),u=Math.floor((t+this.scrollTop-n.top)/this.lineHeight);return this.session.screenToDocumentPosition(u,Math.max(o,0),i)},e.prototype.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+(this.session.$bidiHandler.isBidiRow(r.row,e)?this.session.$bidiHandler.getPosLeft(r.column):Math.round(r.column*this.characterWidth)),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},e.prototype.visualizeFocus=function(){i.addCssClass(this.container,\"ace_focus\")},e.prototype.visualizeBlur=function(){i.removeCssClass(this.container,\"ace_focus\")},e.prototype.showComposition=function(e){this.$composition=e,e.cssText||(e.cssText=this.textarea.style.cssText),e.useTextareaForIME==undefined&&(e.useTextareaForIME=this.$useTextareaForIME),this.$useTextareaForIME?(i.addCssClass(this.textarea,\"ace_composition\"),this.textarea.style.cssText=\"\",this.$moveTextAreaToCursor(),this.$cursorLayer.element.style.display=\"none\"):e.markerId=this.session.addMarker(e.markerRange,\"ace_composition_marker\",\"text\")},e.prototype.setCompositionText=function(e){var t=this.session.selection.cursor;this.addToken(e,\"composition_placeholder\",t.row,t.column),this.$moveTextAreaToCursor()},e.prototype.hideComposition=function(){if(!this.$composition)return;this.$composition.markerId&&this.session.removeMarker(this.$composition.markerId),i.removeCssClass(this.textarea,\"ace_composition\"),this.textarea.style.cssText=this.$composition.cssText;var e=this.session.selection.cursor;this.removeExtraToken(e.row,e.column),this.$composition=null,this.$cursorLayer.element.style.display=\"\"},e.prototype.setGhostText=function(e,t){var n=this.session.selection.cursor,r=t||{row:n.row,column:n.column};this.removeGhostText();var i=e.split(\"\\n\");this.addToken(i[0],\"ghost_text\",r.row,r.column),this.$ghostText={text:e,position:{row:r.row,column:r.column}},i.length>1&&(this.$ghostTextWidget={text:i.slice(1).join(\"\\n\"),row:r.row,column:r.column,className:\"ace_ghost_text\"},this.session.widgetManager.addLineWidget(this.$ghostTextWidget))},e.prototype.removeGhostText=function(){if(!this.$ghostText)return;var e=this.$ghostText.position;this.removeExtraToken(e.row,e.column),this.$ghostTextWidget&&(this.session.widgetManager.removeLineWidget(this.$ghostTextWidget),this.$ghostTextWidget=null),this.$ghostText=null},e.prototype.addToken=function(e,t,n,r){var i=this.session;i.bgTokenizer.lines[n]=null;var s={type:t,value:e},o=i.getTokens(n);if(r==null||!o.length)o.push(s);else{var u=0;for(var a=0;a<o.length;a++){var f=o[a];u+=f.value.length;if(r<=u){var l=f.value.length-(u-r),c=f.value.slice(0,l),h=f.value.slice(l);o.splice(a,1,{type:f.type,value:c},s,{type:f.type,value:h});break}}}this.updateLines(n,n)},e.prototype.removeExtraToken=function(e,t){this.session.bgTokenizer.lines[e]=null,this.updateLines(e,e)},e.prototype.setTheme=function(e,t){function s(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw new Error(\"couldn't load module \"+e+\" or it didn't call define\");r.$id&&(n.$themeId=r.$id),i.importCssString(r.cssText,r.cssClass,n.container),n.theme&&i.removeCssClass(n.container,n.theme.cssClass);var s=\"padding\"in r?r.padding:\"padding\"in(n.theme||{})?4:n.$padding;n.$padding&&s!=n.$padding&&n.setPadding(s),n.$theme=r.cssClass,n.theme=r,i.addCssClass(n.container,r.cssClass),i.setCssClass(n.container,\"ace_dark\",r.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent(\"themeLoaded\",{theme:r}),t&&t()}var n=this;this.$themeId=e,n._dispatchEvent(\"themeChange\",{theme:e});if(!e||typeof e==\"string\"){var r=e||this.$options.theme.initialValue;o.loadModule([\"theme\",r],s)}else s(e)},e.prototype.getTheme=function(){return this.$themeId},e.prototype.setStyle=function(e,t){i.setCssClass(this.container,e,t!==!1)},e.prototype.unsetStyle=function(e){i.removeCssClass(this.container,e)},e.prototype.setCursorStyle=function(e){i.setStyle(this.scroller.style,\"cursor\",e)},e.prototype.setMouseCursor=function(e){i.setStyle(this.scroller.style,\"cursor\",e)},e.prototype.attachToShadowRoot=function(){i.importCssString(y,\"ace_editor.css\",this.container)},e.prototype.destroy=function(){this.freeze(),this.$fontMetrics.destroy(),this.$cursorLayer.destroy(),this.removeAllListeners(),this.container.textContent=\"\",this.setOption(\"useResizeObserver\",!1)},e.prototype.$updateCustomScrollbar=function(e){var t=this;this.$horizScroll=this.$vScroll=null,this.scrollBarV.element.remove(),this.scrollBarH.element.remove(),this.$scrollDecorator&&delete this.$scrollDecorator,e===!0?(this.scrollBarV=new d(this.container,this),this.scrollBarH=new p(this.container,this),this.scrollBarV.setHeight(this.$size.scrollerHeight),this.scrollBarH.setWidth(this.$size.scrollerWidth),this.scrollBarV.addEventListener(\"scroll\",function(e){t.$scrollAnimation||t.session.setScrollTop(e.data-t.scrollMargin.top)}),this.scrollBarH.addEventListener(\"scroll\",function(e){t.$scrollAnimation||t.session.setScrollLeft(e.data-t.scrollMargin.left)}),this.$scrollDecorator=new b(this.scrollBarV,this),this.$scrollDecorator.$updateDecorators()):(this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener(\"scroll\",function(e){t.$scrollAnimation||t.session.setScrollTop(e.data-t.scrollMargin.top)}),this.scrollBarH.addEventListener(\"scroll\",function(e){t.$scrollAnimation||t.session.setScrollLeft(e.data-t.scrollMargin.left)}))},e.prototype.$addResizeObserver=function(){if(!window.ResizeObserver||this.$resizeObserver)return;var e=this;this.$resizeTimer=s.delayedCall(function(){e.destroyed||e.onResize()},50),this.$resizeObserver=new window.ResizeObserver(function(t){var n=t[0].contentRect.width,r=t[0].contentRect.height;Math.abs(e.$size.width-n)>1||Math.abs(e.$size.height-r)>1?e.$resizeTimer.delay():e.$resizeTimer.cancel()}),this.$resizeObserver.observe(this.container)},e}();E.prototype.CHANGE_CURSOR=1,E.prototype.CHANGE_MARKER=2,E.prototype.CHANGE_GUTTER=4,E.prototype.CHANGE_SCROLL=8,E.prototype.CHANGE_LINES=16,E.prototype.CHANGE_TEXT=32,E.prototype.CHANGE_SIZE=64,E.prototype.CHANGE_MARKER_BACK=128,E.prototype.CHANGE_MARKER_FRONT=256,E.prototype.CHANGE_FULL=512,E.prototype.CHANGE_H_SCROLL=1024,E.prototype.$changes=0,E.prototype.$padding=null,E.prototype.$frozen=!1,E.prototype.STEPS=8,r.implement(E.prototype,g),o.defineOptions(E.prototype,\"renderer\",{useResizeObserver:{set:function(e){!e&&this.$resizeObserver?(this.$resizeObserver.disconnect(),this.$resizeTimer.cancel(),this.$resizeTimer=this.$resizeObserver=null):e&&!this.$resizeObserver&&this.$addResizeObserver()}},animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){typeof e==\"number\"&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?\"block\":\"none\",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},useSvgGutterIcons:{set:function(e){this.$gutterLayer.$useSvgGutterIcons=e},initialValue:!1},showFoldedAnnotations:{set:function(e){this.$gutterLayer.$showFoldedAnnotations=e},initialValue:!1},fadeFoldWidgets:{set:function(e){i.setCssClass(this.$gutter,\"ace_fade-fold-widgets\",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightIndentGuides:{set:function(e){this.$textLayer.setHighlightIndentGuides(e)==1?this.$textLayer.$highlightIndentGuide():this.$textLayer.$clearActiveIndentGuide(this.$textLayer.$lines.cells)},initialValue:!0},highlightGutterLine:{set:function(e){this.$gutterLayer.setHighlightGutterLine(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},hScrollBarAlwaysVisible:{set:function(e){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){typeof e==\"number\"&&(e+=\"px\"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.$minLines<562949953421311||(this.$minLines=0),this.updateFull()}},maxPixelHeight:{set:function(e){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(e){e=+e||0;if(this.$scrollPastEnd==e)return;this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},customScrollbar:{set:function(e){this.$updateCustomScrollbar(e)},initialValue:!1},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:\"./theme/textmate\",handlesSet:!0},hasCssTransforms:{},useTextareaForIME:{initialValue:!w.isMobile&&!w.isIE}}),t.VirtualRenderer=E}),define(\"ace/worker/worker_client\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/event_emitter\",\"ace/config\"],function(e,t,n){\"use strict\";function u(e){var t=\"importScripts('\"+i.qualifyURL(e)+\"');\";try{return new Blob([t],{type:\"application/javascript\"})}catch(n){var r=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,s=new r;return s.append(t),s.getBlob(\"application/javascript\")}}function a(e){if(typeof Worker==\"undefined\")return{postMessage:function(){},terminate:function(){}};if(o.get(\"loadWorkerFromBlob\")){var t=u(e),n=window.URL||window.webkitURL,r=n.createObjectURL(t);return new Worker(r)}return new Worker(e)}var r=e(\"../lib/oop\"),i=e(\"../lib/net\"),s=e(\"../lib/event_emitter\").EventEmitter,o=e(\"../config\"),f=function(e){e.postMessage||(e=this.$createWorkerFromOldConfig.apply(this,arguments)),this.$worker=e,this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.$createWorkerFromOldConfig=function(t,n,r,i,s){e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl);if(o.get(\"packaged\")||!e.toUrl)i=i||o.moduleUrl(n,\"worker\");else{var u=this.$normalizePath;i=i||u(e.toUrl(\"ace/worker/worker.js\",null,\"_\"));var f={};t.forEach(function(t){f[t]=u(e.toUrl(t,null,\"_\").replace(/(\\.js)?(\\?.*)?$/,\"\"))})}return this.$worker=a(i),s&&this.send(\"importScripts\",s),this.$worker.postMessage({init:!0,tlns:f,module:n,classname:r}),this.$worker},this.onMessage=function(e){var t=e.data;switch(t.type){case\"event\":this._signal(t.name,{data:t.data});break;case\"call\":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id]);break;case\"error\":this.reportError(t.data);break;case\"log\":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return i.qualifyURL(e)},this.terminate=function(){this._signal(\"terminate\",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker.onerror=function(e){e.preventDefault()},this.$worker=null,this.$doc&&this.$doc.off(\"change\",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{t.data&&t.data.err&&(t.data.err={message:t.data.err.message,stack:t.data.err.stack,code:t.data.err.code}),this.$worker&&this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){console.error(n.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call(\"setValue\",[e.getValue()]),e.on(\"change\",this.changeListener,!0)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),e.action==\"insert\"?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;if(!e)return;this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call(\"setValue\",[this.$doc.getValue()]):this.emit(\"change\",{data:e})}}).call(f.prototype);var l=function(e,t,n){var r=null,i=!1,u=Object.create(s),a=[],l=new f({messageBuffer:a,terminate:function(){},postMessage:function(e){a.push(e);if(!r)return;i?setTimeout(c):c()}});l.setEmitSync=function(e){i=e};var c=function(){var e=a.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};return u.postMessage=function(e){l.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:\"call\",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:\"event\",name:e,data:t})},o.loadModule([\"worker\",t],function(e){r=new e[n](u);while(a.length)c()}),l};t.UIWorkerClient=l,t.WorkerClient=f,t.createWorker=a}),define(\"ace/placeholder\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=e(\"./lib/event_emitter\").EventEmitter,s=e(\"./lib/oop\"),o=function(){function e(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on(\"change\",this.$onUpdate,!0),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on(\"changeCursor\",this.$onCursorChange)}return e.prototype.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},e.prototype.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},e.prototype.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e<this.others.length;e++)this.session.removeMarker(this.others[e].markerId)},e.prototype.onUpdate=function(e){if(this.$updating)return this.updateAnchors(e);var t=e;if(t.start.row!==t.end.row)return;if(t.start.row!==this.pos.row)return;this.$updating=!0;var n=e.action===\"insert\"?t.end.column-t.start.column:t.start.column-t.end.column,i=t.start.column>=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action===\"insert\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action===\"remove\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},e.prototype.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},e.prototype.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},e.prototype.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit(\"cursorEnter\",e)):(this.hideOtherMarkers(),this._emit(\"cursorLeave\",e))},e.prototype.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.off(\"change\",this.$onUpdate),this.session.selection.off(\"changeCursor\",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},e.prototype.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n<t;n++)e.undo(this.session,!0);this.selectionBefore&&this.session.selection.fromJSON(this.selectionBefore)},e}();s.implement(o.prototype,i),t.PlaceHolder=o}),define(\"ace/mouse/multi_select_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){function s(e,t){return e.row==t.row&&e.column==t.column}function o(e){var t=e.domEvent,n=t.altKey,o=t.shiftKey,u=t.ctrlKey,a=e.getAccelKey(),f=e.getButton();u&&i.isMac&&(f=t.button);if(e.editor.inMultiSelectMode&&f==2){e.editor.textInput.onContextMenu(e.domEvent);return}if(!u&&!n&&!a){f===0&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode();return}if(f!==0)return;var l=e.editor,c=l.selection,h=l.inMultiSelectMode,p=e.getDocumentPosition(),d=c.getCursor(),v=e.inSelection()||c.isEmpty()&&s(p,d),m=e.x,g=e.y,y=function(e){m=e.clientX,g=e.clientY},b=l.session,w=l.renderer.pixelToScreenCoordinates(m,g),E=w,S;if(l.$mouseHandler.$enableJumpToDef)u&&n||a&&n?S=o?\"block\":\"add\":n&&l.$blockSelectEnabled&&(S=\"block\");else if(a&&!n){S=\"add\";if(!h&&o)return}else n&&l.$blockSelectEnabled&&(S=\"block\");S&&i.isMac&&t.ctrlKey&&l.$mouseHandler.cancelContextMenu();if(S==\"add\"){if(!h&&v)return;if(!h){var x=c.toOrientedRange();l.addSelectionMarker(x)}var T=c.rangeList.rangeAtPoint(p);l.inVirtualSelectionMode=!0,o&&(T=null,x=c.ranges[0]||x,l.removeSelectionMarker(x)),l.once(\"mouseup\",function(){var e=c.toOrientedRange();T&&e.isEmpty()&&s(T.cursor,e.cursor)?c.substractPoint(e.cursor):(o?c.substractPoint(x.cursor):x&&(l.removeSelectionMarker(x),c.addRange(x)),c.addRange(e)),l.inVirtualSelectionMode=!1})}else if(S==\"block\"){e.stop(),l.inVirtualSelectionMode=!0;var N,C=[],k=function(){var e=l.renderer.pixelToScreenCoordinates(m,g),t=b.screenToDocumentPosition(e.row,e.column,e.offsetX);if(s(E,e)&&s(t,c.lead))return;E=e,l.selection.moveToPosition(t),l.renderer.scrollCursorIntoView(),l.removeSelectionMarkers(C),C=c.rectangularRangeBlock(E,w),l.$mouseHandler.$clickSelection&&C.length==1&&C[0].isEmpty()&&(C[0]=l.$mouseHandler.$clickSelection.clone()),C.forEach(l.addSelectionMarker,l),l.updateSelectionMarkers()};h&&!a?c.toSingleRange():!h&&a&&(N=c.toOrientedRange(),l.addSelectionMarker(N)),o?w=b.documentToScreenPosition(c.lead):c.moveToPosition(p),E={row:-1,column:-1};var L=function(e){k(),clearInterval(O),l.removeSelectionMarkers(C),C.length||(C=[c.toOrientedRange()]),N&&(l.removeSelectionMarker(N),c.toSingleRange(N));for(var t=0;t<C.length;t++)c.addRange(C[t]);l.inVirtualSelectionMode=!1,l.$mouseHandler.$clickSelection=null},A=k;r.capture(l.container,y,L);var O=setInterval(function(){A()},20);return e.preventDefault()}}var r=e(\"../lib/event\"),i=e(\"../lib/useragent\");t.onMouseDown=o}),define(\"ace/commands/multi_select_commands\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\"],function(e,t,n){t.defaultCommands=[{name:\"addCursorAbove\",description:\"Add cursor above\",exec:function(e){e.selectMoreLines(-1)},bindKey:{win:\"Ctrl-Alt-Up\",mac:\"Ctrl-Alt-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelow\",description:\"Add cursor below\",exec:function(e){e.selectMoreLines(1)},bindKey:{win:\"Ctrl-Alt-Down\",mac:\"Ctrl-Alt-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorAboveSkipCurrent\",description:\"Add cursor above (skip current)\",exec:function(e){e.selectMoreLines(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Up\",mac:\"Ctrl-Alt-Shift-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelowSkipCurrent\",description:\"Add cursor below (skip current)\",exec:function(e){e.selectMoreLines(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Down\",mac:\"Ctrl-Alt-Shift-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreBefore\",description:\"Select more before\",exec:function(e){e.selectMore(-1)},bindKey:{win:\"Ctrl-Alt-Left\",mac:\"Ctrl-Alt-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreAfter\",description:\"Select more after\",exec:function(e){e.selectMore(1)},bindKey:{win:\"Ctrl-Alt-Right\",mac:\"Ctrl-Alt-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextBefore\",description:\"Select next before\",exec:function(e){e.selectMore(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Left\",mac:\"Ctrl-Alt-Shift-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextAfter\",description:\"Select next after\",exec:function(e){e.selectMore(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Right\",mac:\"Ctrl-Alt-Shift-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"toggleSplitSelectionIntoLines\",description:\"Split selection into lines\",exec:function(e){e.multiSelect.rangeCount>1?e.multiSelect.joinSelections():e.multiSelect.splitIntoLines()},bindKey:{win:\"Ctrl-Alt-L\",mac:\"Ctrl-Alt-L\"},readOnly:!0},{name:\"splitSelectionIntoLines\",description:\"Split into lines\",exec:function(e){e.multiSelect.splitIntoLines()},readOnly:!0},{name:\"alignCursors\",description:\"Align cursors\",exec:function(e){e.alignCursors()},bindKey:{win:\"Ctrl-Alt-A\",mac:\"Ctrl-Alt-A\"},scrollIntoView:\"cursor\"},{name:\"findAll\",description:\"Find all\",exec:function(e){e.findAll()},bindKey:{win:\"Ctrl-Alt-K\",mac:\"Ctrl-Alt-G\"},scrollIntoView:\"cursor\",readOnly:!0}],t.multiSelectCommands=[{name:\"singleSelection\",description:\"Single selection\",bindKey:\"esc\",exec:function(e){e.exitMultiSelectMode()},scrollIntoView:\"cursor\",readOnly:!0,isAvailable:function(e){return e&&e.inMultiSelectMode}}];var r=e(\"../keyboard/hash_handler\").HashHandler;t.keyboardHandler=new r(t.multiSelectCommands)}),define(\"ace/multi_select\",[\"require\",\"exports\",\"module\",\"ace/range_list\",\"ace/range\",\"ace/selection\",\"ace/mouse/multi_select_handler\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/commands/multi_select_commands\",\"ace/search\",\"ace/edit_session\",\"ace/editor\",\"ace/config\"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){if(e.$multiselectOnSessionChange)return;e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),e.$multiselectOnSessionChange=t.onSessionChange.bind(e),e.$checkMultiselectChange=e.$checkMultiselectChange.bind(e),e.$multiselectOnSessionChange(e),e.on(\"changeSession\",e.$multiselectOnSessionChange),e.on(\"mousedown\",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function r(t){n&&(e.renderer.setMouseCursor(\"\"),n=!1)}if(!e.textInput)return;var t=e.textInput.getElement(),n=!1;u.addListener(t,\"keydown\",function(t){var i=t.keyCode==18&&!(t.ctrlKey||t.shiftKey||t.metaKey);e.$blockSelectEnabled&&i?n||(e.renderer.setMouseCursor(\"crosshair\"),n=!0):n&&r()},e),u.addListener(t,\"keyup\",r,e),u.addListener(t,\"blur\",r,e)}var r=e(\"./range_list\").RangeList,i=e(\"./range\").Range,s=e(\"./selection\").Selection,o=e(\"./mouse/multi_select_handler\").onMouseDown,u=e(\"./lib/event\"),a=e(\"./lib/lang\"),f=e(\"./commands/multi_select_commands\");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e(\"./search\").Search,c=new l,p=e(\"./edit_session\").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount===0){var n=this.toOrientedRange();this.rangeList.add(n),this.rangeList.add(e);if(this.rangeList.ranges.length!=2)return this.rangeList.removeAll(),t||this.fromOrientedRange(e);this.rangeList.removeAll(),this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._signal(\"multiSelect\"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length&&this.$onRemoveRange(e)},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal(\"addRange\",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal(\"removeRange\",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal(\"singleSelect\"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){var e=this.ranges.length?this.ranges:[this.getRange()],t=[];for(var n=0;n<e.length;n++){var r=e[n],s=r.start.row,o=r.end.row;if(s===o)t.push(r.clone());else{t.push(new i(s,r.start.column,s,this.session.getLine(s).length));while(++s<o)t.push(this.getLineRange(s,!0));t.push(new i(o,0,o,r.end.column))}n==0&&!this.isBackwards()&&(t=t.reverse())}this.toSingleRange();for(var n=t.length;n--;)this.addRange(t[n])},this.joinSelections=function(){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.cursor),s=this.session.documentToScreenPosition(this.anchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column<t.column;if(s)var o=e.column,u=t.column,a=e.offsetX,f=t.offsetX;else var o=t.column,u=e.column,a=t.offsetX,f=e.offsetX;var l=e.row<t.row;if(l)var c=e.row,h=t.row;else var c=t.row,h=e.row;o<0&&(o=0),c<0&&(c=0),c==h&&(n=!0);var p;for(var d=c;d<=h;d++){var m=i.fromPoints(this.session.screenToDocumentPosition(d,o,a),this.session.screenToDocumentPosition(d,u,f));if(m.isEmpty()){if(p&&v(m.end,p))break;p=m.end}m.cursor=s?m.start:m.end,r.push(m)}l&&r.reverse();if(!n){var g=r.length-1;while(r[g].isEmpty()&&g>0)g--;if(g>0){var y=0;while(r[y].isEmpty())y++}for(var b=g;b>=y;b--)r[b].isEmpty()&&r.splice(b,1)}return r}}.call(s.prototype);var d=e(\"./editor\").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,\"ace_selection\",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle(\"ace_multiselect\"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle(\"ace_multiselect\"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit(\"changeSelection\")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction==\"forEach\"?r=n.forEachSelection(t,e.args):t.multiSelectAction==\"forEachLine\"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction==\"single\"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges(),u.ranges[0]&&u.fromOrientedRange(u.ranges[0]);var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e=\"\";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r<t.length;r++)n.push(this.session.getTextRange(t[r]));var i=this.session.getDocument().getNewLineCharacter();e=n.join(i),e.length==(n.length-1)*i.length&&(e=\"\")}else this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange()));return e},this.$checkMultiselectChange=function(e,t){if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var n=this.multiSelect.ranges[0];if(this.multiSelect.isEmpty()&&t==this.multiSelect.anchor)return;var r=t==this.multiSelect.anchor?n.cursor==n.start?n.end:n.start:n.cursor;r.row!=t.row||this.session.$clipPositionToDocument(r.row,r.column).column!=t.column?this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()):this.multiSelect.mergeOverlappingRanges()}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle;if(t.needle==undefined){var r=this.selection.isEmpty()?this.selection.getWordRange():this.selection.getRange();t.needle=this.session.getTextRange(r)}this.$search.set(t);var i=this.$search.findAll(this.session);if(!i.length)return 0;var s=this.multiSelect;n||s.toSingleRange(i[0]);for(var o=i.length;o--;)s.addRange(i[o],!0);return r&&s.rangeList.rangeAtPoint(r.start)&&s.addRange(r,!0),i.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}n.fromOrientedRange(n.ranges[0])},this.selectMore=function(e,t,n){var r=this.session,i=r.multiSelect,s=i.toOrientedRange();if(s.isEmpty()){s=r.getWordRange(s.start.row,s.start.column),s.cursor=e==-1?s.start:s.end,this.multiSelect.addRange(s);if(n)return}var o=r.getTextRange(s),u=h(r,o,e);u&&(u.cursor=e==-1?u.start:u.end,this.session.unfold(u),this.multiSelect.addRange(u),this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(s.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges,r=-1,s=n.filter(function(e){if(e.cursor.row==r)return!0;r=e.cursor.row});if(!n.length||s.length==n.length-1){var o=this.selection.getRange(),u=o.start.row,f=o.end.row,l=u==f;if(l){var c=this.session.getLength(),h;do h=this.session.getLine(f);while(/[=:]/.test(h)&&++f<c);do h=this.session.getLine(u);while(/[=:]/.test(h)&&--u>0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join(\"\\n\")+\"\\n\"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),i<v&&(v=i),i});n.forEach(function(t,n){var r=t.cursor,s=d-r.column,o=m[n]-v;s>o?e.insert(r,a.stringRepeat(\" \",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(\" \",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\\s*)(.*?)(\\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),s<t[2].length&&(s=t[2].length),o>t[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off(\"addRange\",this.$onAddRange),n.multiSelect.off(\"removeRange\",this.$onRemoveRange),n.multiSelect.off(\"multiSelect\",this.$onMultiSelect),n.multiSelect.off(\"singleSelect\",this.$onSingleSelect),n.multiSelect.lead.off(\"change\",this.$checkMultiselectChange),n.multiSelect.anchor.off(\"change\",this.$checkMultiselectChange)),t&&(t.multiSelect.on(\"addRange\",this.$onAddRange),t.multiSelect.on(\"removeRange\",this.$onRemoveRange),t.multiSelect.on(\"multiSelect\",this.$onMultiSelect),t.multiSelect.on(\"singleSelect\",this.$onSingleSelect),t.multiSelect.lead.on(\"change\",this.$checkMultiselectChange),t.multiSelect.anchor.on(\"change\",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e(\"./config\").defineOptions(d.prototype,\"editor\",{enableMultiselect:{set:function(e){m(this),e?this.on(\"mousedown\",o):this.off(\"mousedown\",o)},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define(\"ace/mode/folding/fold_mode\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../../range\").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?\"start\":t==\"markbeginend\"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?\"end\":\"\"},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++t<a){var c=e.getLine(t).search(i);if(c==-1)continue;if(c<=o){var h=e.getTokenAt(t,0);if(!h||h.type!==\"string\")break}l=t}if(l>f){var p=e.getLine(l).length;return new r(f,u,l,p)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a==\"start\"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define(\"ace/ext/error_marker\",[\"require\",\"exports\",\"module\",\"ace/line_widgets\",\"ace/lib/dom\",\"ace/range\",\"ace/config\"],function(e,t,n){\"use strict\";function u(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function a(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=u(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var o=r[i];if(!o||!n)return;if(o.row===t){do o=r[i+=n];while(o&&o.row===t);if(!o)return r.slice()}var a=[];t=o.row;do a[n<0?\"unshift\":\"push\"](o),o=r[i+=n];while(o&&o.row==t);return a.length&&a}var r=e(\"../line_widgets\").LineWidgets,i=e(\"../lib/dom\"),s=e(\"../range\").Range,o=e(\"../config\").nls;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),u=s.row,f=n.widgetManager.getWidgetsAtRow(u).filter(function(e){return e.type==\"errorMarker\"})[0];f?f.destroy():u-=t;var l=a(n,u,t),c;if(l){var h=l[0];s.column=(h.pos&&typeof h.column!=\"number\"?h.pos.sc:h.column)||0,s.row=h.row,c=e.renderer.$gutterLayer.$annotations[s.row]}else{if(f)return;c={text:[o(\"Looks good!\")],className:\"ace_ok\"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var p={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement(\"div\"),type:\"errorMarker\"},d=p.el.appendChild(i.createElement(\"div\")),v=p.el.appendChild(i.createElement(\"div\"));v.className=\"error_widget_arrow \"+c.className;var m=e.renderer.$cursorLayer.getPixelPosition(s).left;v.style.left=m+e.renderer.gutterWidth-5+\"px\",p.el.className=\"error_widget_wrapper\",d.className=\"error_widget \"+c.className,d.innerHTML=c.text.join(\"<br>\"),d.appendChild(i.createElement(\"div\"));var g=function(e,t,n){if(t===0&&(n===\"esc\"||n===\"return\"))return p.destroy(),{command:\"null\"}};p.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(g),n.widgetManager.removeLineWidget(p),e.off(\"changeSelection\",p.destroy),e.off(\"changeSession\",p.destroy),e.off(\"mouseup\",p.destroy),e.off(\"change\",p.destroy)},e.keyBinding.addKeyboardHandler(g),e.on(\"changeSelection\",p.destroy),e.on(\"changeSession\",p.destroy),e.on(\"mouseup\",p.destroy),e.on(\"change\",p.destroy),e.session.widgetManager.addLineWidget(p),p.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:p.el.offsetHeight})},i.importCssString(\"\\n    .error_widget_wrapper {\\n        background: inherit;\\n        color: inherit;\\n        border:none\\n    }\\n    .error_widget {\\n        border-top: solid 2px;\\n        border-bottom: solid 2px;\\n        margin: 5px 0;\\n        padding: 10px 40px;\\n        white-space: pre-wrap;\\n    }\\n    .error_widget.ace_error, .error_widget_arrow.ace_error{\\n        border-color: #ff5a5a\\n    }\\n    .error_widget.ace_warning, .error_widget_arrow.ace_warning{\\n        border-color: #F1D817\\n    }\\n    .error_widget.ace_info, .error_widget_arrow.ace_info{\\n        border-color: #5a5a5a\\n    }\\n    .error_widget.ace_ok, .error_widget_arrow.ace_ok{\\n        border-color: #5aaa5a\\n    }\\n    .error_widget_arrow {\\n        position: absolute;\\n        border: solid 5px;\\n        border-top-color: transparent!important;\\n        border-right-color: transparent!important;\\n        border-left-color: transparent!important;\\n        top: -5px;\\n    }\\n\",\"error_marker.css\",!1)}),define(\"ace/ace\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/range\",\"ace/editor\",\"ace/edit_session\",\"ace/undomanager\",\"ace/virtual_renderer\",\"ace/worker/worker_client\",\"ace/keyboard/hash_handler\",\"ace/placeholder\",\"ace/multi_select\",\"ace/mode/folding/fold_mode\",\"ace/theme/textmate\",\"ace/ext/error_marker\",\"ace/config\",\"ace/loader_build\"],function(e,t,n){\"use strict\";e(\"./loader_build\")(t);var r=e(\"./lib/dom\"),i=e(\"./range\").Range,s=e(\"./editor\").Editor,o=e(\"./edit_session\").EditSession,u=e(\"./undomanager\").UndoManager,a=e(\"./virtual_renderer\").VirtualRenderer;e(\"./worker/worker_client\"),e(\"./keyboard/hash_handler\"),e(\"./placeholder\"),e(\"./multi_select\"),e(\"./mode/folding/fold_mode\"),e(\"./theme/textmate\"),e(\"./ext/error_marker\"),t.config=e(\"./config\"),t.edit=function(e,n){if(typeof e==\"string\"){var i=e;e=document.getElementById(i);if(!e)throw new Error(\"ace.edit can't find div #\"+i)}if(e&&e.env&&e.env.editor instanceof s)return e.env.editor;var o=\"\";if(e&&/input|textarea/i.test(e.tagName)){var u=e;o=u.value,e=r.createElement(\"pre\"),u.parentNode.replaceChild(e,u)}else e&&(o=e.textContent,e.innerHTML=\"\");var f=t.createEditSession(o),l=new s(new a(e),f,n),c={document:f,editor:l,onResize:l.resize.bind(l,null)};return u&&(c.textarea=u),l.on(\"destroy\",function(){c.editor.container.env=null}),l.container.env=l.env=c,l},t.createEditSession=function(e,t){var n=new o(e,t);return n.setUndoManager(new u),n},t.Range=i,t.Editor=s,t.EditSession=o,t.UndoManager=u,t.VirtualRenderer=a,t.version=t.config.version});            (function() {\n                window.require([\"ace/ace\"], function(a) {\n                    if (a) {\n                        a.config.init(true);\n                        a.define = window.define;\n                    }\n                    if (!window.ace)\n                        window.ace = a;\n                    for (var key in a) if (a.hasOwnProperty(key))\n                        window.ace[key] = a[key];\n                    window.ace[\"default\"] = window.ace;\n                    if (typeof module == \"object\" && typeof exports == \"object\" && module) {\n                        module.exports = window.ace;\n                    }\n                });\n            })();\n        "
  },
  {
    "path": "web/ace-builds/ext-language_tools.js",
    "content": "define(\"ace/snippets\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event_emitter\",\"ace/lib/lang\",\"ace/range\",\"ace/range_list\",\"ace/keyboard/hash_handler\",\"ace/tokenizer\",\"ace/clipboard\",\"ace/editor\"],function(e,t,n){\"use strict\";function p(e){var t=(new Date).toLocaleString(\"en-us\",e);return t.length==1?\"0\"+t:t}var r=e(\"./lib/dom\"),i=e(\"./lib/oop\"),s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./lib/lang\"),u=e(\"./range\").Range,a=e(\"./range_list\").RangeList,f=e(\"./keyboard/hash_handler\").HashHandler,l=e(\"./tokenizer\").Tokenizer,c=e(\"./clipboard\"),h={CURRENT_WORD:function(e){return e.session.getTextRange(e.session.getWordRange())},SELECTION:function(e,t,n){var r=e.session.getTextRange();return n?r.replace(/\\n\\r?([ \\t]*\\S)/g,\"\\n\"+n+\"$1\"):r},CURRENT_LINE:function(e){return e.session.getLine(e.getCursorPosition().row)},PREV_LINE:function(e){return e.session.getLine(e.getCursorPosition().row-1)},LINE_INDEX:function(e){return e.getCursorPosition().row},LINE_NUMBER:function(e){return e.getCursorPosition().row+1},SOFT_TABS:function(e){return e.session.getUseSoftTabs()?\"YES\":\"NO\"},TAB_SIZE:function(e){return e.session.getTabSize()},CLIPBOARD:function(e){return c.getText&&c.getText()},FILENAME:function(e){return/[^/\\\\]*$/.exec(this.FILEPATH(e))[0]},FILENAME_BASE:function(e){return/[^/\\\\]*$/.exec(this.FILEPATH(e))[0].replace(/\\.[^.]*$/,\"\")},DIRECTORY:function(e){return this.FILEPATH(e).replace(/[^/\\\\]*$/,\"\")},FILEPATH:function(e){return\"/not implemented.txt\"},WORKSPACE_NAME:function(){return\"Unknown\"},FULLNAME:function(){return\"Unknown\"},BLOCK_COMMENT_START:function(e){var t=e.session.$mode||{};return t.blockComment&&t.blockComment.start||\"\"},BLOCK_COMMENT_END:function(e){var t=e.session.$mode||{};return t.blockComment&&t.blockComment.end||\"\"},LINE_COMMENT:function(e){var t=e.session.$mode||{};return t.lineCommentStart||\"\"},CURRENT_YEAR:p.bind(null,{year:\"numeric\"}),CURRENT_YEAR_SHORT:p.bind(null,{year:\"2-digit\"}),CURRENT_MONTH:p.bind(null,{month:\"numeric\"}),CURRENT_MONTH_NAME:p.bind(null,{month:\"long\"}),CURRENT_MONTH_NAME_SHORT:p.bind(null,{month:\"short\"}),CURRENT_DATE:p.bind(null,{day:\"2-digit\"}),CURRENT_DAY_NAME:p.bind(null,{weekday:\"long\"}),CURRENT_DAY_NAME_SHORT:p.bind(null,{weekday:\"short\"}),CURRENT_HOUR:p.bind(null,{hour:\"2-digit\",hour12:!1}),CURRENT_MINUTE:p.bind(null,{minute:\"2-digit\"}),CURRENT_SECOND:p.bind(null,{second:\"2-digit\"})};h.SELECTED_TEXT=h.SELECTION;var d=function(){function e(){this.snippetMap={},this.snippetNameMap={},this.variables=h}return e.prototype.getTokenizer=function(){return e.$tokenizer||this.createTokenizer()},e.prototype.createTokenizer=function(){function t(e){return e=e.substr(1),/^\\d+$/.test(e)?[{tabstopId:parseInt(e,10)}]:[{text:e}]}function n(e){return\"(?:[^\\\\\\\\\"+e+\"]|\\\\\\\\.)\"}var r={regex:\"/(\"+n(\"/\")+\"+)/\",onMatch:function(e,t,n){var r=n[0];return r.fmtString=!0,r.guard=e.slice(1,-1),r.flag=\"\",\"\"},next:\"formatString\"};return e.$tokenizer=new l({start:[{regex:/\\\\./,onMatch:function(e,t,n){var r=e[1];return r==\"}\"&&n.length?e=r:\"`$\\\\\".indexOf(r)!=-1&&(e=r),[e]}},{regex:/}/,onMatch:function(e,t,n){return[n.length?n.shift():e]}},{regex:/\\$(?:\\d+|\\w+)/,onMatch:t},{regex:/\\$\\{[\\dA-Z_a-z]+/,onMatch:function(e,n,r){var i=t(e.substr(1));return r.unshift(i[0]),i},next:\"snippetVar\"},{regex:/\\n/,token:\"newline\",merge:!1}],snippetVar:[{regex:\"\\\\|\"+n(\"\\\\|\")+\"*\\\\|\",onMatch:function(e,t,n){var r=e.slice(1,-1).replace(/\\\\[,|\\\\]|,/g,function(e){return e.length==2?e[1]:\"\\0\"}).split(\"\\0\").map(function(e){return{value:e}});return n[0].choices=r,[r[0]]},next:\"start\"},r,{regex:\"([^:}\\\\\\\\]|\\\\\\\\.)*:?\",token:\"\",next:\"start\"}],formatString:[{regex:/:/,onMatch:function(e,t,n){return n.length&&n[0].expectElse?(n[0].expectElse=!1,n[0].ifEnd={elseEnd:n[0]},[n[0].ifEnd]):\":\"}},{regex:/\\\\./,onMatch:function(e,t,n){var r=e[1];return r==\"}\"&&n.length?e=r:\"`$\\\\\".indexOf(r)!=-1?e=r:r==\"n\"?e=\"\\n\":r==\"t\"?e=\"\t\":\"ulULE\".indexOf(r)!=-1&&(e={changeCase:r,local:r>\"a\"}),[e]}},{regex:\"/\\\\w*}\",onMatch:function(e,t,n){var r=n.shift();return r&&(r.flag=e.slice(1,-1)),this.next=r&&r.tabstopId?\"start\":\"\",[r||e]},next:\"start\"},{regex:/\\$(?:\\d+|\\w+)/,onMatch:function(e,t,n){return[{text:e.slice(1)}]}},{regex:/\\${\\w+/,onMatch:function(e,t,n){var r={text:e.slice(2)};return n.unshift(r),[r]},next:\"formatStringVar\"},{regex:/\\n/,token:\"newline\",merge:!1},{regex:/}/,onMatch:function(e,t,n){var r=n.shift();return this.next=r&&r.tabstopId?\"start\":\"\",[r||e]},next:\"start\"}],formatStringVar:[{regex:/:\\/\\w+}/,onMatch:function(e,t,n){var r=n[0];return r.formatFunction=e.slice(2,-1),[n.shift()]},next:\"formatString\"},r,{regex:/:[\\?\\-+]?/,onMatch:function(e,t,n){e[1]==\"+\"&&(n[0].ifEnd=n[0]),e[1]==\"?\"&&(n[0].expectElse=!0)},next:\"formatString\"},{regex:\"([^:}\\\\\\\\]|\\\\\\\\.)*:?\",token:\"\",next:\"formatString\"}]}),e.$tokenizer},e.prototype.tokenizeTmSnippet=function(e,t){return this.getTokenizer().getLineTokens(e,t).tokens.map(function(e){return e.value||e})},e.prototype.getVariableValue=function(e,t,n){if(/^\\d+$/.test(t))return(this.variables.__||{})[t]||\"\";if(/^[A-Z]\\d+$/.test(t))return(this.variables[t[0]+\"__\"]||{})[t.substr(1)]||\"\";t=t.replace(/^TM_/,\"\");if(!this.variables.hasOwnProperty(t))return\"\";var r=this.variables[t];return typeof r==\"function\"&&(r=this.variables[t](e,t,n)),r==null?\"\":r},e.prototype.tmStrFormat=function(e,t,n){if(!t.fmt)return e;var r=t.flag||\"\",i=t.guard;i=new RegExp(i,r.replace(/[^gim]/g,\"\"));var s=typeof t.fmt==\"string\"?this.tokenizeTmSnippet(t.fmt,\"formatString\"):t.fmt,o=this,u=e.replace(i,function(){var e=o.variables.__;o.variables.__=[].slice.call(arguments);var t=o.resolveVariables(s,n),r=\"E\";for(var i=0;i<t.length;i++){var u=t[i];if(typeof u==\"object\"){t[i]=\"\";if(u.changeCase&&u.local){var a=t[i+1];a&&typeof a==\"string\"&&(u.changeCase==\"u\"?t[i]=a[0].toUpperCase():t[i]=a[0].toLowerCase(),t[i+1]=a.substr(1))}else u.changeCase&&(r=u.changeCase)}else r==\"U\"?t[i]=u.toUpperCase():r==\"L\"&&(t[i]=u.toLowerCase())}return o.variables.__=e,t.join(\"\")});return u},e.prototype.tmFormatFunction=function(e,t,n){return t.formatFunction==\"upcase\"?e.toUpperCase():t.formatFunction==\"downcase\"?e.toLowerCase():e},e.prototype.resolveVariables=function(e,t){function f(t){var n=e.indexOf(t,s+1);n!=-1&&(s=n)}var n=[],r=\"\",i=!0;for(var s=0;s<e.length;s++){var o=e[s];if(typeof o==\"string\"){n.push(o),o==\"\\n\"?(i=!0,r=\"\"):i&&(r=/^\\t*/.exec(o)[0],i=/\\S/.test(o));continue}if(!o)continue;i=!1;if(o.fmtString){var u=e.indexOf(o,s+1);u==-1&&(u=e.length),o.fmt=e.slice(s+1,u),s=u}if(o.text){var a=this.getVariableValue(t,o.text,r)+\"\";o.fmtString&&(a=this.tmStrFormat(a,o,t)),o.formatFunction&&(a=this.tmFormatFunction(a,o,t)),a&&!o.ifEnd?(n.push(a),f(o)):!a&&o.ifEnd&&f(o.ifEnd)}else o.elseEnd?f(o.elseEnd):o.tabstopId!=null?n.push(o):o.changeCase!=null&&n.push(o)}return n},e.prototype.getDisplayTextForSnippet=function(e,t){var n=v.call(this,e,t);return n.text},e.prototype.insertSnippetForSelection=function(e,t,n){n===void 0&&(n={});var r=v.call(this,e,t,n),i=e.getSelectionRange();n.range&&n.range.compareRange(i)===0&&(i=n.range);var s=e.session.replace(i,r.text),o=new m(e),u=e.inVirtualSelectionMode&&e.selection.index;o.addTabstops(r.tabstops,i.start,s,u)},e.prototype.insertSnippet=function(e,t,n){n===void 0&&(n={});var r=this;n.range&&!(n.range instanceof u)&&(n.range=u.fromPoints(n.range.start,n.range.end));if(e.inVirtualSelectionMode)return r.insertSnippetForSelection(e,t,n);e.forEachSelection(function(){r.insertSnippetForSelection(e,t,n)},null,{keepOrder:!0}),e.tabstopManager&&e.tabstopManager.tabNext()},e.prototype.$getScope=function(e){var t=e.session.$mode.$id||\"\";t=t.split(\"/\").pop();if(t===\"html\"||t===\"php\"){t===\"php\"&&!e.session.$mode.inlinePhp&&(t=\"html\");var n=e.getCursorPosition(),r=e.session.getState(n.row);typeof r==\"object\"&&(r=r[0]),r.substring&&(r.substring(0,3)==\"js-\"?t=\"javascript\":r.substring(0,4)==\"css-\"?t=\"css\":r.substring(0,4)==\"php-\"&&(t=\"php\"))}return t},e.prototype.getActiveScopes=function(e){var t=this.$getScope(e),n=[t],r=this.snippetMap;return r[t]&&r[t].includeScopes&&n.push.apply(n,r[t].includeScopes),n.push(\"_\"),n},e.prototype.expandWithTab=function(e,t){var n=this,r=e.forEachSelection(function(){return n.expandSnippetForSelection(e,t)},null,{keepOrder:!0});return r&&e.tabstopManager&&e.tabstopManager.tabNext(),r},e.prototype.expandSnippetForSelection=function(e,t){var n=e.getCursorPosition(),r=e.session.getLine(n.row),i=r.substring(0,n.column),s=r.substr(n.column),o=this.snippetMap,u;return this.getActiveScopes(e).some(function(e){var t=o[e];return t&&(u=this.findMatchingSnippet(t,i,s)),!!u},this),u?t&&t.dryRun?!0:(e.session.doc.removeInLine(n.row,n.column-u.replaceBefore.length,n.column+u.replaceAfter.length),this.variables.M__=u.matchBefore,this.variables.T__=u.matchAfter,this.insertSnippetForSelection(e,u.content),this.variables.M__=this.variables.T__=null,!0):!1},e.prototype.findMatchingSnippet=function(e,t,n){for(var r=e.length;r--;){var i=e[r];if(i.startRe&&!i.startRe.test(t))continue;if(i.endRe&&!i.endRe.test(n))continue;if(!i.startRe&&!i.endRe)continue;return i.matchBefore=i.startRe?i.startRe.exec(t):[\"\"],i.matchAfter=i.endRe?i.endRe.exec(n):[\"\"],i.replaceBefore=i.triggerRe?i.triggerRe.exec(t)[0]:\"\",i.replaceAfter=i.endTriggerRe?i.endTriggerRe.exec(n)[0]:\"\",i}},e.prototype.register=function(e,t){function s(e){return e&&!/^\\^?\\(.*\\)\\$?$|^\\\\b$/.test(e)&&(e=\"(?:\"+e+\")\"),e||\"\"}function u(e,t,n){return e=s(e),t=s(t),n?(e=t+e,e&&e[e.length-1]!=\"$\"&&(e+=\"$\")):(e+=t,e&&e[0]!=\"^\"&&(e=\"^\"+e)),new RegExp(e)}function a(e){e.scope||(e.scope=t||\"_\"),t=e.scope,n[t]||(n[t]=[],r[t]={});var s=r[t];if(e.name){var a=s[e.name];a&&i.unregister(a),s[e.name]=e}n[t].push(e),e.prefix&&(e.tabTrigger=e.prefix),!e.content&&e.body&&(e.content=Array.isArray(e.body)?e.body.join(\"\\n\"):e.body),e.tabTrigger&&!e.trigger&&(!e.guard&&/^\\w/.test(e.tabTrigger)&&(e.guard=\"\\\\b\"),e.trigger=o.escapeRegExp(e.tabTrigger));if(!e.trigger&&!e.guard&&!e.endTrigger&&!e.endGuard)return;e.startRe=u(e.trigger,e.guard,!0),e.triggerRe=new RegExp(e.trigger),e.endRe=u(e.endTrigger,e.endGuard,!0),e.endTriggerRe=new RegExp(e.endTrigger)}var n=this.snippetMap,r=this.snippetNameMap,i=this;e||(e=[]),Array.isArray(e)?e.forEach(a):Object.keys(e).forEach(function(t){a(e[t])}),this._signal(\"registerSnippets\",{scope:t})},e.prototype.unregister=function(e,t){function i(e){var i=r[e.scope||t];if(i&&i[e.name]){delete i[e.name];var s=n[e.scope||t],o=s&&s.indexOf(e);o>=0&&s.splice(o,1)}}var n=this.snippetMap,r=this.snippetNameMap;e.content?i(e):Array.isArray(e)&&e.forEach(i)},e.prototype.parseSnippetFile=function(e){e=e.replace(/\\r/g,\"\");var t=[],n={},r=/^#.*|^({[\\s\\S]*})\\s*$|^(\\S+) (.*)$|^((?:\\n*\\t.*)+)/gm,i;while(i=r.exec(e)){if(i[1])try{n=JSON.parse(i[1]),t.push(n)}catch(s){}if(i[4])n.content=i[4].replace(/^\\t/gm,\"\"),t.push(n),n={};else{var o=i[2],u=i[3];if(o==\"regex\"){var a=/\\/((?:[^\\/\\\\]|\\\\.)*)|$/g;n.guard=a.exec(u)[1],n.trigger=a.exec(u)[1],n.endTrigger=a.exec(u)[1],n.endGuard=a.exec(u)[1]}else o==\"snippet\"?(n.tabTrigger=u.match(/^\\S*/)[0],n.name||(n.name=u)):o&&(n[o]=u)}}return t},e.prototype.getSnippetByName=function(e,t){var n=this.snippetNameMap,r;return this.getActiveScopes(t).some(function(t){var i=n[t];return i&&(r=i[e]),!!r},this),r},e}();i.implement(d.prototype,s);var v=function(e,t,n){function l(e){var t=[];for(var n=0;n<e.length;n++){var r=e[n];if(typeof r==\"object\"){if(f[r.tabstopId])continue;var i=e.lastIndexOf(r,n-1);r=t[i]||{tabstopId:r.tabstopId}}t[n]=r}return t}n===void 0&&(n={});var r=e.getCursorPosition(),i=e.session.getLine(r.row),s=e.session.getTabString(),o=i.match(/^\\s*/)[0];r.column<o.length&&(o=o.slice(0,r.column)),t=t.replace(/\\r/g,\"\");var u=this.tokenizeTmSnippet(t);u=this.resolveVariables(u,e),u=u.map(function(e){return e==\"\\n\"&&!n.excludeExtraIndent?e+o:typeof e==\"string\"?e.replace(/\\t/g,s):e});var a=[];u.forEach(function(e,t){if(typeof e!=\"object\")return;var n=e.tabstopId,r=a[n];r||(r=a[n]=[],r.index=n,r.value=\"\",r.parents={});if(r.indexOf(e)!==-1)return;e.choices&&!r.choices&&(r.choices=e.choices),r.push(e);var i=u.indexOf(e,t+1);if(i===-1)return;var s=u.slice(t+1,i),o=s.some(function(e){return typeof e==\"object\"});o&&!r.value?r.value=s:s.length&&(!r.value||typeof r.value!=\"string\")&&(r.value=s.join(\"\"))}),a.forEach(function(e){e.length=0});var f={};for(var c=0;c<u.length;c++){var h=u[c];if(typeof h!=\"object\")continue;var p=h.tabstopId,d=a[p],v=u.indexOf(h,c+1);if(f[p]){f[p]===h&&(delete f[p],Object.keys(f).forEach(function(e){d.parents[e]=!0}));continue}f[p]=h;var m=d.value;typeof m!=\"string\"?m=l(m):h.fmt&&(m=this.tmStrFormat(m,h,e)),u.splice.apply(u,[c+1,Math.max(0,v-c)].concat(m,h)),d.indexOf(h)===-1&&d.push(h)}var g=0,y=0,b=\"\";return u.forEach(function(e){if(typeof e==\"string\"){var t=e.split(\"\\n\");t.length>1?(y=t[t.length-1].length,g+=t.length-1):y+=e.length,b+=e}else e&&(e.start?e.end={row:g,column:y}:e.start={row:g,column:y})}),{text:b,tabstops:a,tokens:u}},m=function(){function e(e){this.index=0,this.ranges=[],this.tabstops=[];if(e.tabstopManager)return e.tabstopManager;e.tabstopManager=this,this.$onChange=this.onChange.bind(this),this.$onChangeSelection=o.delayedCall(this.onChangeSelection.bind(this)).schedule,this.$onChangeSession=this.onChangeSession.bind(this),this.$onAfterExec=this.onAfterExec.bind(this),this.attach(e)}return e.prototype.attach=function(e){this.$openTabstops=null,this.selectedTabstop=null,this.editor=e,this.session=e.session,this.editor.on(\"change\",this.$onChange),this.editor.on(\"changeSelection\",this.$onChangeSelection),this.editor.on(\"changeSession\",this.$onChangeSession),this.editor.commands.on(\"afterExec\",this.$onAfterExec),this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},e.prototype.detach=function(){this.tabstops.forEach(this.removeTabstopMarkers,this),this.ranges.length=0,this.tabstops.length=0,this.selectedTabstop=null,this.editor.off(\"change\",this.$onChange),this.editor.off(\"changeSelection\",this.$onChangeSelection),this.editor.off(\"changeSession\",this.$onChangeSession),this.editor.commands.off(\"afterExec\",this.$onAfterExec),this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.tabstopManager=null,this.session=null,this.editor=null},e.prototype.onChange=function(e){var t=e.action[0]==\"r\",n=this.selectedTabstop||{},r=n.parents||{},i=this.tabstops.slice();for(var s=0;s<i.length;s++){var o=i[s],u=o==n||r[o.index];o.rangeList.$bias=u?0:1;if(e.action==\"remove\"&&o!==n){var a=o.parents&&o.parents[n.index],f=o.rangeList.pointIndex(e.start,a);f=f<0?-f-1:f+1;var l=o.rangeList.pointIndex(e.end,a);l=l<0?-l-1:l-1;var c=o.rangeList.ranges.slice(f,l);for(var h=0;h<c.length;h++)this.removeRange(c[h])}o.rangeList.$onChange(e)}var p=this.session;!this.$inChange&&t&&p.getLength()==1&&!p.getValue()&&this.detach()},e.prototype.updateLinkedFields=function(){var e=this.selectedTabstop;if(!e||!e.hasLinkedRanges||!e.firstNonLinked)return;this.$inChange=!0;var n=this.session,r=n.getTextRange(e.firstNonLinked);for(var i=0;i<e.length;i++){var s=e[i];if(!s.linked)continue;var o=s.original,u=t.snippetManager.tmStrFormat(r,o,this.editor);n.replace(s,u)}this.$inChange=!1},e.prototype.onAfterExec=function(e){e.command&&!e.command.readOnly&&this.updateLinkedFields()},e.prototype.onChangeSelection=function(){if(!this.editor)return;var e=this.editor.selection.lead,t=this.editor.selection.anchor,n=this.editor.selection.isEmpty();for(var r=0;r<this.ranges.length;r++){if(this.ranges[r].linked)continue;var i=this.ranges[r].contains(e.row,e.column),s=n||this.ranges[r].contains(t.row,t.column);if(i&&s)return}this.detach()},e.prototype.onChangeSession=function(){this.detach()},e.prototype.tabNext=function(e){var t=this.tabstops.length,n=this.index+(e||1);n=Math.min(Math.max(n,1),t),n==t&&(n=0),this.selectTabstop(n),n===0&&this.detach()},e.prototype.selectTabstop=function(e){this.$openTabstops=null;var t=this.tabstops[this.index];t&&this.addTabstopMarkers(t),this.index=e,t=this.tabstops[this.index];if(!t||!t.length)return;this.selectedTabstop=t;var n=t.firstNonLinked||t;t.choices&&(n.cursor=n.start);if(!this.editor.inVirtualSelectionMode){var r=this.editor.multiSelect;r.toSingleRange(n);for(var i=0;i<t.length;i++){if(t.hasLinkedRanges&&t[i].linked)continue;r.addRange(t[i].clone(),!0)}}else this.editor.selection.fromOrientedRange(n);this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler),this.selectedTabstop&&this.selectedTabstop.choices&&this.editor.execCommand(\"startAutocomplete\",{matches:this.selectedTabstop.choices})},e.prototype.addTabstops=function(e,t,n){var r=this.useLink||!this.editor.getOption(\"enableMultiselect\");this.$openTabstops||(this.$openTabstops=[]);if(!e[0]){var i=u.fromPoints(n,n);y(i.start,t),y(i.end,t),e[0]=[i],e[0].index=0}var s=this.index,o=[s+1,0],f=this.ranges;e.forEach(function(e,n){var i=this.$openTabstops[n]||e;for(var s=0;s<e.length;s++){var l=e[s],c=u.fromPoints(l.start,l.end||l.start);g(c.start,t),g(c.end,t),c.original=l,c.tabstop=i,f.push(c),i!=e?i.unshift(c):i[s]=c,l.fmtString||i.firstNonLinked&&r?(c.linked=!0,i.hasLinkedRanges=!0):i.firstNonLinked||(i.firstNonLinked=c)}i.firstNonLinked||(i.hasLinkedRanges=!1),i===e&&(o.push(i),this.$openTabstops[n]=i),this.addTabstopMarkers(i),i.rangeList=i.rangeList||new a,i.rangeList.$bias=0,i.rangeList.addList(i)},this),o.length>2&&(this.tabstops.length&&o.push(o.splice(2,1)[0]),this.tabstops.splice.apply(this.tabstops,o))},e.prototype.addTabstopMarkers=function(e){var t=this.session;e.forEach(function(e){e.markerId||(e.markerId=t.addMarker(e,\"ace_snippet-marker\",\"text\"))})},e.prototype.removeTabstopMarkers=function(e){var t=this.session;e.forEach(function(e){t.removeMarker(e.markerId),e.markerId=null})},e.prototype.removeRange=function(e){var t=e.tabstop.indexOf(e);t!=-1&&e.tabstop.splice(t,1),t=this.ranges.indexOf(e),t!=-1&&this.ranges.splice(t,1),t=e.tabstop.rangeList.ranges.indexOf(e),t!=-1&&e.tabstop.splice(t,1),this.session.removeMarker(e.markerId),e.tabstop.length||(t=this.tabstops.indexOf(e.tabstop),t!=-1&&this.tabstops.splice(t,1),this.tabstops.length||this.detach())},e}();m.prototype.keyboardHandler=new f,m.prototype.keyboardHandler.bindKeys({Tab:function(e){if(t.snippetManager&&t.snippetManager.expandWithTab(e))return;e.tabstopManager.tabNext(1),e.renderer.scrollCursorIntoView()},\"Shift-Tab\":function(e){e.tabstopManager.tabNext(-1),e.renderer.scrollCursorIntoView()},Esc:function(e){e.tabstopManager.detach()}});var g=function(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row},y=function(e,t){e.row==t.row&&(e.column-=t.column),e.row-=t.row};r.importCssString(\"\\n.ace_snippet-marker {\\n    -moz-box-sizing: border-box;\\n    box-sizing: border-box;\\n    background: rgba(194, 193, 208, 0.09);\\n    border: 1px dotted rgba(211, 208, 235, 0.62);\\n    position: absolute;\\n}\",\"snippets.css\",!1),t.snippetManager=new d;var b=e(\"./editor\").Editor;(function(){this.insertSnippet=function(e,n){return t.snippetManager.insertSnippet(this,e,n)},this.expandSnippet=function(e){return t.snippetManager.expandWithTab(this,e)}}).call(b.prototype)}),define(\"ace/autocomplete/popup\",[\"require\",\"exports\",\"module\",\"ace/virtual_renderer\",\"ace/editor\",\"ace/range\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/lib/dom\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../virtual_renderer\").VirtualRenderer,i=e(\"../editor\").Editor,s=e(\"../range\").Range,o=e(\"../lib/event\"),u=e(\"../lib/lang\"),a=e(\"../lib/dom\"),f=e(\"../config\").nls,l=function(e){return\"suggest-aria-id:\".concat(e)},c=function(e){var t=new r(e);t.$maxLines=4;var n=new i(t);return n.setHighlightActiveLine(!1),n.setShowPrintMargin(!1),n.renderer.setShowGutter(!1),n.renderer.setHighlightGutterLine(!1),n.$mouseHandler.$focusTimeout=0,n.$highlightTagPending=!0,n},h=function(){function e(e){var t=a.createElement(\"div\"),n=new c(t);e&&e.appendChild(t),t.style.display=\"none\",n.renderer.content.style.cursor=\"default\",n.renderer.setStyle(\"ace_autocomplete\"),n.renderer.container.setAttribute(\"role\",\"listbox\"),n.renderer.container.setAttribute(\"aria-label\",f(\"Autocomplete suggestions\")),n.setOption(\"displayIndentGuides\",!1),n.setOption(\"dragDelay\",150);var r=function(){};n.focus=r,n.$isFocused=!0,n.renderer.$cursorLayer.restartTimer=r,n.renderer.$cursorLayer.element.style.opacity=0,n.renderer.$maxLines=8,n.renderer.$keepTextAreaAtCursor=!1,n.setHighlightActiveLine(!1),n.session.highlight(\"\"),n.session.$searchHighlight.clazz=\"ace_highlight-marker\",n.on(\"mousedown\",function(e){var t=e.getDocumentPosition();n.selection.moveToPosition(t),p.start.row=p.end.row=t.row,e.stop()});var i,h=new s(-1,0,-1,Infinity),p=new s(-1,0,-1,Infinity);p.id=n.session.addMarker(p,\"ace_active-line\",\"fullLine\"),n.setSelectOnHover=function(e){e?h.id&&(n.session.removeMarker(h.id),h.id=null):h.id=n.session.addMarker(h,\"ace_line-hover\",\"fullLine\")},n.setSelectOnHover(!1),n.on(\"mousemove\",function(e){if(!i){i=e;return}if(i.x==e.x&&i.y==e.y)return;i=e,i.scrollTop=n.renderer.scrollTop;var t=i.getDocumentPosition().row;h.start.row!=t&&(h.id||n.setRow(t),v(t))}),n.renderer.on(\"beforeRender\",function(){if(i&&h.start.row!=-1){i.$pos=null;var e=i.getDocumentPosition().row;h.id||n.setRow(e),v(e,!0)}}),n.renderer.on(\"afterRender\",function(){var e=n.getRow(),t=n.renderer.$textLayer,r=t.element.childNodes[e-t.config.firstRow],i=document.activeElement;r!==t.selectedNode&&t.selectedNode&&(a.removeCssClass(t.selectedNode,\"ace_selected\"),i.removeAttribute(\"aria-activedescendant\"),t.selectedNode.removeAttribute(\"id\")),t.selectedNode=r;if(r){a.addCssClass(r,\"ace_selected\");var s=l(e);r.id=s,n.renderer.container.setAttribute(\"aria-activedescendant\",s),i.setAttribute(\"aria-activedescendant\",s),r.setAttribute(\"role\",\"option\"),r.setAttribute(\"aria-label\",n.getData(e).value),r.setAttribute(\"aria-setsize\",n.data.length),r.setAttribute(\"aria-posinset\",e),r.setAttribute(\"aria-describedby\",\"doc-tooltip\")}});var d=function(){v(-1)},v=function(e,t){e!==h.start.row&&(h.start.row=h.end.row=e,t||n.session._emit(\"changeBackMarker\"),n._emit(\"changeHoverMarker\"))};n.getHoveredRow=function(){return h.start.row},o.addListener(n.container,\"mouseout\",d),n.on(\"hide\",d),n.on(\"changeSelection\",d),n.session.doc.getLength=function(){return n.data.length},n.session.doc.getLine=function(e){var t=n.data[e];return typeof t==\"string\"?t:t&&t.value||\"\"};var m=n.session.bgTokenizer;return m.$tokenizeRow=function(e){function s(e,n){e&&r.push({type:(t.className||\"\")+(n||\"\"),value:e})}var t=n.data[e],r=[];if(!t)return r;typeof t==\"string\"&&(t={value:t});var i=t.caption||t.value||t.name,o=i.toLowerCase(),u=(n.filterText||\"\").toLowerCase(),a=0,f=0;for(var l=0;l<=u.length;l++)if(l!=f&&(t.matchMask&1<<l||l==u.length)){var c=u.slice(f,l);f=l;var h=o.indexOf(c,a);if(h==-1)continue;s(i.slice(a,h),\"\"),a=h+c.length,s(i.slice(h,a),\"completion-highlight\")}return s(i.slice(a,i.length),\"\"),r.push({type:\"completion-spacer\",value:\" \"}),t.meta&&r.push({type:\"completion-meta\",value:t.meta}),t.message&&r.push({type:\"completion-message\",value:t.message}),r},m.$updateOnChange=r,m.start=r,n.session.$computeWidth=function(){return this.screenWidth=0},n.isOpen=!1,n.isTopdown=!1,n.autoSelect=!0,n.filterText=\"\",n.data=[],n.setData=function(e,t){n.filterText=t||\"\",n.setValue(u.stringRepeat(\"\\n\",e.length),-1),n.data=e||[],n.setRow(0)},n.getData=function(e){return n.data[e]},n.getRow=function(){return p.start.row},n.setRow=function(e){e=Math.max(this.autoSelect?0:-1,Math.min(this.data.length-1,e)),p.start.row!=e&&(n.selection.clearSelection(),p.start.row=p.end.row=e||0,n.session._emit(\"changeBackMarker\"),n.moveCursorTo(e||0,0),n.isOpen&&n._signal(\"select\"))},n.on(\"changeSelection\",function(){n.isOpen&&n.setRow(n.selection.lead.row),n.renderer.scrollCursorIntoView()}),n.hide=function(){this.container.style.display=\"none\",n.anchorPos=null,n.anchor=null,n.isOpen&&(n.isOpen=!1,this._signal(\"hide\"))},n.tryShow=function(e,t,r,s){if(!s&&n.isOpen&&n.anchorPos&&n.anchor&&n.anchorPos.top===e.top&&n.anchorPos.left===e.left&&n.anchor===r)return!0;var o=this.container,u=window.innerHeight,a=window.innerWidth,f=this.renderer,l=f.$maxLines*t*1.4,c={top:0,bottom:0,left:0},h=u-e.top-3*this.$borderSize-t,p=e.top-3*this.$borderSize;r||(p<=h||h>=l?r=\"bottom\":r=\"top\"),r===\"top\"?(c.bottom=e.top-this.$borderSize,c.top=c.bottom-l):r===\"bottom\"&&(c.top=e.top+t+this.$borderSize,c.bottom=c.top+l);var d=c.top>=0&&c.bottom<=u;if(!s&&!d)return!1;d?f.$maxPixelHeight=null:r===\"top\"?f.$maxPixelHeight=p:f.$maxPixelHeight=h,r===\"top\"?(o.style.top=\"\",o.style.bottom=u-c.bottom+\"px\",n.isTopdown=!1):(o.style.top=c.top+\"px\",o.style.bottom=\"\",n.isTopdown=!0),o.style.display=\"\";var v=e.left;return v+o.offsetWidth>a&&(v=a-o.offsetWidth),o.style.left=v+\"px\",o.style.right=\"\",n.isOpen||(n.isOpen=!0,this._signal(\"show\"),i=null),n.anchorPos=e,n.anchor=r,!0},n.show=function(e,t,n){this.tryShow(e,t,n?\"bottom\":undefined,!0)},n.goTo=function(e){var t=this.getRow(),n=this.session.getLength()-1;switch(e){case\"up\":t=t<=0?n:t-1;break;case\"down\":t=t>=n?-1:t+1;break;case\"start\":t=0;break;case\"end\":t=n}this.setRow(t)},n.getTextLeftOffset=function(){return this.$borderSize+this.renderer.$padding+this.$imageSize},n.$imageSize=0,n.$borderSize=1,n}return e}();a.importCssString(\"\\n.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\\n    background-color: #CAD6FA;\\n    z-index: 1;\\n}\\n.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\\n    background-color: #3a674e;\\n}\\n.ace_editor.ace_autocomplete .ace_line-hover {\\n    border: 1px solid #abbffe;\\n    margin-top: -1px;\\n    background: rgba(233,233,253,0.4);\\n    position: absolute;\\n    z-index: 2;\\n}\\n.ace_dark.ace_editor.ace_autocomplete .ace_line-hover {\\n    border: 1px solid rgba(109, 150, 13, 0.8);\\n    background: rgba(58, 103, 78, 0.62);\\n}\\n.ace_completion-meta {\\n    opacity: 0.5;\\n    margin: 0 0.9em;\\n}\\n.ace_completion-message {\\n    color: blue;\\n}\\n.ace_editor.ace_autocomplete .ace_completion-highlight{\\n    color: #2d69c7;\\n}\\n.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{\\n    color: #93ca12;\\n}\\n.ace_editor.ace_autocomplete {\\n    width: 300px;\\n    z-index: 200000;\\n    border: 1px lightgray solid;\\n    position: fixed;\\n    box-shadow: 2px 3px 5px rgba(0,0,0,.2);\\n    line-height: 1.4;\\n    background: #fefefe;\\n    color: #111;\\n}\\n.ace_dark.ace_editor.ace_autocomplete {\\n    border: 1px #484747 solid;\\n    box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);\\n    line-height: 1.4;\\n    background: #25282c;\\n    color: #c1c1c1;\\n}\\n.ace_autocomplete_right .ace_text-layer  {\\n    width: calc(100% - 8px);\\n}\\n.ace_autocomplete_right .ace_line {\\n    display: flex;\\n}\\n.ace_autocomplete_right .ace_completion-spacer {\\n    flex: 1;\\n}\\n\",\"autocompletion.css\",!1),t.AcePopup=h,t.$singleLineEditor=c,t.getAriaId=l}),define(\"ace/autocomplete/inline\",[\"require\",\"exports\",\"module\",\"ace/snippets\"],function(e,t,n){\"use strict\";var r=e(\"../snippets\").snippetManager,i=function(){function e(){this.editor=null}return e.prototype.show=function(e,t,n){n=n||\"\",e&&this.editor&&this.editor!==e&&(this.hide(),this.editor=null);if(!e||!t)return!1;var i=t.snippet?r.getDisplayTextForSnippet(e,t.snippet):t.value;return!i||!i.startsWith(n)?!1:(this.editor=e,i=i.slice(n.length),i===\"\"?e.removeGhostText():e.setGhostText(i),!0)},e.prototype.isOpen=function(){return this.editor?!!this.editor.renderer.$ghostText:!1},e.prototype.hide=function(){return this.editor?(this.editor.removeGhostText(),!0):!1},e.prototype.destroy=function(){this.hide(),this.editor=null},e}();t.AceInline=i}),define(\"ace/autocomplete/util\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.parForEach=function(e,t,n){var r=0,i=e.length;i===0&&n();for(var s=0;s<i;s++)t(e[s],function(e,t){r++,r===i&&n(e,t)})};var r=/[a-zA-Z_0-9\\$\\-\\u00A2-\\u2000\\u2070-\\uFFFF]/;t.retrievePrecedingIdentifier=function(e,t,n){n=n||r;var i=[];for(var s=t-1;s>=0;s--){if(!n.test(e[s]))break;i.push(e[s])}return i.reverse().join(\"\")},t.retrieveFollowingIdentifier=function(e,t,n){n=n||r;var i=[];for(var s=t;s<e.length;s++){if(!n.test(e[s]))break;i.push(e[s])}return i},t.getCompletionPrefix=function(e){var t=e.getCursorPosition(),n=e.session.getLine(t.row),r;return e.completers.forEach(function(e){e.identifierRegexps&&e.identifierRegexps.forEach(function(e){!r&&e&&(r=this.retrievePrecedingIdentifier(n,t.column,e))}.bind(this))}.bind(this)),r||this.retrievePrecedingIdentifier(n,t.column)},t.triggerAutocomplete=function(e){var t=e.getCursorPosition(),n=e.session.getLine(t.row),r=t.column===0?0:t.column-1,i=n[r];return e.completers.some(function(e){if(e.triggerCharacters&&Array.isArray(e.triggerCharacters))return e.triggerCharacters.includes(i)})}}),define(\"ace/autocomplete\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\",\"ace/autocomplete/popup\",\"ace/autocomplete/inline\",\"ace/autocomplete/popup\",\"ace/autocomplete/util\",\"ace/lib/lang\",\"ace/lib/dom\",\"ace/snippets\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"./keyboard/hash_handler\").HashHandler,i=e(\"./autocomplete/popup\").AcePopup,s=e(\"./autocomplete/inline\").AceInline,o=e(\"./autocomplete/popup\").getAriaId,u=e(\"./autocomplete/util\"),a=e(\"./lib/lang\"),f=e(\"./lib/dom\"),l=e(\"./snippets\").snippetManager,c=e(\"./config\"),h=function(e,t){t.completer&&t.completer.destroy()},p=function(){function e(){this.autoInsert=!1,this.autoSelect=!0,this.autoShown=!1,this.exactMatch=!1,this.inlineEnabled=!1,this.keyboardHandler=new r,this.keyboardHandler.bindKeys(this.commands),this.parentNode=null,this.blurListener=this.blurListener.bind(this),this.changeListener=this.changeListener.bind(this),this.mousedownListener=this.mousedownListener.bind(this),this.mousewheelListener=this.mousewheelListener.bind(this),this.changeTimer=a.delayedCall(function(){this.updateCompletions(!0)}.bind(this)),this.tooltipTimer=a.delayedCall(this.updateDocTooltip.bind(this),50)}return e.prototype.$init=function(){return this.popup=new i(this.parentNode||document.body||document.documentElement),this.popup.on(\"click\",function(e){this.insertMatch(),e.stop()}.bind(this)),this.popup.focus=this.editor.focus.bind(this.editor),this.popup.on(\"show\",this.$onPopupChange.bind(this)),this.popup.on(\"hide\",this.$onHidePopup.bind(this)),this.popup.on(\"select\",this.$onPopupChange.bind(this)),this.popup.on(\"changeHoverMarker\",this.tooltipTimer.bind(null,null)),this.popup},e.prototype.$initInline=function(){if(!this.inlineEnabled||this.inlineRenderer)return;return this.inlineRenderer=new s,this.inlineRenderer},e.prototype.getPopup=function(){return this.popup||this.$init()},e.prototype.$onHidePopup=function(){this.inlineRenderer&&this.inlineRenderer.hide(),this.hideDocTooltip()},e.prototype.$onPopupChange=function(e){if(this.inlineRenderer&&this.inlineEnabled){var t=e?null:this.popup.getData(this.popup.getRow()),n=u.getCompletionPrefix(this.editor);this.inlineRenderer.show(this.editor,t,n)||this.inlineRenderer.hide(),this.$updatePopupPosition()}this.tooltipTimer.call(null,null)},e.prototype.$updatePopupPosition=function(){var e=this.editor,t=e.renderer,n=t.layerConfig.lineHeight,r=t.$cursorLayer.getPixelPosition(this.base,!0);r.left-=this.popup.getTextLeftOffset();var i=e.container.getBoundingClientRect();r.top+=i.top-t.layerConfig.offset,r.left+=i.left-e.renderer.scrollLeft,r.left+=t.gutterWidth;var s={top:r.top,left:r.left};t.$ghostText&&t.$ghostTextWidget&&this.base.row===t.$ghostText.position.row&&(s.top+=t.$ghostTextWidget.el.offsetHeight);if(this.popup.tryShow(s,n,\"bottom\"))return;if(this.popup.tryShow(r,n,\"top\"))return;this.popup.show(r,n)},e.prototype.openPopup=function(e,t,n){this.popup||this.$init(),this.inlineEnabled&&!this.inlineRenderer&&this.$initInline(),this.popup.autoSelect=this.autoSelect,this.popup.setData(this.completions.filtered,this.completions.filterText),this.editor.textInput.setAriaOptions&&this.editor.textInput.setAriaOptions({activeDescendant:o(this.popup.getRow()),inline:this.inlineEnabled}),e.keyBinding.addKeyboardHandler(this.keyboardHandler),this.popup.setRow(this.autoSelect?0:-1),n?n&&!t&&this.detach():(this.popup.setTheme(e.getTheme()),this.popup.setFontSize(e.getFontSize()),this.$updatePopupPosition(),this.tooltipNode&&this.updateDocTooltip()),this.changeTimer.cancel()},e.prototype.detach=function(){this.editor&&(this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.off(\"changeSelection\",this.changeListener),this.editor.off(\"blur\",this.blurListener),this.editor.off(\"mousedown\",this.mousedownListener),this.editor.off(\"mousewheel\",this.mousewheelListener)),this.changeTimer.cancel(),this.hideDocTooltip(),this.completionProvider&&this.completionProvider.detach(),this.popup&&this.popup.isOpen&&this.popup.hide(),this.base&&this.base.detach(),this.activated=!1,this.completionProvider=this.completions=this.base=null},e.prototype.changeListener=function(e){var t=this.editor.selection.lead;(t.row!=this.base.row||t.column<this.base.column)&&this.detach(),this.activated?this.changeTimer.schedule():this.detach()},e.prototype.blurListener=function(e){var t=document.activeElement,n=this.editor.textInput.getElement(),r=e.relatedTarget&&this.tooltipNode&&this.tooltipNode.contains(e.relatedTarget),i=this.popup&&this.popup.container;t!=n&&t.parentNode!=i&&!r&&t!=this.tooltipNode&&e.relatedTarget!=n&&this.detach()},e.prototype.mousedownListener=function(e){this.detach()},e.prototype.mousewheelListener=function(e){this.detach()},e.prototype.goTo=function(e){this.popup.goTo(e)},e.prototype.insertMatch=function(e,t){e||(e=this.popup.getData(this.popup.getRow()));if(!e)return!1;if(e.value===\"\")return this.detach();var n=this.completions,r=this.getCompletionProvider().insertMatch(this.editor,e,n.filterText,t);return this.completions==n&&this.detach(),r},e.prototype.showPopup=function(e,t){this.editor&&this.detach(),this.activated=!0,this.editor=e,e.completer!=this&&(e.completer&&e.completer.detach(),e.completer=this),e.on(\"changeSelection\",this.changeListener),e.on(\"blur\",this.blurListener),e.on(\"mousedown\",this.mousedownListener),e.on(\"mousewheel\",this.mousewheelListener),this.updateCompletions(!1,t)},e.prototype.getCompletionProvider=function(){return this.completionProvider||(this.completionProvider=new d),this.completionProvider},e.prototype.gatherCompletions=function(e,t){return this.getCompletionProvider().gatherCompletions(e,t)},e.prototype.updateCompletions=function(e,t){if(e&&this.base&&this.completions){var n=this.editor.getCursorPosition(),r=this.editor.session.getTextRange({start:this.base,end:n});if(r==this.completions.filterText)return;this.completions.setFilter(r);if(!this.completions.filtered.length)return this.detach();if(this.completions.filtered.length==1&&this.completions.filtered[0].value==r&&!this.completions.filtered[0].snippet)return this.detach();this.openPopup(this.editor,r,e);return}if(t&&t.matches){var n=this.editor.getSelectionRange().start;return this.base=this.editor.session.doc.createAnchor(n.row,n.column),this.base.$insertRight=!0,this.completions=new v(t.matches),this.openPopup(this.editor,\"\",e)}var i=this.editor.getSession(),n=this.editor.getCursorPosition(),r=u.getCompletionPrefix(this.editor);this.base=i.doc.createAnchor(n.row,n.column-r.length),this.base.$insertRight=!0;var s={exactMatch:this.exactMatch};this.getCompletionProvider().provideCompletions(this.editor,s,function(t,n,r){var i=n.filtered,s=u.getCompletionPrefix(this.editor);if(r){if(!i.length){var o=!this.autoShown&&this.emptyMessage;typeof o==\"function\"&&(o=this.emptyMessage(s));if(o){var a=[{caption:this.emptyMessage(s),value:\"\"}];this.completions=new v(a),this.openPopup(this.editor,s,e);return}return this.detach()}if(i.length==1&&i[0].value==s&&!i[0].snippet)return this.detach();if(this.autoInsert&&!this.autoShown&&i.length==1)return this.insertMatch(i[0])}this.completions=n,this.openPopup(this.editor,s,e)}.bind(this))},e.prototype.cancelContextMenu=function(){this.editor.$mouseHandler.cancelContextMenu()},e.prototype.updateDocTooltip=function(){var e=this.popup,t=e.data,n=t&&(t[e.getHoveredRow()]||t[e.getRow()]),r=null;if(!n||!this.editor||!this.popup.isOpen)return this.hideDocTooltip();var i=this.editor.completers.length;for(var s=0;s<i;s++){var o=this.editor.completers[s];if(o.getDocTooltip&&n.completerId===o.id){r=o.getDocTooltip(n);break}}!r&&typeof n!=\"string\"&&(r=n),typeof r==\"string\"&&(r={docText:r});if(!r||!r.docHTML&&!r.docText)return this.hideDocTooltip();this.showDocTooltip(r)},e.prototype.showDocTooltip=function(e){this.tooltipNode||(this.tooltipNode=f.createElement(\"div\"),this.tooltipNode.style.margin=0,this.tooltipNode.style.pointerEvents=\"auto\",this.tooltipNode.tabIndex=-1,this.tooltipNode.onblur=this.blurListener.bind(this),this.tooltipNode.onclick=this.onTooltipClick.bind(this),this.tooltipNode.id=\"doc-tooltip\",this.tooltipNode.setAttribute(\"role\",\"tooltip\"));var t=this.editor.renderer.theme;this.tooltipNode.className=\"ace_tooltip ace_doc-tooltip \"+(t.isDark?\"ace_dark \":\"\")+(t.cssClass||\"\");var n=this.tooltipNode;e.docHTML?n.innerHTML=e.docHTML:e.docText&&(n.textContent=e.docText),n.parentNode||this.popup.container.appendChild(this.tooltipNode);var r=this.popup,i=r.container.getBoundingClientRect();n.style.top=r.container.style.top,n.style.bottom=r.container.style.bottom,n.style.display=\"block\",window.innerWidth-i.right<320?i.left<320?r.isTopdown?(n.style.top=i.bottom+\"px\",n.style.left=i.left+\"px\",n.style.right=\"\",n.style.bottom=\"\"):(n.style.top=r.container.offsetTop-n.offsetHeight+\"px\",n.style.left=i.left+\"px\",n.style.right=\"\",n.style.bottom=\"\"):(n.style.right=window.innerWidth-i.left+\"px\",n.style.left=\"\"):(n.style.left=i.right+1+\"px\",n.style.right=\"\")},e.prototype.hideDocTooltip=function(){this.tooltipTimer.cancel();if(!this.tooltipNode)return;var e=this.tooltipNode;!this.editor.isFocused()&&document.activeElement==e&&this.editor.focus(),this.tooltipNode=null,e.parentNode&&e.parentNode.removeChild(e)},e.prototype.onTooltipClick=function(e){var t=e.target;while(t&&t!=this.tooltipNode){if(t.nodeName==\"A\"&&t.href){t.rel=\"noreferrer\",t.target=\"_blank\";break}t=t.parentNode}},e.prototype.destroy=function(){this.detach();if(this.popup){this.popup.destroy();var e=this.popup.container;e&&e.parentNode&&e.parentNode.removeChild(e)}this.editor&&this.editor.completer==this&&(this.editor.off(\"destroy\",h),this.editor.completer=null),this.inlineRenderer=this.popup=this.editor=null},e}();p.prototype.commands={Up:function(e){e.completer.goTo(\"up\")},Down:function(e){e.completer.goTo(\"down\")},\"Ctrl-Up|Ctrl-Home\":function(e){e.completer.goTo(\"start\")},\"Ctrl-Down|Ctrl-End\":function(e){e.completer.goTo(\"end\")},Esc:function(e){e.completer.detach()},Return:function(e){return e.completer.insertMatch()},\"Shift-Return\":function(e){e.completer.insertMatch(null,{deleteSuffix:!0})},Tab:function(e){var t=e.completer.insertMatch();if(!!t||!!e.tabstopManager)return t;e.completer.goTo(\"down\")},PageUp:function(e){e.completer.popup.gotoPageUp()},PageDown:function(e){e.completer.popup.gotoPageDown()}},p.for=function(e){return e.completer instanceof p?e.completer:(e.completer&&(e.completer.destroy(),e.completer=null),c.get(\"sharedPopups\")?(p.$sharedInstance||(p.$sharedInstance=new p),e.completer=p.$sharedInstance):(e.completer=new p,e.once(\"destroy\",h)),e.completer)},p.startCommand={name:\"startAutocomplete\",exec:function(e,t){var n=p.for(e);n.autoInsert=!1,n.autoSelect=!0,n.autoShown=!1,n.showPopup(e,t),n.cancelContextMenu()},bindKey:\"Ctrl-Space|Ctrl-Shift-Space|Alt-Space\"};var d=function(){function e(){this.active=!0}return e.prototype.insertByIndex=function(e,t,n){return!this.completions||!this.completions.filtered?!1:this.insertMatch(e,this.completions.filtered[t],n)},e.prototype.insertMatch=function(e,t,n){if(!t)return!1;e.startOperation({command:{name:\"insertMatch\"}});if(t.completer&&t.completer.insertMatch)t.completer.insertMatch(e,t);else{if(!this.completions)return!1;if(this.completions.filterText){var r;e.selection.getAllRanges?r=e.selection.getAllRanges():r=[e.getSelectionRange()];for(var i=0,s;s=r[i];i++)s.start.column-=this.completions.filterText.length,e.session.remove(s)}t.snippet?l.insertSnippet(e,t.snippet,{range:t.range}):this.$insertString(e,t),t.command&&t.command===\"startAutocomplete\"&&e.execCommand(t.command)}return e.endOperation(),!0},e.prototype.$insertString=function(e,t){var n=t.value||t;if(t.range){if(e.inVirtualSelectionMode)return e.session.replace(t.range,n);e.forEachSelection(function(){var r=e.getSelectionRange();t.range.compareRange(r)===0?e.session.replace(t.range,n):e.insert(n)},null,{keepOrder:!0})}else e.execCommand(\"insertstring\",n)},e.prototype.gatherCompletions=function(e,t){var n=e.getSession(),r=e.getCursorPosition(),i=u.getCompletionPrefix(e),s=[],o=e.completers.length;return e.completers.forEach(function(a,f){a.getCompletions(e,n,r,i,function(n,r){!n&&r&&(s=s.concat(r)),t(null,{prefix:u.getCompletionPrefix(e),matches:s,finished:--o===0})})}),!0},e.prototype.provideCompletions=function(e,t,n){var r=function(e){var r=e.prefix,i=e.matches;this.completions=new v(i),t.exactMatch&&(this.completions.exactMatch=!0),t.ignoreCaption&&(this.completions.ignoreCaption=!0),this.completions.setFilter(r),(e.finished||this.completions.filtered.length)&&n(null,this.completions,e.finished)}.bind(this),i=!0,s=null;this.gatherCompletions(e,function(e,t){if(!this.active)return;e&&(n(e,[],!0),this.detach());var o=t.prefix;if(o.indexOf(t.prefix)!==0)return;if(i){s=t;return}r(t)}.bind(this)),i=!1;if(s){var o=s;s=null,r(o)}},e.prototype.detach=function(){this.active=!1},e}(),v=function(){function e(e,t){this.all=e,this.filtered=e,this.filterText=t||\"\",this.exactMatch=!1,this.ignoreCaption=!1}return e.prototype.setFilter=function(e){if(e.length>this.filterText&&e.lastIndexOf(this.filterText,0)===0)var t=this.filtered;else var t=this.all;this.filterText=e,t=this.filterCompletions(t,this.filterText),t=t.sort(function(e,t){return t.exactMatch-e.exactMatch||t.$score-e.$score||(e.caption||e.value).localeCompare(t.caption||t.value)});var n=null;t=t.filter(function(e){var t=e.snippet||e.caption||e.value;return t===n?!1:(n=t,!0)}),this.filtered=t},e.prototype.filterCompletions=function(e,t){var n=[],r=t.toUpperCase(),i=t.toLowerCase();e:for(var s=0,o;o=e[s];s++){var u=!this.ignoreCaption&&o.caption||o.value||o.snippet;if(!u)continue;var a=-1,f=0,l=0,c,h;if(this.exactMatch){if(t!==u.substr(0,t.length))continue e}else{var p=u.toLowerCase().indexOf(i);if(p>-1)l=p;else for(var d=0;d<t.length;d++){var v=u.indexOf(i[d],a+1),m=u.indexOf(r[d],a+1);c=v>=0?m<0||v<m?v:m:m;if(c<0)continue e;h=c-a-1,h>0&&(a===-1&&(l+=10),l+=h,f|=1<<d),a=c}}o.matchMask=f,o.exactMatch=l?0:1,o.$score=(o.score||0)-l,n.push(o)}return n},e}();t.Autocomplete=p,t.CompletionProvider=d,t.FilteredList=v}),define(\"ace/autocomplete/text_completer\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){function s(e,t){var n=e.getTextRange(r.fromPoints({row:0,column:0},t));return n.split(i).length-1}function o(e,t){var n=s(e,t),r=e.getValue().split(i),o=Object.create(null),u=r[n];return r.forEach(function(e,t){if(!e||e===u)return;var i=Math.abs(n-t),s=r.length-i;o[e]?o[e]=Math.max(s,o[e]):o[e]=s}),o}var r=e(\"../range\").Range,i=/[^a-zA-Z_0-9\\$\\-\\u00C0-\\u1FFF\\u2C00-\\uD7FF\\w]+/;t.getCompletions=function(e,t,n,r,i){var s=o(t,n),u=Object.keys(s);i(null,u.map(function(e){return{caption:e,value:e,score:s[e],meta:\"local\"}}))}}),define(\"ace/ext/language_tools\",[\"require\",\"exports\",\"module\",\"ace/snippets\",\"ace/autocomplete\",\"ace/config\",\"ace/lib/lang\",\"ace/autocomplete/util\",\"ace/autocomplete/text_completer\",\"ace/editor\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../snippets\").snippetManager,i=e(\"../autocomplete\").Autocomplete,s=e(\"../config\"),o=e(\"../lib/lang\"),u=e(\"../autocomplete/util\"),a=e(\"../autocomplete/text_completer\"),f={getCompletions:function(e,t,n,r,i){if(t.$mode.completer)return t.$mode.completer.getCompletions(e,t,n,r,i);var s=e.session.getState(n.row),o=t.$mode.getCompletions(s,t,n,r);o=o.map(function(e){return e.completerId=f.id,e}),i(null,o)},id:\"keywordCompleter\"},l=function(e){var t={};return e.replace(/\\${(\\d+)(:(.*?))?}/g,function(e,n,r,i){return t[n]=i||\"\"}).replace(/\\$(\\d+?)/g,function(e,n){return t[n]})},c={getCompletions:function(e,t,n,i,s){var o=[],u=t.getTokenAt(n.row,n.column);u&&u.type.match(/(tag-name|tag-open|tag-whitespace|attribute-name|attribute-value)\\.xml$/)?o.push(\"html-tag\"):o=r.getActiveScopes(e);var a=r.snippetMap,f=[];o.forEach(function(e){var t=a[e]||[];for(var n=t.length;n--;){var r=t[n],i=r.name||r.tabTrigger;if(!i)continue;f.push({caption:i,snippet:r.content,meta:r.tabTrigger&&!r.name?r.tabTrigger+\"\\u21e5 \":\"snippet\",completerId:c.id})}},this),s(null,f)},getDocTooltip:function(e){e.snippet&&!e.docHTML&&(e.docHTML=[\"<b>\",o.escapeHTML(e.caption),\"</b>\",\"<hr></hr>\",o.escapeHTML(l(e.snippet))].join(\"\"))},id:\"snippetCompleter\"},h=[c,a,f];t.setCompleters=function(e){h.length=0,e&&h.push.apply(h,e)},t.addCompleter=function(e){h.push(e)},t.textCompleter=a,t.keyWordCompleter=f,t.snippetCompleter=c;var p={name:\"expandSnippet\",exec:function(e){return r.expandWithTab(e)},bindKey:\"Tab\"},d=function(e,t){v(t.session.$mode)},v=function(e){typeof e==\"string\"&&(e=s.$modes[e]);if(!e)return;r.files||(r.files={}),m(e.$id,e.snippetFileId),e.modes&&e.modes.forEach(v)},m=function(e,t){if(!t||!e||r.files[e])return;r.files[e]={},s.loadModule(t,function(t){if(!t)return;r.files[e]=t,!t.snippets&&t.snippetText&&(t.snippets=r.parseSnippetFile(t.snippetText)),r.register(t.snippets||[],t.scope),t.includeScopes&&(r.snippetMap[t.scope].includeScopes=t.includeScopes,t.includeScopes.forEach(function(e){v(\"ace/mode/\"+e)}))})},g=function(e){var t=e.editor,n=t.completer&&t.completer.activated;if(e.command.name===\"backspace\")n&&!u.getCompletionPrefix(t)&&t.completer.detach();else if(e.command.name===\"insertstring\"){var r=u.getCompletionPrefix(t),s=u.triggerAutocomplete(t);if((r||s)&&!n){var o=i.for(t);o.autoShown=!0,o.showPopup(t)}}},y=e(\"../editor\").Editor;e(\"../config\").defineOptions(y.prototype,\"editor\",{enableBasicAutocompletion:{set:function(e){e?(this.completers||(this.completers=Array.isArray(e)?e:h),this.commands.addCommand(i.startCommand)):this.commands.removeCommand(i.startCommand)},value:!1},enableLiveAutocompletion:{set:function(e){e?(this.completers||(this.completers=Array.isArray(e)?e:h),this.commands.on(\"afterExec\",g)):this.commands.removeListener(\"afterExec\",g)},value:!1},enableSnippets:{set:function(e){e?(this.commands.addCommand(p),this.on(\"changeMode\",d),d(null,this)):(this.commands.removeCommand(p),this.off(\"changeMode\",d))},value:!1}})});                (function() {\n                    window.require([\"ace/ext/language_tools\"], function(m) {\n                        if (typeof module == \"object\" && typeof exports == \"object\" && module) {\n                            module.exports = m;\n                        }\n                    });\n                })();\n            "
  },
  {
    "path": "web/ace-builds/mode-mocodo.js",
    "content": "define(\"ace/mode/mocodo_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"], function(require, exports, module){\"use strict\";\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar MocodoHighlightRules = function() {\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        start: [{\n            include: \"#indent\"\n        }, {\n            include: \"#comment\"\n        }, {\n            include: \"#phantoms\"\n        }, {\n            include: \"#constraint_clause\"\n        }, {\n            include: \"#inheritance_clause\"\n        }, {\n            include: \"#association_clause\"\n        }, {\n            include: \"#entity_clause\"\n        }, {\n            include: \"#invalid\"\n        }],\n        \"#indent\": [{\n            token: \"text\",\n            regex: /^\\s+/\n        }],\n        \"#comment\": [{\n            token: \"comment.line.magic.mocodo markup.bold\",\n            regex: /%%mocodo\\b.*$/\n        }, {\n            token: \"comment.line.normal.mocodo\",\n            regex: /%.*$/\n        }],\n        \"#phantoms\": [{\n            token: \"punctuation.separator.phantom.mocodo markup.italic\",\n            regex: /:[:\\s]*$/\n        }],\n        \"#association_clause\": [{\n            token: [\n                \"keyword.control.mocodo\",\n                \"entity.other.attribute-name.association.mocodo markup.bold\"\n            ],\n            regex: /((?:\\+|-)?)((?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\])(?=\\s*,\\s*)/,\n            push: [{\n                token: \"association.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#association_legs\"\n            }, {\n                defaultToken: \"association.mocodo\"\n            }]\n        }],\n        \"#association_legs\": [{\n            token: [\n                \"text\",\n                \"keyword.control.card_hidden.mocodo\",\n                \"keyword.control.card_prefix.mocodo\",\n                \"entity.other.attribute-name.cardinality.mocodo\",\n                \"keyword.control.arrow.mocodo\",\n                \"text\",\n                \"invisible.note.mocodo\",\n                \"text\",\n                \"heading.entity.mocodo\",\n                \"text\"\n            ],\n            regex: /(\\s*,\\s*)(?:((?:-)?)((?:[_\\/])?)((?![-_\\/])[\\w?]{2}(?=[\\s]*[^\\w,\\r$:])))?((?:[<>])?)(\\s*)((?:\\[.*?\\])?)(\\s*)((?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\])(\\s*)/\n        }, {\n            include: \"#association_attrs\"\n        }, {\n            include: \"#invalid\"\n        }],\n        \"#association_attrs\": [{\n            token: \"attrs.mocodo\",\n            regex: /\\s*:\\s*/,\n            push: [{\n                token: \"attrs.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#typed_attr\"\n            }, {\n                token: \"punctuation.separator\",\n                regex: /\\s*,\\s*/\n            }, {\n                defaultToken: \"attrs.mocodo\"\n            }]\n        }],\n        \"#typed_attr\": [{\n            token: [\n                \"variable.attribute.mocodo\",\n                \"typed_attribute.mocodo\",\n                \"variable.parameter.datatype.mocodo markup.italic\",\n                \"typed_attribute.mocodo\"\n            ],\n            regex: /((?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s])(\\s*)((?:\\[.*?\\])?)(\\s*)/\n        }],\n        \"#entity_clause\": [{\n            token: [\n                \"keyword.control.mocodo\",\n                \"heading.entity.mocodo markup.bold\",\n                \"entity.mocodo\"\n            ],\n            regex: /((?:\\+|-)?)((?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\])(\\s*:\\s*)/,\n            push: [{\n                token: \"entity.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#entity_first_attr\"\n            }, {\n                defaultToken: \"entity.mocodo\"\n            }]\n        }],\n        \"#entity_first_attr\": [{\n            token: [\n                \"invisible.id_symbols.mocodo\",\n                \"variable.attribute.mocodo\",\n                \"invisible.alt_id_symbols.mocodo\",\n                \"variable.attribute.mocodo markup.underline\",\n                \"text\",\n                \"variable.parameter.datatype.mocodo markup.italic\"\n            ],\n            regex: /(?:((?:\\d*0\\d*_|_))((?:(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]|#(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]))|((?:[1-9]+_)?)((?:(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]|#(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]))|)(\\s*)((?:\\[.*?\\])?)/,\n            push: [{\n                token: \"text\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#entity_next_attrs\"\n            }, {\n                include: \"#invalid\"\n            }]\n        }],\n        \"#entity_next_attrs\": [{\n            token: [\n                \"text\",\n                \"invisible.id_symbols.mocodo\",\n                \"variable.attribute.mocodo markup.underline\",\n                \"invisible.alt_id_symbols.mocodo\",\n                \"variable.attribute.mocodo\",\n                \"text\",\n                \"variable.parameter.datatype.mocodo markup.italic\"\n            ],\n            regex: /(\\s*,\\s*)(?:((?:\\d*0\\d*_|_))((?:(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]|#(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]))|((?:[1-9]+_)?)((?:(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]|#(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]\\s*>\\s*(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]))|)(\\s*)((?:\\[.*?\\])?)/\n        }, {\n            include: \"#invalid\"\n        }],\n        \"#constraint_clause\": [{\n            token: [\n                \"support.function.constraint_name.mocodo markup.bold\",\n                \"constraint.mocodo\",\n                \"invisible.note.mocodo\",\n                \"constraint.mocodo\"\n            ],\n            regex: /(\\([a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF\\d_\\s]{0,3}\\))(\\s*)((?:\\[.*?\\])?)(\\s*)/,\n            push: [{\n                token: \"constraint.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#constraint_targets\"\n            }, {\n                defaultToken: \"constraint.mocodo\"\n            }]\n        }],\n        \"#constraint_targets\": [{\n            token: [\n                \"string.regexp.constraint_leg.mocodo\",\n                \"text\",\n                \"support.type.box.mocodo\"\n            ],\n            regex: /((?:<?(?:\\.+|-+)>?)?)(\\s*)((?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\])/\n        }, {\n            token: \"text\",\n            regex: /\\s*,\\s*/\n        }, {\n            include: \"#constraint_coords\"\n        }, {\n            include: \"#invalid\"\n        }],\n        \"#constraint_coords\": [{\n            token: [\n                \"coords.mocodo\",\n                \"invisible.constraint_coords.mocodo markup.italic\",\n                \"coords.mocodo\",\n                \"invisible.constraint_coords.mocodo markup.italic\"\n            ],\n            regex: /(\\s*:\\s*)((?:-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\]))(\\s*,\\s*)((?:-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\]))$/\n        }],\n        \"#inheritance_clause\": [{\n            token: [\n                \"entity.other.attribute-name.inheritance.mocodo markup.underline markup.bold\",\n                \"inheritance.mocodo\",\n                \"heading.parent.mocodo\",\n                \"inheritance.mocodo\",\n                \"keyword.control.arrow.mocodo\",\n                \"inheritance.mocodo\"\n            ],\n            regex: /(\\/(?:XT\\d?|TX\\d?|X\\d?|T\\d?|\\d?)\\\\{1,2})(\\s*)((?:(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\])?)(\\s*)((?:<==?|<--?|--?>|==?>))(\\s*)/,\n            push: [{\n                token: \"inheritance.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                include: \"#inheritance_children\"\n            }, {\n                defaultToken: \"inheritance.mocodo\"\n            }]\n        }],\n        \"#inheritance_children\": [{\n            token: \"heading.child.mocodo\",\n            regex: /(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF])[^=<>,:\\\\]*[^-\\[\\]\\\\=<>,:\\s\\\\]/\n        }, {\n            token: \"text\",\n            regex: /\\s*,\\s*/\n        }, {\n            include: \"#inheritance_attrs\"\n        }, {\n            include: \"#invalid\"\n        }],\n        \"#inheritance_attrs\": [{\n            token: \"attrs.mocodo\",\n            regex: /\\s*:\\s*/,\n            push: [{\n                token: \"attrs.mocodo\",\n                regex: /$|^/,\n                next: \"pop\"\n            }, {\n                token: \"invisible.inheritance_attribute.mocodo markup.italic\",\n                regex: /(?=[a-zA-Z\\u00C0-\\u024F\\u1E00-\\u1EFF0-9])[^\\[\\]>,]*[^\\[\\]>,\\s]/\n            }, {\n                token: \"text\",\n                regex: /\\s*,\\s*/\n            }, {\n                include: \"#invalid\"\n            }, {\n                defaultToken: \"attrs.mocodo\"\n            }]\n        }],\n        \"#invalid\": [{\n            token: \"invalid.illegal.mocodo\",\n            regex: /.+/\n        }]\n    }\n    \n    this.normalizeRules();\n};\n\nMocodoHighlightRules.metaData = {\n    name: \"Mocodo\",\n    scopeName: \"source.mocodo\"\n}\n\n\noop.inherits(MocodoHighlightRules, TextHighlightRules);\n\nexports.MocodoHighlightRules = MocodoHighlightRules;\n});\n\ndefine(\"ace/mode/mocodo\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/mocodo_highlight_rules\"], function(require, exports, module){\"use strict\";\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar MocodoHighlightRules = require(\"./mocodo_highlight_rules\").MocodoHighlightRules;\nvar Mode = function () {\n    this.HighlightRules = MocodoHighlightRules;\n    this.$behaviour = this.$defaultBehaviour;\n};\noop.inherits(Mode, TextMode);\n(function () {\n    this.lineCommentStart = \"%\";\n    this.$id = \"ace/mode/mocodo\";\n}).call(Mode.prototype);\nexports.Mode = Mode;\n\n});                (function() {\n                    window.require([\"ace/mode/mocodo\"], function(m) {\n                        if (typeof module == \"object\" && typeof exports == \"object\" && module) {\n                            module.exports = m;\n                        }\n                    });\n                })();\n            "
  },
  {
    "path": "web/ace-builds/mode-text.js",
    "content": "\n;                (function() {\n                    window.require([\"ace/mode/text\"], function(m) {\n                        if (typeof module == \"object\" && typeof exports == \"object\" && module) {\n                            module.exports = m;\n                        }\n                    });\n                })();\n            "
  },
  {
    "path": "web/ace-builds/text_highlight_rules.js",
    "content": "\"use strict\";\n\nvar lang = require(\"../lib/lang\");\n\nvar TextHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [{\n            token : \"empty_line\",\n            regex : '^$'\n        }, {\n            defaultToken : \"text\"\n        }]\n    };\n};\n\n(function() {\n\n    this.addRules = function(rules, prefix) {\n        if (!prefix) {\n            for (var key in rules)\n                this.$rules[key] = rules[key];\n            return;\n        }\n        for (var key in rules) {\n            var state = rules[key];\n            for (var i = 0; i < state.length; i++) {\n                var rule = state[i];\n                if (rule.next || rule.onMatch) {\n                    if (typeof rule.next == \"string\") {\n                        if (rule.next.indexOf(prefix) !== 0)\n                            rule.next = prefix + rule.next;\n                    }\n                    if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)\n                        rule.nextState = prefix + rule.nextState;\n                }\n            }\n            this.$rules[prefix + key] = state;\n        }\n    };\n\n    this.getRules = function() {\n        return this.$rules;\n    };\n\n    this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {\n        var embedRules = typeof HighlightRules == \"function\"\n            ? new HighlightRules().getRules()\n            : HighlightRules;\n        if (states) {\n            for (var i = 0; i < states.length; i++)\n                states[i] = prefix + states[i];\n        } else {\n            states = [];\n            for (var key in embedRules)\n                states.push(prefix + key);\n        }\n\n        this.addRules(embedRules, prefix);\n\n        if (escapeRules) {\n            var addRules = Array.prototype[append ? \"push\" : \"unshift\"];\n            for (var i = 0; i < states.length; i++)\n                addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));\n        }\n\n        if (!this.$embeds)\n            this.$embeds = [];\n        this.$embeds.push(prefix);\n    };\n\n    this.getEmbeds = function() {\n        return this.$embeds;\n    };\n\n    var pushState = function(currentState, stack) {\n        if (currentState != \"start\" || stack.length)\n            stack.unshift(this.nextState, currentState);\n        return this.nextState;\n    };\n    var popState = function(currentState, stack) {\n        // if (stack[0] === currentState)\n        stack.shift();\n        return stack.shift() || \"start\";\n    };\n\n    this.normalizeRules = function() {\n        var id = 0;\n        var rules = this.$rules;\n        function processState(key) {\n            var state = rules[key];\n            state.processed = true;\n            for (var i = 0; i < state.length; i++) {\n                var rule = state[i];\n                var toInsert = null;\n                if (Array.isArray(rule)) {\n                    toInsert = rule;\n                    rule = {};\n                }\n                if (!rule.regex && rule.start) {\n                    rule.regex = rule.start;\n                    if (!rule.next)\n                        rule.next = [];\n                    rule.next.push({\n                        defaultToken: rule.token\n                    }, {\n                        token: rule.token + \".end\",\n                        regex: rule.end || rule.start,\n                        next: \"pop\"\n                    });\n                    rule.token = rule.token + \".start\";\n                    rule.push = true;\n                }\n                var next = rule.next || rule.push;\n                if (next && Array.isArray(next)) {\n                    var stateName = rule.stateName;\n                    if (!stateName)  {\n                        stateName = rule.token;\n                        if (typeof stateName != \"string\")\n                            stateName = stateName[0] || \"\";\n                        if (rules[stateName])\n                            stateName += id++;\n                    }\n                    rules[stateName] = next;\n                    rule.next = stateName;\n                    processState(stateName);\n                } else if (next == \"pop\") {\n                    rule.next = popState;\n                }\n\n                if (rule.push) {\n                    rule.nextState = rule.next || rule.push;\n                    rule.next = pushState;\n                    delete rule.push;\n                }\n\n                if (rule.rules) {\n                    for (var r in rule.rules) {\n                        if (rules[r]) {\n                            if (rules[r].push)\n                                rules[r].push.apply(rules[r], rule.rules[r]);\n                        } else {\n                            rules[r] = rule.rules[r];\n                        }\n                    }\n                }\n                var includeName = typeof rule == \"string\" ? rule : rule.include;\n                if (includeName) {\n                    if (includeName === \"$self\")\n                        includeName = \"start\";\n                    if (Array.isArray(includeName))\n                        toInsert = includeName.map(function(x) { return rules[x]; });\n                    else\n                        toInsert = rules[includeName];\n                }\n\n                if (toInsert) {\n                    var args = [i, 1].concat(toInsert);\n                    if (rule.noEscape)\n                        args = args.filter(function(x) {return !x.next;});\n                    state.splice.apply(state, args);\n                    // skip included rules since they are already processed\n                    //i += args.length - 3;\n                    i--;\n                }\n                \n                if (rule.keywordMap) {\n                    rule.token = this.createKeywordMapper(\n                        rule.keywordMap, rule.defaultToken || \"text\", rule.caseInsensitive\n                    );\n                    delete rule.defaultToken;\n                }\n            }\n        }\n        Object.keys(rules).forEach(processState, this);\n    };\n\n    this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {\n        var keywords = Object.create(null);\n        this.$keywordList = [];\n        Object.keys(map).forEach(function(className) {\n            var a = map[className];\n            var list = a.split(splitChar || \"|\");\n            for (var i = list.length; i--; ) {\n                var word = list[i];\n                this.$keywordList.push(word);\n                if (ignoreCase)\n                    word = word.toLowerCase(); \n                keywords[word] = className;\n            }\n        }, this);\n        map = null;\n        return ignoreCase\n            ? function(value) {return keywords[value.toLowerCase()] || defaultToken; }\n            : function(value) {return keywords[value] || defaultToken; };\n    };\n\n    this.getKeywords = function() {\n        return this.$keywords;\n    };\n\n}).call(TextHighlightRules.prototype);\n\nexports.TextHighlightRules = TextHighlightRules;\n"
  },
  {
    "path": "web/ace-builds/theme-chrome.js",
    "content": "define(\"ace/theme/chrome.css\",[\"require\",\"exports\",\"module\"], function(require, exports, module){module.exports = \".ace-chrome .ace_gutter {\\n  background: #ebebeb;\\n  color: #333;\\n  overflow : hidden;\\n}\\n\\n.ace-chrome .ace_print-margin {\\n  width: 1px;\\n  background: #e8e8e8;\\n}\\n\\n.ace-chrome {\\n  background-color: #FFFFFF;\\n  color: black;\\n}\\n\\n.ace-chrome .ace_cursor {\\n  color: black;\\n}\\n\\n.ace-chrome .ace_invisible {\\n  color: rgb(191, 191, 191);\\n}\\n\\n.ace-chrome .ace_constant.ace_buildin {\\n  color: rgb(88, 72, 246);\\n}\\n\\n.ace-chrome .ace_constant.ace_language {\\n  color: rgb(88, 92, 246);\\n}\\n\\n.ace-chrome .ace_constant.ace_library {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-chrome .ace_invalid {\\n  background-color: rgb(153, 0, 0);\\n  color: white;\\n}\\n\\n.ace-chrome .ace_fold {\\n}\\n\\n.ace-chrome .ace_support.ace_function {\\n  color: rgb(60, 76, 114);\\n}\\n\\n.ace-chrome .ace_support.ace_constant {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-chrome .ace_support.ace_type,\\n.ace-chrome .ace_support.ace_class\\n.ace-chrome .ace_support.ace_other {\\n  color: rgb(109, 121, 222);\\n}\\n\\n.ace-chrome .ace_variable.ace_parameter {\\n  font-style:italic;\\n  color:#FD971F;\\n}\\n.ace-chrome .ace_keyword.ace_operator {\\n  color: rgb(104, 118, 135);\\n}\\n\\n.ace-chrome .ace_comment {\\n  color: #236e24;\\n}\\n\\n.ace-chrome .ace_comment.ace_doc {\\n  color: #236e24;\\n}\\n\\n.ace-chrome .ace_comment.ace_doc.ace_tag {\\n  color: #236e24;\\n}\\n\\n.ace-chrome .ace_constant.ace_numeric {\\n  color: rgb(0, 0, 205);\\n}\\n\\n.ace-chrome .ace_variable {\\n  color: rgb(49, 132, 149);\\n}\\n\\n.ace-chrome .ace_xml-pe {\\n  color: rgb(104, 104, 91);\\n}\\n\\n.ace-chrome .ace_entity.ace_name.ace_function {\\n  color: #0000A2;\\n}\\n\\n\\n.ace-chrome .ace_heading {\\n  color: rgb(12, 7, 255);\\n}\\n\\n.ace-chrome .ace_list {\\n  color:rgb(185, 6, 144);\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_selection {\\n  background: rgb(181, 213, 255);\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_step {\\n  background: rgb(252, 255, 0);\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_stack {\\n  background: rgb(164, 229, 101);\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_bracket {\\n  margin: -1px 0 0 -1px;\\n  border: 1px solid rgb(192, 192, 192);\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_active-line {\\n  background: rgba(0, 0, 0, 0.07);\\n}\\n\\n.ace-chrome .ace_gutter-active-line {\\n    background-color : #dcdcdc;\\n}\\n\\n.ace-chrome .ace_marker-layer .ace_selected-word {\\n  background: rgb(250, 250, 255);\\n  border: 1px solid rgb(200, 200, 250);\\n}\\n\\n.ace-chrome .ace_storage,\\n.ace-chrome .ace_keyword,\\n.ace-chrome .ace_meta.ace_tag {\\n  color: rgb(147, 15, 128);\\n}\\n\\n.ace-chrome .ace_string.ace_regex {\\n  color: rgb(255, 0, 0)\\n}\\n\\n.ace-chrome .ace_string {\\n  color: #1A1AA6;\\n}\\n\\n.ace-chrome .ace_entity.ace_other.ace_attribute-name {\\n  color: #994409;\\n}\\n\\n.ace-chrome .ace_indent-guide {\\n  background: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\\\") right repeat-y;\\n}\\n  \\n.ace-chrome .ace_indent-guide-active {\\n  background: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAZSURBVHjaYvj///9/hivKyv8BAAAA//8DACLqBhbvk+/eAAAAAElFTkSuQmCC\\\") right repeat-y;\\n}\\n\";\n\n});\n\ndefine(\"ace/theme/chrome\",[\"require\",\"exports\",\"module\",\"ace/theme/chrome.css\",\"ace/lib/dom\"], function(require, exports, module){exports.isDark = false;\nexports.cssClass = \"ace-chrome\";\nexports.cssText = require(\"./chrome.css\");\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass, false);\n\n});                (function() {\n                    window.require([\"ace/theme/chrome\"], function(m) {\n                        if (typeof module == \"object\" && typeof exports == \"object\" && module) {\n                            module.exports = m;\n                        }\n                    });\n                })();\n            "
  },
  {
    "path": "web/favicons/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<browserconfig>\r\n  <msapplication>\r\n    <tile>\r\n      <square150x150logo src=\"/mstile-150x150.png\"/>\r\n      <TileColor>#ffc40d</TileColor>\r\n    </tile>\r\n  </msapplication>\r\n</browserconfig>\r\n"
  },
  {
    "path": "web/favicons/manifest.json",
    "content": "{\n\t\"name\": \"Mocodo\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"\\/android-chrome-192x192.png\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"\\/android-chrome-512x512.png\",\n\t\t\t\"sizes\": \"512x512\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#fff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "web/flashlight.js",
    "content": "function switchOnFlashlight(event) {\n    document.documentElement.classList.toggle('flashlight');\n    document.addEventListener('mousemove', trackMouse);\n    document.addEventListener('mousedown', switchOffFlashlight);\n    trackMouse(event);\n}\n\nfunction switchOffFlashlight() {\n    document.documentElement.classList.toggle('flashlight');\n    document.removeEventListener('mousemove', trackMouse);\n    document.removeEventListener('mousedown', switchOffFlashlight);\n    document.getElementById('flashlight').checked = false;\n}\n\nfunction trackMouse(event) {\n    document.documentElement.style.setProperty('--cursorXPos', event.clientX + 'px');\n    document.documentElement.style.setProperty('--cursorYPos', event.clientY + 'px');\n}\n"
  },
  {
    "path": "web/generate.php",
    "content": "<?php\nsession_start();\nif (!array_key_exists('text', $_POST)) {\n    exit(\"Need a POST value.\");\n}\n\n// log all $_POST content\n// $php_log = fopen(\"php.log\", 'a') or die('{\"err\": \"PHP: Can\\'t open \\'php.log\\' file.\"}');\n// fwrite($php_log, json_encode($_POST) . \"\\n\");\n\nif (strpos($_SERVER['HTTP_REFERER'], 'localhost')) {\n  $mocodo = \"~/opt/anaconda3/bin/mocodo\";\n  $web_url = \"http://localhost:8898/mocodo/web/\";\n} else {\n  $mocodo = \"~/.local/bin/mocodo\";\n  $web_url = \"https://www.mocodo.net/web/\";\n}\n\n$transformations = array(\n  \"_url.url\" => \"url\",\n  \"_data_dict_2.md\" => \"data_dict:label,type=_Description_\",\n  \"_data_dict_3.md\" => \"data_dict\",\n  \"_mld.html\" => \"html:e\",\n  \"_mld.md\" => \"markdown\",\n  \"_mld.txt\" => \"text\",\n  \"_mld.tex\" => \"latex:b\",\n  \"_mld.mcd\" => \"diagram\",\n  \"_mld_with_constraints.html\" => \"html:ce\",\n  \"_mld_with_constraints.md\" => \"markdown:c\",\n  \"_mld_with_constraints.txt\" => \"text:c\",\n  \"_mld_with_constraints.tex\" => \"latex:bc\",\n  \"_mld_with_constraints.mcd\" => \"diagram:c\",\n  \"_dependencies.gv\" => \"dependencies\",\n  \"_ddl.sql\" => \"sql\",\n  \"_uml.puml\" => \"uml\",\n  \"_ddl.dbml\" => \"dbml\",\n  \"_prompt_for_types.md\" => \"prompt:types\",\n  \"_prompt_for_cards.md\" => \"prompt:cards\",\n);\n\n\n// Prevent the automatic substitution of : by / on Mac OS X (IPV6 syntax)\n$user_path = \"/sessions/\" . str_replace(\":\", \"_\", $_SERVER['REMOTE_ADDR'] . \"-\" . session_id());\n$local_path =  __DIR__ . $user_path;\n// Make a folder for this user\nfile_exists($local_path) or mkdir($local_path) or die('{\"err\": \"PHP: Failed to create user folder.\"}');\nchdir($local_path); \n\n$postId = md5(serialize($_POST));\n\n$title = $_POST['title'];\n\n// Sanitize the title for filesystem safety\n$sanitizedTitle = preg_replace('/[\\/\\\\:*?\"<>|]/', '-', $title); // Replace invalid characters with '-'\n$sanitizedTitle = trim($sanitizedTitle); // Remove leading/trailing spaces\nif (empty($sanitizedTitle) || $sanitizedTitle === '.' || $sanitizedTitle === '..') {\n    $sanitizedTitle = \"MCD\"; // Default title if invalid\n    $title = \"MCD\";\n};\n\n$_POST['input'] = \"{$sanitizedTitle}.mcd\";\n\nif ($_POST['png']) { $mocodo .= \" --svg_to png\"; };\nif ($_POST['pdf']) { $mocodo .= \" --svg_to pdf\"; };\n\n$basthon_source = preg_replace(\"/\\n+$/\", \"\", $_POST['text']);\n\nif ($_POST['state']==\"moved\") {\n    $geo = json_decode(file_get_contents(\"{$title}_geo.json\"),true);\n    $geo['width'] = intval($_POST['width']);\n    $geo['height'] = intval($_POST['height']);\n    foreach ($geo[\"cx\"] as $i => $value) {\n      $geo[\"cx\"][$i] = array($value[0],intval($_POST[\"cx\".$i]));\n      $geo[\"cy\"][$i] = array($value[0],intval($_POST[\"cy\".$i]));\n    };\n    foreach ($geo[\"shift\"] as $i => $value) {\n      $geo[\"shift\"][$i] = array($value[0],floatval($_POST[\"shift\".$i]));\n    };\n    foreach ($geo[\"ratio\"] as $i => $value) {\n      $geo[\"ratio\"][$i] = array($value[0],floatval($_POST[\"ratio\".$i]));\n    };\n    $chan = fopen(\"{$title}_geo.json\", 'w') or die('{\"err\": \"PHP: Can\\'t open geo file.\"}');\n    fwrite($chan, json_encode($geo, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));\n    fclose($chan);\n    $mocodo .= \" --reuse_geo\";\n}\nelse {\n    // Clean the directory up\n    foreach (glob(\"*.*\") as $filename) {\n      unlink($filename);\n    };\n    // Create the MCD text file\n    $chan = fopen($_POST['input'], 'w') or die('{\"err\": \"PHP: Can\\'t open MCD file.\"}');\n    $_POST['text'] = str_replace('\"','',$_POST['text']); # double-check js validation\n    $_POST['text'] = str_replace('`','',$_POST['text']); # double-check js validation\n    $_POST['text'] = str_replace(\"\\\\'\",\"'\",$_POST['text']); # disable http://en.wikipedia.org/wiki/Magic_quotes\n    fwrite($chan, $_POST['text']);\n    fclose($chan);\n\n    // Prepare the contents of the options file\n    unset($_POST['text']);\n    unset($_POST['state']);\n    $_POST['language'] = 'fr';\n    $_POST['encodings'] = array(\"utf8\");\n\n    // Write it\n    $chan = fopen(\"params.json\", 'w') or die('{\"err\": \"PHP: Can\\'t open \\'params.json\\' file.\"}');\n    fwrite($chan, json_encode($_POST));\n    fclose($chan);\n  };\n\n$basthon_options .= \"\";\n\nif ($_POST['conversions']) {\n  $transformation_options = \"\";\n  $conversions = array();\n  foreach ($_POST['conversions'] as $ext) {\n    if ($ext == \"_ddl.sql\") {\n      $transformation_options .= \" \" . escapeshellarg($_POST[\"sql_case\"]) . \":labels\";\n    };\n    if ($_POST['with_constraints']) {\n      $option = $transformations[str_replace(\"_mld\", \"_mld_with_constraints\", $ext)];\n    } else {\n      $option = $transformations[$ext];\n    };\n    $transformation_options .= \" \" . $option;\n    $conversions[] = $ext;\n  };\n  $mocodo .= \" -t{$transformation_options}\";\n  $basthon_options .= \" --select all -t{$transformation_options}\";\n};\n\nif (!isset($_POST[\"knowledge\"]) || !is_array($_POST[\"knowledge\"]) || !in_array(\"assoc_ids\", $_POST[\"knowledge\"])) {\n  $mocodo .= \" --no_assoc_ids\";\n};\n\nif (isset($_POST[\"basthon\"])) {\n  $basthon_options = str_replace(\" html:\", \" md:\", $basthon_options); // patch: since the CSS style is not generated along with the HTML, important features are lost, such as the underlining of primary keys. We use markdown instead.\n  $default_option_values = array(\n    \"shapes\" => \"copperplate\",\n    \"colors\" => \"bw\",\n    \"adjust_width\" => \"1.00\",\n    \"fk_format\" => \"#{label}\",\n    \"strengthen_card\" => \"_1,1_\",\n    \"lib\" => null,\n    \"seed\" => null,\n  );\n  foreach ($default_option_values as $option => $default_value) {\n    if (isset($_POST[$option]) && ($_POST[$option] != $default_value)) {\n      $basthon_options .= \" --{$option}=\" . escapeshellarg($_POST[$option]);\n    };\n  };\n  $basthon_options = substr($basthon_options, 1); // strip the first space\n  if ($_POST[\"detect_overlaps\"] == \"on\") {\n    $basthon_options .= \" --detect_overlaps\";\n  };\n  $result = array(\n    \"options\" => $basthon_options,\n    \"source\" => $basthon_source,\n  );\n  echo json_encode($result);\n  exit();\n};\n\n// Launch the script\n\n$out = array();\n$command_line = \"{$mocodo} 2>&1 >/dev/null\";\nexec($command_line, $out);\n\nif (!empty($out)) {\n    echo json_encode(array(\"err\" => implode(\"\\n\",$out)));\n    exit();\n};\n\n// Use the sanitized title for the ZIP file on the server\n$zipName = $sanitizedTitle . \".zip\";\n\n// Create the ZIP archive\n$zip = new ZipArchive();\nif ($zip->open($zipName, ZIPARCHIVE::CREATE) !== TRUE) {\n    die('{\"err\": \"PHP: Can\\'t open <{$zipName}>\\n\"}');\n}\n\n// Add files to the ZIP archive with error handling\n$filesToAdd = [\n    \"{$sanitizedTitle}_geo.json\",\n    \"{$sanitizedTitle}.mcd\",\n    \"{$sanitizedTitle}.svg\",\n    \"{$sanitizedTitle}_static.svg\", // Optional\n    \"{$sanitizedTitle}.png\", // Optional\n    \"{$sanitizedTitle}.pdf\", // Optional\n];\n\nforeach ($filesToAdd as $file) {\n    if (file_exists($file)) {\n        $zip->addFile($file);\n    }\n}\n\nforeach ($conversions as $ext) {\n    $file = \"{$sanitizedTitle}{$ext}\";\n    if (file_exists($file)) {\n        $zip->addFile($file);\n    }\n}\n\n$zip->close();\n\n// return the response\n$svg = file_get_contents(\"{$sanitizedTitle}.svg\");\n$count = 1;\n\n$result = array(\n    \"svg\" => str_replace('stroke=\"none\" stroke-width=\"0\"', 'stroke=\"#808080\" stroke-width=\"1\" stroke-dasharray=\"2,2\"', $svg, $count),\n    \"geo\" => file_get_contents(\"{$sanitizedTitle}_geo.json\"),\n    \"zipName\" => $zipName,\n    \"zipURL\" => $web_url . $user_path . \"/\" . $zipName,\n    \"conversions\" => array(),\n    \"title\" => $title,\n);\nforeach ($conversions as $ext) {\n    $str = file_get_contents(\"{$sanitizedTitle}{$ext}\");\n    $result[\"conversions\"][] = array($ext, $str);\n};\n// fwrite($php_log, json_encode($result) . \"\\n\");\necho json_encode($result);\n?>\n"
  },
  {
    "path": "web/get_from_lib.php",
    "content": "<?php\n\nsession_start();\n// $php_log = fopen(\"php.log\", 'w') or die(\"can't open file\");\n// fwrite($php_log, \"Log file\\n\");\n// ini_set('display_errors', 1);\n// ini_set('display_startup_errors', 1);\n// error_reporting(E_ALL);\nif (!array_key_exists('title', $_POST)) {\n    exit(\"Need a POST value.\");\n}\n\n// Make a folder for this user\n$path = str_replace(\":\", \"_\", \"sessions/\" . $_SERVER['REMOTE_ADDR'] . \"-\" . session_id()) ; // prevent the automatic substitution of : by / on Mac OS X (IPV6 syntax)\nfile_exists($path) or mkdir($path) or die('{\"err\": \"PHP: Failed to create user folder.\"}');\nchdir($path);\n\n// Double-check js validation\n$title = preg_replace(\"/[^- _a-zA-Z0-9.]/\",\"\",$_POST['title']);\n$title = preg_replace(\"/^ *$/\",\"Sans titre\",$title);\n$title = preg_replace(\"/\\.mcd$/\",\"\",$title);\n\n// Disable SSL verification\nstream_context_set_default([\n\t'ssl' => [\n\t  'verify_peer' => false,\n\t  'verify_peer_name' => false,\n\t],\n  ]);\n\n// Try to get the file from the lib url provided by the user\n$mcd_url = $_POST['lib'] . \"/{$title}.mcd\";\n$contents = file_get_contents($mcd_url) or \"\";\n\n// If the file is not found, try to get it from mocodo.net\nif ($contents == \"\") {\n\t$mcd_url = \"https://mocodo.net/web/lib/{$title}.mcd\";\n\t$contents = file_get_contents($mcd_url) or \"\";\n};\n\necho $contents;\n?>\n"
  },
  {
    "path": "web/js.cookie.js",
    "content": "/*!\n * JavaScript Cookie v2.0.0-pre\n * https://github.com/js-cookie/js-cookie\n *\n * Copyright 2006, 2015 Klaus Hartl\n * Released under the MIT license\n */\n(function (factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(factory);\n\t} else if (typeof exports === 'object') {\n\t\tmodule.exports = factory();\n\t} else {\n\t\tvar _OldCookies = window.Cookies;\n\t\tvar api = window.Cookies = factory(window.jQuery);\n\t\tapi.noConflict = function () {\n\t\t\twindow.Cookies = _OldCookies;\n\t\t\treturn api;\n\t\t};\n\t}\n}(function () {\n\tfunction extend () {\n\t\tvar i = 0;\n\t\tvar result = {};\n\t\tfor (; i < arguments.length; i++) {\n\t\t\tvar attributes = arguments[ i ];\n\t\t\tfor (var key in attributes) {\n\t\t\t\tresult[key] = attributes[key];\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tfunction init (converter) {\n\t\tfunction api (key, value, attributes) {\n\t\t\tvar result;\n\n\t\t\t// Write\n\n\t\t\tif (arguments.length > 1) {\n\t\t\t\tattributes = extend({\n\t\t\t\t\tpath: '/'\n\t\t\t\t}, api.defaults, attributes);\n\n\t\t\t\tif (typeof attributes.expires === 'number') {\n\t\t\t\t\tvar expires = new Date();\n\t\t\t\t\texpires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);\n\t\t\t\t\tattributes.expires = expires;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tresult = JSON.stringify(value);\n\t\t\t\t\tif (/^[\\{\\[]/.test(result)) {\n\t\t\t\t\t\tvalue = result;\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {}\n\n\t\t\t\tvalue = encodeURIComponent(String(value));\n\t\t\t\tvalue = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);\n\n\t\t\t\tkey = encodeURIComponent(String(key));\n\t\t\t\tkey = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);\n\t\t\t\tkey = key.replace(/[\\(\\)]/g, escape);\n\n\t\t\t\treturn (document.cookie = [\n\t\t\t\t\tkey, '=', value,\n\t\t\t\t\tattributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE\n\t\t\t\t\tattributes.path    && '; path=' + attributes.path,\n\t\t\t\t\tattributes.domain  && '; domain=' + attributes.domain,\n\t\t\t\t\tattributes.secure  && '; secure'\n\t\t\t\t].join(''));\n\t\t\t}\n\n\t\t\t// Read\n\n\t\t\tif (!key) {\n\t\t\t\tresult = {};\n\t\t\t}\n\n\t\t\t// To prevent the for loop in the first place assign an empty array\n\t\t\t// in case there are no cookies at all. Also prevents odd result when\n\t\t\t// calling \"get()\"\n\t\t\tvar cookies = document.cookie ? document.cookie.split('; ') : [];\n\t\t\tvar rdecode = /(%[0-9A-Z]{2})+/g;\n\t\t\tvar i = 0;\n\n\t\t\tfor (; i < cookies.length; i++) {\n\t\t\t\tvar parts = cookies[i].split('=');\n\t\t\t\tvar name = parts[0].replace(rdecode, decodeURIComponent);\n\t\t\t\tvar cookie = parts.slice(1).join('=');\n\n\t\t\t\tif (cookie.charAt(0) === '\"') {\n\t\t\t\t\tcookie = cookie.slice(1, -1);\n\t\t\t\t}\n\n\t\t\t\tcookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent);\n\n\t\t\t\tif (this.json) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcookie = JSON.parse(cookie);\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}\n\n\t\t\t\tif (key === name) {\n\t\t\t\t\tresult = cookie;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (!key) {\n\t\t\t\t\tresult[name] = cookie;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tapi.get = api.set = api;\n\t\tapi.getJSON = function () {\n\t\t\treturn api.apply({\n\t\t\t\tjson: true\n\t\t\t}, [].slice.call(arguments));\n\t\t};\n\t\tapi.defaults = {};\n\n\t\tapi.remove = function (key, attributes) {\n\t\t\tapi(key, '', extend(attributes, {\n\t\t\t\texpires: -1\n\t\t\t}));\n\t\t};\n\n\t\tapi.withConverter = init;\n\n\t\treturn api;\n\t}\n\n\treturn init();\n}));\n"
  },
  {
    "path": "web/mocodo.js",
    "content": "/*global $, jQuery*/\n'use strict';\nconst openInNewTab = (href) => {\n  const a = document.createElement(\"a\");\n  a.target = \"_blank\";\n  a.rel = \"noopener noreferrer\";\n  a.href = href;\n  a.style.display = \"none\";\n  document.body.appendChild(a); // Append the link to the document\n  a.click(); // Programmatically click the link\n  document.body.removeChild(a); // Remove the link after clicking\n};\nconst basthon_template = JSON.stringify({\n  cells: [\n    {\n      metadata: { trusted: true },\n      cell_type: \"code\",\n      source: \"from mocodo.magic import mocodo\",\n      execution_count: null,\n      outputs: [],\n    },\n    {\n      metadata: { trusted: true },\n      cell_type: \"code\",\n      source: 'mocodo(\"\"\"\\n%%mocodo {options}\\n{source}\\n\"\"\")',\n      execution_count: null,\n      outputs: [],\n    },\n  ],\n  metadata: {\n    kernelspec: {\n      name: \"python3\",\n      display_name: \"Python 3\",\n      language: \"python\",\n    },\n  },\n  nbformat: 4,\n  nbformat_minor: 2,\n});\nvar request_lock = false;\nvar conversions = {\n  \"_url.url\": {\n    \"default\": true,\n    \"highlighting\": \"none\",\n    \"title\": \"URL d&#39;une session Mocodo online pré-remplie avec le texte-source de votre MCD.\",\n    \"name\": \"Lien de partage du MCD\",\n  },\n  \"_mld.mcd\": {\n    \"default\": false,\n    \"highlighting\": \"none\",\n    \"title\": \"Résultat à réinjecter sous l&#39;onglet Entrée pour tracer un diagramme sagittal des relations.\",\n    \"name\": \"Diagramme relationnel en Mocodo, clés étrangères&nbsp;&nbsp;\",\n  },\n  \"_mld.html\": {\n    \"default\": false,\n    \"highlighting\": \"markup\",\n    \"title\": \"Affiché également au-dessous du diagramme conceptuel. Cliquez sur un schéma de relation pour faire apparaître une explication du passage du MCD au MLD.\",\n    \"name\": \"Schéma relationnel expliqué\",\n  },\n  \"_prompt_for_types.md\": {\n    \"default\": false,\n    \"highlighting\": \"markdown\",\n    \"title\": \"À copier-coller sous l&#39;IA conversationnelle de votre choix pour remplir les types des attributs.\",\n    \"name\": \"Prompt de remplissage des types par IA\",\n    \"advanced\": false,\n  },\n  \"_ddl.sql\": {\n    \"default\": false,\n    \"highlighting\": \"sql\",\n    \"title\": \"DDL œcuménique, pour peu que vous utilisiez les types requis par le dialecte-cible (MySQL, SQLite, PostgreSQL, Oracle, SQL Server, etc.). Les libellés sont automatiquement privés de leurs accents et espaces pour éviter de polluer le code SQL avec des délimiteurs de chaînes, qui plus est non portables.\",\n    \"name\": \"Script SQL de création des tables, libellés en&nbsp;&nbsp;\",\n  },\n  \"_prompt_for_cards.md\": {\n    \"default\": false,\n    \"highlighting\": \"markdown\",\n    \"title\": \"À copier-coller sous l&#39;IA conversationnelle de votre choix pour ajouter les explications qui apparaîtront au survol des cardinalités.\",\n    \"name\": \"Prompt d'explication des cardinalités par IA\",\n    \"advanced\": true,\n  },\n  \"_data_dict_2.md\": {\n    \"default\": false,\n    \"highlighting\": \"markdown\",\n    \"title\": \"Colonnes : attribut / descriptif.\",\n    \"name\": \"Dictionnaire des données sur deux colonnes\",\n    \"advanced\": true,\n  },\n  \"_data_dict_3.md\": {\n    \"default\": false,\n    \"highlighting\": \"markdown\",\n    \"title\": \"Colonnes : entité ou association / attribut / type.\",\n    \"name\": \"Dictionnaire des données sur trois colonnes\",\n    \"advanced\": true,\n  },\n  \"_dependencies.gv\": {\n    \"default\": false,\n    \"highlighting\": \"graphviz\",\n    \"title\": \"Vue simplifiée des contraintes de clés étrangères. Copiez-collez le résultat sur le site donné en lien pour visualiser le diagramme.\",\n    \"name\": \"Graphe des dépendances pour <a href='https://dreampuf.github.io/GraphvizOnline/' target='_blank'>Graphviz</a>\",\n    \"advanced\": true,\n  },\n  \"_mld.txt\": {\n    \"default\": false,\n    \"highlighting\": \"txt\",\n    \"name\": \"Schéma relationnel en texte brut\",\n    \"advanced\": true,\n  },\n  \"_mld.tex\": {\n    \"default\": false,\n    \"highlighting\": \"tex\",\n    \"name\": \"Schéma relationnel en LaTeX\",\n    \"advanced\": true,\n  },\n  \"_mld.md\": {\n    \"default\": false,\n    \"highlighting\": \"markdown\",\n    \"name\": \"Schéma relationnel en Markdown\",\n    \"advanced\": true,\n  },\n  \"_uml.puml\": {\n    \"default\": false,\n    \"highlighting\": \"none\",\n    \"title\": \"Copiez-collez le résultat sur le site donné en lien pour visualiser le diagramme.\",\n    \"name\": \"Diagramme de classes UML pour <a href='https://www.plantuml.com/plantuml/uml' target='_blank'>PlantUML</a>\",\n    \"advanced\": true,\n  },\n  \"_ddl.dbml\": {\n    \"default\": false,\n    \"highlighting\": \"dbml\",\n    \"title\": \"DBML (database markup language) est un langage dédié simple et lisible conçu pour définir des structures de base de données.\",\n    \"name\": \"Définition de la base en <a href='https://dbdiagram.io/' target='_blank'>DBML</a>\",\n    \"advanced\": true,\n  },\n}\nvar knowledge = {\n  \"advanced_tutorial\": {\n    \"name\": \"Tutoriel (2/2)\",\n    \"title\": \"Cochez pour remplacer la première partie du tutoriel par la seconde.\",\n    \"default\": false,\n    \"onchange\": \"setTutorialKnowledge(event.target.checked)\",\n  },\n  \"weak\": {\n    \"name\": \"Entité faible (ou identification relative), cardinalités notées&nbsp;&nbsp;\",\n    \"title\": \"Cochez pour inclure des entités faibles dans les MCD aléatoires et certaines opérations de décomposition. Une entité faible est une entité dont l&#39;identifiant nécessite d&#39;être renforcé par une ou plusieurs entités dont elle dépend fonctionnellement. NB : laisser cette option non cochée ne vous empêchera pas de créer vous-même des entités faibles.\",\n    \"default\": false\n  },\n  \"cluster\": {\n    \"name\": \"Agrégation (ou pseudo-entité) / CIF\",\n    \"title\": \"Cochez pour inclure une agrégation simple dans les MCD aléatoires et pour ajouter au menu « Révéler » une option permettant de la visualiser comme une Contrainte d&#39;intégrité fonctionnelle. Ces notions voisines traitent du cas où une des entités participant à une association est complètement déterminée par la connaissance d&#39;autres entités participantes : une ou plusieurs dans le cas général, toutes sous Mocodo.\",\n    \"default\": false,\n    \"onchange\": \"setClusterKnowledge(event.target.checked)\",\n  },\n  \"constraints\": {\n    \"name\": \"Contraintes d'unicité et d'optionalité\",\n    \"title\": \"Cochez pour faire apparaître dans le schéma relationnel les contraintes d&#39unicité en exposant, d&#39optionalité comme des « ? », et de non-optionalité comme des « ! ». Ces notations sont non standard et peuvent gêner la lecture. NB : quel que soit votre choix, Mocodo ajoute systématiquement les contraintes UNIQUE, NULL ou NOT NULL appropriées dans le code SQL généré.\",\n    \"default\": false\n  },\n  \"assoc_ids\": {\n    \"name\": \"Autoriser les identifiants supplémentaires dans les associations\",\n    \"title\": \"Cochez pour activer cette possibilité, non prévue par Merise, mais qui permet dans certains cas de produire un même schéma relationnel à partir d&#39un schéma conceptuel plus simple.\",\n    \"default\": false\n  },\n  \"reproductibility\": {\n    \"name\": \"Reproductibilité des tirages pseudo-aléatoires\",\n    \"title\": \"Cochez pour que la longueur de la première ligne du texte-source soit prise comme germe du générateur pseudo-aléatoire. Ainsi, les algorithmes randomisés produiront toujours la même sortie sur un même texte-source.\",\n    \"default\": false\n  },\n  \"random\": {\n    \"name\": \"Masquage et génération aléatoire\",\n    \"title\": \"Cochez pour ajouter un bouton donnant accès à des opérations de masquage des libellés et de génération d&#39exercices aléatoires.\",\n    \"default\": false,\n    \"onchange\": \"setRandomKnowledge(event.target.checked)\",\n  },\n  \"decomposition\": {\n    \"name\": \"Décomposition d'associations\",\n    \"title\": \"Cochez pour ajouter un bouton donnant accès à des opérations de réécriture de certains types d&#39;associations.\",\n    \"default\": false,\n    \"onchange\": \"setDecompositionKnowledge(event.target.checked)\",\n  },\n}\nfunction createTabs() {\n  $('ul.tabs').each(function () { // based upon http://www.jacklmoore.com/notes/jquery-tabs\n    $(this).find('a:not(.active)').each(function () {\n      $($(this).attr('href')).hide();\n    });\n    $(this).on('click', 'a', function (e) {\n      var $active = $(this).parent().siblings().children(\".active\");\n      var $content = $($active.attr('href'));\n      $active.removeClass('active');\n      $content.hide();\n      $active = $(this);\n      $content = $($(this).attr('href'));\n      $active.addClass('active');\n      $content.show();\n      e.preventDefault();\n    });\n  });\n}\nfunction activateTab(zone, target) {\n  var $active = $(zone + ' a.active');\n  if (\"#\" + $active.attr(\"id\") === target) { return; }\n  var $content = $($active.attr('href'));\n  $active.removeClass('active');\n  $content.hide();\n  $active = $(target);\n  $content = $($active.attr('href'));\n  $active.addClass('active');\n  $content.show();\n}\nfunction createOptions(id, items, selected, on_demand_index) {\n  $.each(items, function (i, elt) {\n    $(\"#\" + id).append(\"<option\" + (elt === selected ? \" selected='selected'\" : \"\") + \">\" + elt + \"<\\/option>\");\n  });\n}\nfunction createCheckboxes(group, group_name) {\n  var s = '';\n  $.each(group, function (key, value) {\n    s = \"<li>\";\n    s += '<span><input type=\"checkbox\" name=\"' + group_name + '[]\" id=' + key + ' value=\"' + key + '\"';\n    if (value[\"default\"]) { s += \" checked='checked'\" };\n    s += \" onchange='markAsDirty();writeCookie()\"\n    if (value[\"onchange\"]) { s += \";\" + value[\"onchange\"] }\n    s += \"'\\/> <label for='\" + key + \"'\";\n    if (value[\"title\"]) { s += \" title='\" + value[\"title\"] + \"'\" };\n    s += \">\" + value[\"name\"] + \"<\\/label><\\/span><\\/li>\";\n    if (value[\"advanced\"]) {\n      $(\"#\" + group_name).find(\"details\").append(s);\n    } else {\n      if ($(\"#\" + group_name).find(\"details\").length) {\n        $(\"#\" + group_name).find(\"details\").before(s);\n      } else {\n        $(\"#\" + group_name).append(s);\n      }\n    }\n  })\n}\nfunction appendMenuToInput(menuId, inputId) {\n  document.getElementById(inputId).parentNode.appendChild(document.getElementById(menuId));\n}\nfunction refreshSize(geo) {\n  var s = '<div><label>&nbsp;<\\/label> ' +\n    '<input value=\"' + geo.width + '\" type=\"text\" onfocus=\"markAsMoved()\" name=\"width\" id=\"width\" min=\"0\"\\/> ' +\n    '<input value=\"' + geo.height + '\" type=\"text\" onfocus=\"markAsMoved()\" name=\"height\" id=\"height\" min=\"0\"\\/> ' +\n    '<\\/div>';\n  $(\"#size\").html(s);\n}\nfunction refreshCoordinates(geo) {\n  var s = ''\n  $.each(geo[\"cx\"], function (i, item) {\n    var key = item[0]\n    var cx = item[1]\n    var cy = geo[\"cy\"][i][1]\n    s += '<div><label>' + key + '<\\/label> ' +\n      '<input value=\"' + cx + '\" type=\"text\" onfocus=\"markAsMoved()\" name=\"cx' + i + '\" id=\"cx' + i + '\" min=\"0\"\\/> ' +\n      '<input value=\"' + cy + '\" type=\"text\" onfocus=\"markAsMoved()\" name=\"cy' + i + '\" id=\"cy' + i + '\" min=\"0\"\\/> ' +\n      '<\\/div>';\n  })\n  $(\"#coords\").html(s);\n}\nfunction refreshCardinalities(geo) {\n  var s = '';\n  $.each(geo[\"shift\"], function (i, item) {\n    s += '<div><label for=\"shift' + i + '\">' + item[0] + '<\\/label> <input value=\"' + item[1] + '\" type=\"text\"  onfocus=\"markAsMoved()\" name=\"shift' + i + '\" id=\"shift' + i + '\"\\/><\\/div>';\n  });\n  $(\"#cards\").html(s);\n}\nfunction refreshArrows(geo) {\n  var s = '';\n  $.each(geo[\"ratio\"], function (i, item) {\n    s += '<div><label for=\"ratio' + i + '\">' + item[0] + '<\\/label> <input value=\"' + item[1] + '\" type=\"text\"  onfocus=\"markAsMoved()\" name=\"ratio' + i + '\" id=\"ratio' + i + '\"\\/><\\/div>';\n  });\n  $(\"#arrows\").html(s);\n}\nfunction refreshDiagram(result) {\n  var svg = result[\"svg\"];\n  var container = $(\"#diagramOutput\");\n  container.html(svg);\n  var containerWidth = container.width();\n  if (containerWidth) {\n    var svgWidth = container.find(\"svg\").width();\n    if (svgWidth > containerWidth) {\n      var scale = containerWidth / svgWidth;\n      container.find(\"svg\").attr(\"width\", svgWidth * scale);\n      container.find(\"svg\").attr(\"height\", container.find(\"svg\").height() * scale);\n    }\n  }\n  // switch to last page\n  $(\".diagram_page\").each(function() { $(this).attr(\"visibility\", \"visible\"); });\n  $(\".pager_dot\").each(function() { $(this).attr(\"fill\", \"gray\"); });\n}\nfunction refreshConvertOutput(result) {\n  var s = '';\n  var supplement = '';\n  var name = '';\n  var highlighting = '';\n  $.each(result[\"conversions\"], function (i, item) {\n    name = conversions[item[0]][\"name\"].replace(/,.*$/, \"\");\n    highlighting = conversions[item[0]][\"highlighting\"];\n    s += `<fieldset class=\"listing\">`;\n    s += `<legend data-index=${i}>⧉ ${name}</legend>`;\n    s += `<pre><code class=\"language-${highlighting}\" id=\"code-${i}\">`\n    s += item[1];\n    s += `</code></pre></fieldset>`;\n    if (item[0] == \"_mld.html\") {\n      supplement = item[1].replace(new RegExp(\"&lt;\", \"g\"), \"<\")\n    };\n  })\n  $(\"#convertOutput\").html(s);\n  $(\"#diagramOutputSupplement\").html(supplement);\n  var legends = document.getElementsByTagName(\"legend\");\n  for (var i = 0; i < legends.length; i++) {\n    legends[i].addEventListener(\"click\", function (event) {\n      var index = event.target.dataset.index;\n      var code = document.getElementById(`code-${index}`);\n      navigator.clipboard.writeText(code.innerText + \"\\n\");\n      $(`#code-${index}`).highlight();\n    })\n  }\n}\n// stolen from https://stackoverflow.com/a/11589350/173003\n$.fn.highlight = function () {\n  $(this).each(function () {\n    var el = $(this);\n    el.before(\"<div/>\")\n    el.prev()\n      .width(el.width())\n      .height(el.height())\n      .css({\n        \"position\": \"absolute\",\n        \"backgroundColor\": \"#0000ff\",\n        \"opacity\": \".1\"\n      })\n      .fadeOut(500);\n  });\n};\nfunction sendToBasthon() {\n  var text = ace.edit(\"editor\").getSession().getValue();\n  $('textarea[name=\"text\"]').val(text);\n  var data = $(\"#mainForm\").serializeArray();\n  data.push({ name: \"basthon\", value: true });\n  if ($(\"#reproductibility\").prop(\"checked\")) {\n    data.push({ name: \"seed\", value: text.indexOf(\"\\n\") });\n  };\n  if ($(\"#constraints\").prop(\"checked\")) {\n    data.push({ name: \"with_constraints\", value: true })\n  };\n  $.ajax({\n    type: \"POST\",\n    url: \"web/generate.php\",\n    data: $.param(data),\n    success: function (result) {\n      result = $.parseJSON(result);\n      let ipynb = basthon_template;\n      // if the source consists in only blank characters, replace %%mocodo by %mocodo\n      if (/^\\s*$/.test(result[\"source\"])) {\n        ipynb = ipynb.replace(\"%%mocodo\", \"%mocodo\");\n      }\n      ipynb = ipynb.replace(\"{options}\", result[\"options\"]);\n      ipynb = ipynb.replace(\"{source}\", result[\"source\"].replaceAll(\"\\r\", \"\").replaceAll(\"\\n\", \"\\\\n\"));\n      ipynb = encodeURIComponent(ipynb);\n      const url = new URL(\"https://notebook.basthon.fr\");\n      url.searchParams.set(\"ipynb\", ipynb);\n      openInNewTab(url.href);\n    },\n  });\n};\nfunction generate() {\n  if (request_lock) return;\n  request_lock = true;\n  $(\"#refreshButton\").hide();\n  $(\"#rotatingButton\").show();\n  var text = ace.edit(\"editor\").getSession().getValue();\n  $('textarea[name=\"text\"]').val(text);\n  var data = $(\"#mainForm\").serializeArray();\n  if ($(\"#reproductibility\").prop(\"checked\")) {\n    data.push({ name: \"seed\", value: text.indexOf(\"\\n\") });\n  };\n  if ($(\"#constraints\").prop(\"checked\")) {\n    data.push({ name: \"with_constraints\", value: true })\n  };\n  $.ajax({\n    type: \"POST\",\n    url: \"web/generate.php\",\n    data: $.param(data),\n    success: function (result) {\n      result = $.parseJSON(result);\n      if (result.hasOwnProperty(\"err\")) {\n        var error_message = result[\"err\"].replace(\"<\", \"&lt;\")\n        $(\"#errorOutput\").html(\"<pre>\" + error_message + \"</pre>\");\n        $(\"#errorTab\").css(\"display\", \"inline\");\n        return;\n      }\n      var geo = $.parseJSON(result[\"geo\"]);\n      refreshSize(geo);\n      refreshCoordinates(geo);\n      refreshCardinalities(geo);\n      refreshArrows(geo);\n      $(\"#diagramOutput\").removeClass('never_refreshed');\n      $(\"#convertOutput\").removeClass('never_refreshed');\n      refreshDiagram(result);\n      refreshConvertOutput(result);\n      $(\"#title\").val(result[\"title\"]);\n      $(\"#downloadButton\").attr(\"href\", result[\"zipURL\"]);\n      $(\"#downloadButton\").attr(\"download\", result[\"zipName\"]);\n      if ($(\"#errorTab\").hasClass('active')) {\n        activateTab(\"#outputZone\", \"#diagramTab\");\n      }\n      $(\"#errorTab\").fadeOut();\n      markAsReady();\n      // suppress the sessions older than 24 hours\n      $.ajax({\n        type: \"POST\",\n        url: \"web/purge.php\",\n        data: {}\n      });\n    },\n    complete: function (data) {\n      $(\"#refreshButton\").show();\n      $(\"#rotatingButton\").hide();\n      request_lock = false;\n    }\n  });\n};\nfunction rewrite(args) {\n    if (request_lock) return;\n    request_lock = true;\n    $(\"#rotatingButton\").show();\n    $(\"#refreshButton\").hide();\n    $(\"#downloadButton\").hide();\n    $(\"#editor\").addClass(\"flash\");\n    if (args.includes(\"arrange\")) {\n      args = args.replace(\"arrange,\", \"arrange:\");\n    }\n    if (args.includes(\"explode\")) {\n      args = $(\"#weak\").prop(\"checked\") ? args.replace(\":\", \":weak,\") : args.replace(\"weak,\", \"\");\n    };\n    if (args.includes(\"grow\")) {\n      args = $(\"#weak\").prop(\"checked\") ? args.replace(\":\", \":_11-*N=1,\") : args.replace(\"_11-*N=1,\", \"\");\n      args = $(\"#cluster\").prop(\"checked\") ? args.replace(\":\", \":/*N-*N=1,\") : args.replace(\"/*N-*N=1,\", \"\");\n    };\n    var text = ace.edit(\"editor\").getSession().getValue();\n    $('textarea[name=\"text\"]').val(text);\n    if ($(\"#reproductibility\").prop(\"checked\")) {\n      args += \" --seed=\" + text.indexOf(\"\\n\");\n    }\n    return $.ajax({\n      type: \"POST\",\n      url: \"web/rewrite.php\",\n      data: {\n        args: args,\n        text: text\n      },\n      success: function (result) {\n        result = $.parseJSON(result);\n        if (result.hasOwnProperty(\"err\")) {\n          var error_message = result[\"err\"].replace(\"<\", \"&lt;\")\n          $(\"#errorOutput\").html(\"<pre>\" + error_message + \"</pre>\");\n          $(\"#errorTab\").css(\"display\", \"inline\");\n          return;\n        }\n        setEditorContent(result[\"text\"]);\n        request_lock = false;\n        generate();\n      },\n      complete: function (data) {\n        $(\"#refreshButton\").show();\n        $(\"#rotatingButton\").hide();\n        $(\"#editor\").removeClass(\"flash\");\n        request_lock = false;\n      }\n    });\n  };\nfunction get_from_lib() {\n  if (request_lock) return;\n  request_lock = true\n  $.ajax({\n    type: \"POST\",\n    url: \"web/get_from_lib.php\",\n    data: {\n      title: $(\"#title\").val(),\n      lib: $(\"#lib\").val(),\n    },\n    success: function (result) {\n      if (result) {\n        setEditorContent(result);\n        request_lock = false;\n        generate();\n      }\n  },\n    complete: function (data) {\n      request_lock = false;\n    }\n  });\n};\nfunction setPulsatingButton(is_visible, checkbox, button) {\n  if (is_visible) {\n    button.show().css(\"opacity\", \"1\");\n    checkbox.off(\"mouseenter\");\n    checkbox.off(\"mouseleave\");\n    button.removeClass(\"pulsating\");\n   } else {\n    button.hide();\n    button.addClass(\"pulsating\");\n    checkbox.on(\"mouseenter\", function () { button.show(); });\n    checkbox.on(\"mouseleave\", function () { button.hide(); });\n   }\n};\nfunction setDecompositionKnowledge(is_visible) {\n  setPulsatingButton(is_visible, $(\"#decomposition\").parent(), $(\"#explodeButton\"));\n};\nfunction setRandomKnowledge(is_visible) {\n  setPulsatingButton(is_visible, $(\"#random\").parent(), $(\"#jokerButton\"));\n};\nfunction setClusterKnowledge(is_visible) {\n  is_visible ? $(\"#createCifs\").show() : $(\"#createCifs\").hide();\n};\nfunction setButtonPreviewOnHover(checkboxId, buttonId) {\n  $('label[for=\"' + checkboxId + '\"]').hover(function() {\n    if ($(\"#\" + checkboxId).prop(\"checked\", false)) {\n      $('#' + buttonId).fadeTo(500, 0.5);\n    }\n  }, function() {\n    if ($(\"#\" + checkboxId).prop(\"checked\", false)) {\n      $('#' + buttonId).hide();\n    }\n  });\n}\nvar tutorialOptions = [\"Tutoriel interactif (1/2)\", \"Entité\", \"Identifiant et attributs d'entité\", \"Identifiant composite\", \"Association\", \"Cardinalités\", \"Attribut d'association\", \"Association de dépendance fonctionnelle\", \"Association réflexive\", \"Schéma relationnel\", \"Rôles\", \"Diagramme relationnel (1)\", \"Diagramme relationnel (2)\", \"Inférence de types\", \"Génération du DDL\", \"Schéma sur plusieurs rangées\", \"Réarrangement automatique\", \"Réarrangement automatique avec contraintes\", \"Entraînement au passage au relationnel\", \"Pour aller plus loin...\", \"Tutoriel interactif (2/2)\", \"Entité faible (ou identification relative)\", \"Entité faible sans identifiant\", \"Identifiants candidats\", \"Héritage (ou spécialisation)\", \"Agrégation (ou pseudo-entité)\", \"Agrégation et contraintes d'unicité\", \"Agrégation multiple\", \"Contrainte d'intégrité fonctionnelle (CIF)\", \"Autres contraintes sur associations\", \"Explication interactive d'une contrainte\", \"Explication interactive des cardinalités\", \"Flèche sur une patte\", \"Dévoilement progressif du schéma\", \"Boîtes homonymes\", \"Vue en extension\", \"Décomposition des associations ternaires (1)\", \"Décomposition des associations ternaires (2)\", \"Pour aller plus loin...\"];\nvar basicTutorialLimit = 20;\nfunction setTutorialKnowledge(is_advanced) {\n  $(\"#tutorial\").empty();\n  if (is_advanced) {\n    createOptions(\"tutorial\", tutorialOptions.slice(basicTutorialLimit))\n  } else {\n    createOptions(\"tutorial\", tutorialOptions.slice(0, basicTutorialLimit));\n  }\n}\n\nfunction setEditorContent(text) {\n  var editor = ace.edit(\"editor\");\n  editor.session.off('change', markAsDirty);\n  editor.setValue(text + (text.slice(-1) == \"\\n\" ? \"\" : \"\\n\"));\n  editor.session.on('change', markAsDirty);\n  editor.selection.moveCursorFileStart();\n};\nfunction markAsDirty() {\n  $(\"#geoTab\").fadeOut();\n  $(\"#downloadButton\").fadeOut();\n  $(\"#state\").val(\"dirty\");\n};\nfunction changeTitleToNthTuto() {\n  var index = $(\"select[id='tutorial'] option:selected\").index();\n  if ($(\"#advanced_tutorial\").prop(\"checked\")) {\n    index += basicTutorialLimit;\n  }\n  $(\"#title\").val(\"tuto-\" + (\"000\" + index).slice(-4));\n}\nfunction markAsMoved() {\n  $(\"#state\").val(\"moved\");\n};\nfunction markAsReady() {\n  $(\"#geoTab\").css(\"display\", \"inline\");\n  $('#downloadButton').css('display', 'inline-block');\n  $(\"#state\").val(\"ready\");\n};\nfunction onBlur(elt) {\n  if (/^ *$/i.test(elt.value)) {\n    elt.value = elt.defaultValue;\n  }\n}\nfunction onFocus(elt) {\n  if (elt.value == elt.defaultValue) {\n    elt.value = '';\n  }\n}\nfunction writeCookie() {\n  Cookies.set('mocodo-options', JSON.stringify($(\"#paramContents\").find(\":input\").serializeArray()), { expires: 365 });\n}\nfunction readCookie() {\n  var options = Cookies.get('mocodo-options');\n  if (options) {\n    var objects = $.parseJSON(options);\n    $(\"#paramContents\").find(\":checkbox:checked\").removeAttr(\"checked\")\n    $(\"#svg\").prop(\"checked\", true);\n    $.each(objects, function (index, object) {\n      var elt = $('[name=\"' + object.name + '\"]');\n      if (!elt[0]) { return };\n      switch (elt[0].type) {\n        case 'checkbox':\n          elt.each(function () {\n            if ($(this).attr('value') == object.value) {\n              $(this).attr(\"checked\", \"checked\");\n            };\n          });\n          break;\n        default:\n          elt.val(object.value);\n      }\n    });\n  }\n}\n\nvar clickTimer = null;\nvar currentPopup = null;\n\nfunction handleClick(element, rewrite_operation) {\n  if (clickTimer != null) { // a double-click: call the default rewriting and close the popup menu if needed.\n    if (currentPopup) {\n      currentPopup.style.display = \"none\";\n      currentPopup = null;\n    };\n    clearTimeout(clickTimer);\n    clickTimer = null;\n    rewrite(rewrite_operation);\n  } else { // may be a simple click: if eventually so, switch the popup menu visibility.\n    clickTimer = setTimeout(function () {\n      clickTimer = null;\n      if (currentPopup) {\n        currentPopup.style.display = \"none\";\n        currentPopup = null;\n      } else {\n        currentPopup = element.nextElementSibling;\n        currentPopup.style.display = \"block\";\n      }\n    }, 350);\n  }\n}\nfunction closePopup() {\n  if (currentPopup) {\n    currentPopup.style.display = \"none\";\n  };\n  currentPopup = null;\n}\n$(document).keypress(function (e) {\n  if (e.which == 13 && e.target.nodeName != \"TEXTAREA\") {\n    return false\n  };\n});\nfunction make_editor_react_on_change(flag) {\n  var editor = ace.edit(\"editor\");\n  if (flag) {\n    editor.session.on('change', markAsDirty);\n  } else {\n    editor.session.off('change', markAsDirty);\n  }\n}\n$().ready(function () {\n  createTabs();\n\tvar editor = ace.edit(\"editor\");\n  // if the hidden text area named \"text\" is not empty, use its content as the never_refreshed value of the editor\n  var text = $('textarea[name=\"text\"]').val();\n  if (text) {\n    editor.setValue(text);\n    editor.selection.moveCursorFileStart();\n  }\n  else {\n    // if it is launched from localhost, use the local pristine sandbox\n    if (location.hostname == \"localhost\") {\n      var pristine_sandbox = \"/mocodo/mocodo/resources/pristine_sandbox.mcd\";\n    }\n    else {\n      var pristine_sandbox = \"/resources/pristine_sandbox.mcd\";\n    }\n    $.get(location.protocol + '//' + location.host + pristine_sandbox, function (data) {\n      editor.setValue(data);\n      editor.selection.moveCursorFileStart();\n    });\n  };\n  editor.session.on('change', markAsDirty);\n  editor.session.setMode(\"ace/mode/mocodo\");\n  editor.setTheme(\"ace/theme/chrome\");\n\teditor.setOptions({\n    enableAutoIndent: false,\n    showPrintMargin: false,\n    showGutter: false,\n    enableLiveAutocompletion: true,\n\t});\n  editor.renderer.updateFull();\n  var default_color = \"brewer\" + \"+-\"[Math.floor(Math.random() * 2)] + (Math.floor(Math.random() * 9) + 1);\n  createOptions(\"colors\", [\"blank\", \"bw\", \"bw-alpha\", \"desert\", \"dark\", \"dark-desert\", \"dark-ocean\", \"dark-pond\", \"keepsake\", \"mondrian\", \"ocean\", \"pond\", \"wb\", \"xinnian\", \"brewer+1\", \"brewer-1\", \"brewer+2\", \"brewer-2\", \"brewer+3\", \"brewer-3\", \"brewer+4\", \"brewer-4\", \"brewer+5\", \"brewer-5\", \"brewer+6\", \"brewer-6\", \"brewer+7\", \"brewer-7\", \"brewer+8\", \"brewer-8\", \"brewer+9\", \"brewer-9\"], default_color);\n  createOptions(\"shapes\", [\"arial\", \"copperplate\", \"georgia\", \"mondrian\", \"sans\", \"serif\", \"times\", \"trebuchet\", \"verdana\", \"xinnian\"], \"verdana\");\n  createCheckboxes(conversions, \"conversions\");\n  createCheckboxes(knowledge, \"knowledge\");\n  appendMenuToInput(\"sql_case\", \"_ddl.sql\");\n  appendMenuToInput(\"fk_format\", \"_mld.mcd\");\n  appendMenuToInput(\"strengthen_card\", \"weak\");\n  readCookie();\n  setTutorialKnowledge($(\"#advanced_tutorial\").prop(\"checked\"))\n  setDecompositionKnowledge($(\"#decomposition\").prop(\"checked\"));\n  setRandomKnowledge($(\"#random\").prop(\"checked\"));\n  setClusterKnowledge($(\"#cluster\").prop(\"checked\"));\n  $(\"#basic\").prop(\"checked\", true);\n  $(\"#basic\").prop(\"disabled\", true);\n});\n"
  },
  {
    "path": "web/purge.php",
    "content": "<?php\n// Remove the old sessions' subdirectories\n$session_dir = __DIR__ . \"/sessions\";\nif (file_exists($session_dir)) {\n  $files = glob(\"{$session_dir}/*\");\n  foreach ($files as $file) {\n    if (is_dir($file) && (time() - filemtime($file) > 24*60*60)) {\n      $files2 = glob(\"{$file}/*\");\n      foreach ($files2 as $file2) {\n        if (is_file($file2)) {\n          unlink($file2);\n        };\n      };\n      rmdir($file);\n    };\n  };\n};\n?>\n"
  },
  {
    "path": "web/reset.css",
    "content": "/* http://meyerweb.com/eric/tools/css/reset/ \n   v2.0 | 20110126\n   License: none (public domain)\n*/\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed, \nfigure, figcaption, footer, header, hgroup, \nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfont-size: 100%;\n\tfont: inherit;\n\tvertical-align: baseline;\n}\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure, \nfooter, header, hgroup, menu, nav, section {\n\tdisplay: block;\n}\nbody {\n\tline-height: 1;\n}\nol, ul {\n\tlist-style: none;\n}\nblockquote, q {\n\tquotes: none;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n\tcontent: '';\n\tcontent: none;\n}\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}"
  },
  {
    "path": "web/rewrite.php",
    "content": "<?php\nsession_start();\n\n// $php_log = fopen(\"php.log\", 'w') or die(\"can't open file\");\n\nif (!array_key_exists('text', $_POST)) {\n    exit(\"Need a POST value.\");\n}\n\n// Make a folder for this user\n$path = str_replace(\":\", \"_\", \"sessions/\" . $_SERVER['REMOTE_ADDR'] . \"-\" . session_id()) ; // prevent the automatic substitution of : by / on Mac OS X (IPV6 syntax)\nfile_exists($path) or mkdir($path) or die('{\"err\": \"PHP: Failed to create user folder.\"}');\nchdir($path);\n\n// Create the MCD text file\n$title = preg_replace(\"/[^- _a-zA-Z0-9.]/\",\"\",$_POST['title']); # double-check js validation\n$title = preg_replace(\"/^ *$/\",\"Sans titre\",$title); # double-check js validation\n$_POST['input'] = \"{$title}.mcd\";\n$chan = fopen($_POST['input'], 'w') or die('{\"err\": \"PHP: Can\\'t open MCD file.\"}');\n$_POST['text'] = str_replace('\"','',$_POST['text']); # double-check js validation\n$_POST['text'] = str_replace('`','',$_POST['text']); # double-check js validation\n$_POST['text'] = str_replace(\"\\\\'\",\"'\",$_POST['text']); # disable http://en.wikipedia.org/wiki/Magic_quotes\nfwrite($chan, $_POST['text']);\nfclose($chan);\n\n// Prepare the contents of the options file\nunset($_POST['text']);\nunset($_POST['state']);\n$_POST['language'] = 'fr';\n$_POST['encodings'] = array(\"utf8\");\n$_POST['title'] = $title;\n\n// Write it\n$chan = fopen(\"params.json\", 'w') or die('{\"err\": \"PHP: Can\\'t open \\'params.json\\' file.\"}');\nfwrite($chan, json_encode($_POST));\nfclose($chan);\n\n// Launch the script\n\nif (strpos($_SERVER['HTTP_REFERER'], 'localhost')) {\n    $mocodo = \"~/opt/anaconda3/bin/mocodo\";\n  } else {\n    $mocodo = \"~/.local/bin/mocodo\";\n};\n$command_line = \"{$mocodo} -t \" . escapeshellcmd($_POST['args']) . \" 2>&1\";\n\n// Execute the command and test the exit code.\n// If it is not 0, return an array with a key \"err\" and the error message.\n\n$out = array();\nexec($command_line, $out, $exitCode);\nif ($exitCode) {\n    echo json_encode(array(\"err\" => implode(\"\\n\", $out)));\n    exit();\n}\n\n// Otherwise, retrieve the updated input file and return it\n// in an array with a key \"text\".\n\n$chan = fopen($_POST['input'], 'r') or die('{\"err\": \"PHP: Can\\'t open MCD file.\"}');\n$contents = fread($chan, filesize($_POST['input']));\n\necho json_encode(array(\"text\" => $contents));\n\n?>"
  },
  {
    "path": "web/style.css",
    "content": "* {\n  margin: 0;\n  padding: 0;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n#wrap {\n  width:1024px;\n  margin:0 auto;\n  background:#fff;\n  -webkit-box-shadow: 0px 0px 10px 0px gray;\n  box-shadow: 0px 0px 10px 0px gray;\n  display:block;\n\tpadding-bottom:45px;\n}\n\n#banner{\n  text-align:center;\n  padding-top:45px;\n}\n#motto {\n  text-align: center;\n  letter-spacing: 4px;\n  font-size: 14px;\n  font-family: \"Helvetica Neue\", \"Helvetica\", \"Liberation Sans\", Arial, sans-serif;\n  color: #666;\n  margin-top: 10px;\n  margin-bottom: 45px;\n}\n#navigation {\n\tfont-size: 15px;\n  font-weight: 200;\n  text-align:center;\n  color:#666;\n  clear: both;\n  position: relative;\n  z-index: 10;\n  padding: 15px 0 15px 0;\n}\n#navigation a:hover {\n  color:black;\n}\n\na {\n  text-decoration:none;\n  color:#666;\n}\nhtml {\n\toverflow-y:scroll;\n}\nhtml, body {\n  height:100%;\n\tline-height:150%;\n\tfont-family: \"Helvetica Neue\", \"Helvetica\", \"Liberation Sans\", Arial, sans-serif;\n  background-attachment: fixed !important;\n  background: #f8f8f8; /* Old browsers */\n  background: -moz-linear-gradient(top,  #f8f8f8 52%, #cccccc 100%); /* FF3.6+ */\n  background: -webkit-gradient(linear, left top, left bottom, color-stop(52%,#f8f8f8), color-stop(100%,#cccccc)); /* Chrome,Safari4+ */\n  background: -webkit-linear-gradient(top,  #f8f8f8 52%,#cccccc 100%); /* Chrome10+,Safari5.1+ */\n  background: -o-linear-gradient(top,  #f8f8f8 52%,#cccccc 100%); /* Opera 11.10+ */\n  background: -ms-linear-gradient(top,  #f8f8f8 52%,#cccccc 100%); /* IE10+ */\n  background: linear-gradient(to bottom,  #f8f8f8 52%,#cccccc 100%); /* W3C */\n/*  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f8f8f8', endColorstr='#ccccccc',GradientType=0 ); IE6-9 */\n}\n\n\nform input[type=\"text\"] {\n  padding:3px;\n  width:3em;\n  text-align:right;\n}\n\n.contents {\n  position:relative;\n  margin-left: 80px;\n\tmargin-right: 80px;\n\toverflow-x: auto;\n  max-width:900px;\n  clear:both;\n  margin-bottom:30px;\n\tmargin-top:-30px;\n}\n#title {\n  padding-left:10px;\n\tfont-size:11pt;\n}\n#inputContents input {\n  color:#666;\n  text-align:left;\n\twidth:864px;\n\theight:31px;\n\tborder: 1px solid #ccc;\n  border-bottom:0px;\n\tbackground:#f8f8f8;\n}\n#inputPane {\n    overflow-x: hidden;\n}\n#inputContents input:hover {\n  color:black;\n}\n#editor-wrapper {\n  border: 1px solid #bbb;\n  padding: 8px 0px 0px 5px;\n}\n\n#editor {\n\tfont-size:12pt;\n  font-family: 'Menlo', 'Monaco', 'Andale mono', 'Source Code Pro', monospace;\n  max-width:100%;\n  min-width:100%;\n  min-height:100px;\n  height:350px;\n\tposition:relative;\n  resize: vertical;\n}\n#editor.flash {\n  background-color:#ededed;\n}\n#inputZone, #outputZone {\n  background:#fff;\n  overflow:auto;\n  border:0px;\n}\nform #geoContents label {\n  color:#222;\n  float: left;\n  width: 325px;\n  text-align: right;\n  margin-right: 0.5em;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  -o-text-overflow: ellipsis;\n}\n#paramContents input, #geoContents input {\n  border:1px solid #bbb;\n  border-radius: 6px;\n  margin-bottom:2px;\n}\n\n#conversions, #knowledge {\n  list-style-type:none;\n  float:left;\n  color:#222;\n}\n\nfieldset {\n  border:1px solid #bbb;\n  margin:5px;\n  padding: 1em;\n  float:left;\n  min-width: 0;\n}\nfieldset.listing {\n  float:none;\n}\n\nfieldset.listing legend {\n  padding: 0.2em 0.5em;\n  background: #fff;\n  text-align:left;\n  cursor:pointer;\n}\ncode {\n  display: block;\n  white-space: pre\n}\n.circled {\n  display: inline-block;\n  width: 1.2em;\n  line-height: 1.2em;\n  border-radius: 50%;\n  text-align: center;\n  color: #fff;\n  background-color: #666;\n  padding-left: 0.1em;\n  padding-bottom: 0.1em;\n  height: 1.2em;\n}\n#errorTab {\n  color: red;\n}\n#errorOutput {\n  font-family: menlo, consolas, 'DejaVu Sans Mono', monospace;\n\tcolor: #00ff00;\n\tbackground: black;\n\tfont-size: 12pt;\n\tpadding: 10px;\n}\n#diagramOutputSupplement {\n\tpadding-top: 10px;\n  color:#222;\n}\n#convertOutput {\n  min-height: 135px;\n}\n#convertOutput pre {\n  font-family: menlo, consolas, 'DejaVu Sans Mono', monospace;\n  font-size: 9pt;\n  line-height: 1.4em;\n  overflow-x: auto;\n  overflow-y: hidden;\n}\n.line {\n\tdisplay: block;\n\theight:38px;\n  border-bottom:solid 1px #ccc; /* ligne continue sur toute la largeur */\n}\n.info-symbol {\n  display: inline-block;\n  width: 16px;\n  height: 16px;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  vertical-align: middle;\n}\nul.tabs {\n\tdisplay: block;\n\tposition:relative;\n\ttop:-35px;\n\tfont-size:15px;\n\tfont-weight:bold;\n}\nul.tabs .first_tab {\n\tmargin-left:75px;\n}\nul.tabs li {\n\tdisplay: inline;\n\tmargin-left:5px;\n}\nul.tabs li a {\n\t-webkit-border-radius: 6px 6px 0px 0px;\n\t-moz-border-radius: 6px 6px 0px 0px;\n\tborder-radius: 6px 6px 0px 0px;\n\tborder-top: 1px solid #ccc;\n\tborder-left: 1px solid #ccc;\n\tborder-right: 1px solid #ccc;\n\tpadding: 5px 20px;\n  line-height:40px;\n\tbackground: #f8f8f8;\n}\n@-moz-document url-prefix() { \n  ul.tabs li a {\n    position: relative;\n    bottom: 1px;\n  }\n}\n@media screen and (max-device-width: 480px){\n    ul.tabs li a {\n        position: relative;\n        bottom: 12px;\n    }\n}\n\nul.tabs li a.active {\n\tbackground: #fff;\n  border-bottom:3px solid #fff; /* on the continuous line */\n}\nul.tabs a:hover {\n  color:black;\n}\n\n#aboutContents, #paramContents {\n  padding: 20px;\n}\n\n#geoContents, #paramContents, #aboutContents {\n  display: none;\n  overflow-y: auto;\n  border: 1px solid #ccc;\n}\n#geoTab, #errorTab, #downloadButton {\n  display: none;\n}\n.never_refreshed {\n\tpadding-top:40px;\n\tpadding-bottom:20px;\n}\n\n#aboutContents body {\n    line-height: 1.5em;\n    padding: 0 1.9em;\n}\n#aboutContents pre {\n    font-family: \"Source Code Pro\", monospace;\n\t\tfont-size: 10pt;\n\t\tfont-weight: 600;\n    margin: 0;\n    padding: 1em 1em;\n    background-color: #222;\n    color: greenyellow;\n    height: \"4em\";\n    border-radius: 5px;\n}\n#aboutContents ul {\n  list-style-type:square;\n  margin: 1em 0 1em 2em;\n}\n#aboutContents i {\n  font-style: italic;\n}\n#tutorial {\n  position: absolute;\n  top: 6px;\n  right: 6px;\n  padding: 0 10px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border-radius: 3px;\n  cursor: pointer;\n}\n\n#tutorial::after {\n  margin-left: 5px;\n}\n\n\n.buttons {\n  margin-top: 32px;\n  margin-left: 8px;\n  width: 64px;\n  position:absolute;\n  text-align: center;\n}\n\n.customButton {\n  display: inline-block;\n  width: 48px;\n  height: 48px;\n  background-size:cover;\n  background-position:50% 50%;\n  background-repeat: no-repeat;\n  background-position: center;\n  cursor: pointer;\n  border: none;\n  outline: none;\n  transition: transform 0.2s ease-in-out;\n  margin-bottom: 5px;\n}\n\n.customButton:hover {\n  transform: scale(1.4);\n}\n\n.inlineIcon {\n  height: 1.5em;\n  vertical-align: bottom;\n  transition: transform 0.2s ease-in-out;\n}\n.inlineIcon:hover {\n  transform: scale(1.4);\n}\n\n.tooltip {\n  position: relative;\n  display: inline-block;\n}\n\n.tooltip .tooltiptext {\n  visibility: hidden;\n  background-color: #666;\n  color: #fff;\n  font-size: 10px;\n  font-weight: 600;\n  text-align:center;\n  border-radius: 6px;\n  padding: 0px 8px;\n  position: absolute;\n  z-index: 50;\n  top: 50%;\n  right: calc(100% + 10px);\n  white-space: nowrap;\n  opacity: 0;\n}\n\n.tooltip:hover .tooltiptext {\n  visibility: visible;\n  opacity: 1;\n  transform: translateY(-50%);\n}\n\n.button-with-popup {\n  position: relative;\n  user-select: none;\n  -moz-user-select: none;\n  -webkit-user-select: none;\n  -ms-user-select: none;\n}\n\n.popup-menu {\n  position: absolute;\n  top: calc(50% - 52px);\n  left: 80px;\n  z-index: 50;\n  display: none;\n}\n\n.popup-item {\n  display: block;\n  background-color: #666;\n  color: #fff;\n  border-radius: 6px;\n  border: 0px;\n  padding: 0px 5px;\n  margin-bottom: 4px;\n  box-shadow: 1px 1px 1px 1px rgba(255,255,255,0.7);\n  cursor: pointer;\n  font-size: 11px;\n  font-weight: 600;\n  text-align: left;\n  width:max-content;\n}\n\n.popup-close {\n  border-radius: 50%;\n  width: 24px;\n  height: 24px;\n  text-align: center;\n}\n\n.popup-item:hover {\n  background-color: #FF931E;\n  transition: transform 0.1s;\n  transform: scale(1.1);\n  transform-origin: left;\n}\n\n.popup-close:hover {\n  background-color: #DF3633;\n}\n\n.mld .relation { font-variant: small-caps; font-weight: bold }\n.mld .primary { text-decoration: underline }\n.mld .foreign { font-style: oblique }\n.mld strong { font-weight: bold }\n.mld i { font-style: italic }\n.mld ul { list-style-type:square; margin: 0 0 1em 2em }\n.mld sup { vertical-align: super; font-size: smaller;}\n\n#rotatingButton {\n  position: relative;\n  top: 0;\n  left: 0;\n}\n\n#empty {\n  position: relative;\n  top: 0;\n  left: 0;\n}\n\n#refreshRotatingButton {\n  position: absolute;\n  top: 1px;\n  left: 10px;\n  width: 45px;\n  height: 45px;\n  animation: rotation 0.4s infinite linear;\n}\n@keyframes rotation {\n  from {transform: rotate(359deg);}\n  to {transform: rotate(0deg);}\n}\n\n:root.flashlight:before {\n  content: '';\n  width: 100%;\n  height: 100%;\n  position: fixed;\n  background: radial-gradient(\n      circle 16rem at var(--cursorXPos) var(--cursorYPos),\n      rgba(0, 0, 50, 0) 0%,\n      rgba(0, 0, 0, 0.95) 100%\n  ), #FFFF0020;\n  z-index: 11;\n}\n@keyframes pulse {\n  0% {\n   transform: scale(0.9, 0.9);\n  }\n  50% {\n   transform: scale(1.3, 1.3);\n  }\n  100% {\n  transform: scale(0.9, 0.9);\n  }\n}\n.pulsating {\n  animation: pulse 1s linear infinite;\n}\n\n.settings-pane {\n  display: grid;\n  grid-template-columns: 0.5fr 1fr;\n  gap: 0.3ex 0.8em; /* Vertical and horizontal gap */\n}\n\n.setting-row {\n  display: contents; /* Makes .setting-row transparent to the grid */\n  color:#222;\n}\n\n.setting-label {\n  grid-column: 1; /* Position in the first column */\n  text-align: right;\n  padding-right: 10px; /* A little spacing between the label and the control */\n}\n\n.setting-controls {\n  grid-column: 2; /* Position in the second column */\n  list-style-type: none; /* Removes bullets from the list */\n  padding: 0; /* Removes default padding from the list */\n  margin: 0; /* Removes default margin from the list */\n}\n\n.setting-controls li {\n  display: flex; /* Makes sure checkbox and its label are side by side */\n  align-items: center; /* Vertically centers checkbox with its label */\n}\n\n.setting-control {\n  margin-right: 10px; /* Adds some space between a checkbox and its label */\n}\n.setting-details {\n  width: 100%;\n  box-sizing: border-box;\n}\n\n.setting-details summary {\n  cursor: pointer; /* Makes it clear that this is clickable */\n  color: #666;\n}\n.footnote {\n  margin-top: 50px;\n}\n\n.footnote p {\n  font-size: 11px;\n  color: #666;\n  line-height:normal;\n}\n\n.footnote p a {\n  color: black;\n}\n\n#paramContents input[type=\"url\"] {\n  width: 100%;\n  height: 2em;\n  border: 1px solid #CCC;\n  border-radius: 0px;\n  padding: 0px 0.5em 0px 0.5em;\n}\n"
  }
]