@tricoteuses/assemblee
Version:
Retrieve, clean up & handle French Assemblée nationale's open data
886 lines (881 loc) • 136 kB
JavaScript
/// Load data from files
import assert from "assert";
import fs from "fs-extra";
import path from "path";
export { EnabledDatasets } from "./datasets.mjs";
import { datasets, EnabledDatasets } from "./datasets.mjs";
export { walkDir } from "./file_systems.mjs";
import { walkDir } from "./file_systems.mjs";
import { Convert as ActeursEtOrganesConvert } from "./types/acteurs_et_organes.mjs";
import { Convert as AgendasConvert } from "./types/agendas.mjs";
import { Convert as AmendementsConvert } from "./types/amendements.mjs";
import { Convert as DossiersLegislatifsConvert } from "./types/dossiers_legislatifs.mjs";
import { Legislature } from "./types/legislatures.mjs";
import { Convert as ScrutinsConvert } from "./types/scrutins.mjs";
import { Convert as QuestionsConvert } from "./types/questions.mjs";
import { Convert as ComptesRendusConvert } from "./types/debats.mjs";
const documentUidRegex = /^((?<documentType>ACIN|ALCN|AVCE|AVIS|DECL|ETDI|LETT|MESS|MION|PION|PNRE|PRJL|RAPP|RINF|RION)(?<chambre>AN|CG|SN)(?<republique>R\d+)[LS](?<legislature>\d+)(?<etat>B|BTA|BTC|TAP)(?<numero>\d+)(-.*)?)|((?<documentType2>MION)(?<chambre2>AN|SN)(?<republique2>R\d+)[LS](?<legislature2>\d+)-N(?<numero2>\d+))$/;
const dossierUidRegex = /^DL(R\d+)(L\d+)N(\d+)$/;
const reunionUidRegex = /^RU(AN|CG|SN)(R\d+)(L\d+)([AS]\d{4})(IDC|IDFL?|IDS)(\d+)$/;
const scrutinUidRegex = /^VT(AN|CG)(R\d+)(L\d+)V(\d+)$/;
const compteRenduUidRegex = /^CRS(AN|CG)(R\d+)(L\d+)(S\d+)(O|E|D)(\d+)(N\d+)$/;
const questionUidRegex = /^QAN(R\d+)(L\d+)Q(E|G|OSD)(\d+)$/;
function* iterLoadAssembleeItems(dataDir, legislature, datasets, convertToItem, subfolderName, fileExtension = "json", {
noValidation = false,
log = false
} = {}) {
const itemUid = new Set();
for (const dataset of datasets) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== undefined && legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
let fileExtensionRegex = new RegExp(`\\.${fileExtension}$`);
const datasetDir = path.join(dataDir, dataset.filename.replace(fileExtensionRegex, "_nettoye"));
for (const itemSplitPath of walkDir(datasetDir, subfolderName)) {
const itemFilename = itemSplitPath[itemSplitPath.length - 1];
if (!itemFilename.endsWith(".json")) {
continue;
}
const itemFilePath = path.join(datasetDir, ...itemSplitPath);
if (log) {
console.log(`Loading file: ${itemFilePath}…`);
}
let itemJson = fs.readFileSync(itemFilePath, {
encoding: "utf8"
});
let item = noValidation ? JSON.parse(itemJson) : convertToItem(itemJson);
if (itemUid.has(item.uid)) {
continue;
}
itemUid.add(item.uid);
yield {
item: item,
datasetLegislature: dataset.legislature
};
itemJson = null;
}
}
}
export function* iterLoadAssembleeActeurs(dataDir, legislature, options = {}) {
for (const {
item: acteur,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.acteursEtOrganes, ActeursEtOrganesConvert.toActeur, ["acteurs"], "json", options)) {
yield {
acteur,
datasetLegislature
};
}
}
export function* iterLoadAssembleeOrganes(dataDir, legislature, options = {}) {
for (const {
item: organe,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.acteursEtOrganes, ActeursEtOrganesConvert.toOrgane, ["organes"], "json", options)) {
yield {
organe,
datasetLegislature
};
}
}
export function* iterLoadAssembleeAmendements(dataDir, legislature, options = {}) {
for (const {
item: amendement,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.amendements, AmendementsConvert.toAmendement, [], "json", options)) {
yield {
amendement,
datasetLegislature
};
}
}
export function* iterLoadAssembleeDocuments(dataDir, legislature, options = {}) {
for (const {
item: document,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.dossiersLegislatifs, DossiersLegislatifsConvert.toDocument, ["documents"], "json", options)) {
yield {
document,
datasetLegislature
};
}
}
export function* iterLoadAssembleeDossiersParlementaires(dataDir, legislature, options = {}) {
for (const {
item: dossierParlementaire,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.dossiersLegislatifs, DossiersLegislatifsConvert.toDossierParlementaire, ["dossiers"], "json", options)) {
yield {
dossierParlementaire,
datasetLegislature
};
}
}
export function* iterLoadAssembleeReunions(dataDir, legislature, options = {}) {
for (const {
item: reunion,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.agendas, AgendasConvert.toReunion, [], "json", options)) {
yield {
reunion,
datasetLegislature
};
}
}
export function* iterLoadAssembleeScrutins(dataDir, legislature, options = {}) {
for (const {
item: scrutin,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.scrutins, ScrutinsConvert.toScrutin, [], "json", options)) {
yield {
scrutin,
datasetLegislature
};
}
}
export function* iterLoadAssembleeQuestions(dataDir, legislature, options = {}) {
for (const {
item: question,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.questions, QuestionsConvert.toQuestion, [], "json", options)) {
yield {
question,
datasetLegislature
};
}
}
export function* iterLoadAssembleeComptesRendus(dataDir, legislature, options = {}) {
for (const {
item: compteRendu,
datasetLegislature
} of iterLoadAssembleeItems(dataDir, legislature, datasets.comptesRendusSeances, ComptesRendusConvert.toCompteRendu, [], "xml", options)) {
yield {
compteRendu,
datasetLegislature
};
}
}
/// Load data from split files.
/// Deprecated: Use iterLoad... iterators instead.
export function loadAssembleeData(dataDir, enabledDatasets, legislature, {
log = false
} = {}) {
const acteurByUid = {};
const organeByUid = {};
if (enabledDatasets & EnabledDatasets.ActeursEtOrganes) {
for (const dataset of datasets.acteursEtOrganes) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const acteurSplitPath of walkDir(datasetDir, ["acteurs"])) {
const acteurFilename = acteurSplitPath[acteurSplitPath.length - 1];
if (!acteurFilename.endsWith(".json")) {
continue;
}
const acteurFilePath = path.join(datasetDir, ...acteurSplitPath);
if (log) {
console.log(`Loading file: ${acteurFilePath}…`);
}
const acteurJson = fs.readFileSync(acteurFilePath, {
encoding: "utf8"
});
const acteur = ActeursEtOrganesConvert.toActeur(acteurJson);
// Keep the first existing "acteur", because the first wrapper is the most complete.
if (acteurByUid[acteur.uid] === undefined) {
acteurByUid[acteur.uid] = acteur;
}
}
for (const organeSplitPath of walkDir(datasetDir, ["organes"])) {
const organeFilename = organeSplitPath[organeSplitPath.length - 1];
if (!organeFilename.endsWith(".json")) {
continue;
}
const organeFilePath = path.join(datasetDir, ...organeSplitPath);
if (log) {
console.log(`Loading file: ${organeFilePath}…`);
}
const organeJson = fs.readFileSync(organeFilePath, {
encoding: "utf8"
});
const organe = ActeursEtOrganesConvert.toOrgane(organeJson);
// Keep the first existing "organe", because the first wrapper is the most complete.
if (organeByUid[organe.uid] === undefined) {
organeByUid[organe.uid] = organe;
}
}
}
}
const reunionByUid = {};
const reunionsByDay = {};
const reunionsByDossierUid = {};
if (enabledDatasets & EnabledDatasets.Agendas) {
for (const dataset of datasets.agendas) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const reunionSplitPath of walkDir(datasetDir)) {
const reunionFilename = reunionSplitPath[reunionSplitPath.length - 1];
if (!reunionFilename.endsWith(".json")) {
continue;
}
const reunionFilePath = path.join(datasetDir, ...reunionSplitPath);
if (log) {
console.log(`Loading file: ${reunionFilePath}…`);
}
const reunionJson = fs.readFileSync(reunionFilePath, {
encoding: "utf8"
});
const reunion = AgendasConvert.toReunion(reunionJson);
if (reunionByUid[reunion.uid] === undefined) {
reunionByUid[reunion.uid] = reunion;
}
const day = reunion.timestampDebut.toISOString().split("T")[0];
let reunionsAtDay = reunionsByDay[day];
if (reunionsAtDay === undefined) {
reunionsAtDay = reunionsByDay[day] = [];
}
reunionsAtDay.push(reunion);
const odj = reunion.odj;
if (odj !== undefined) {
for (const pointOdj of odj.pointsOdj || []) {
for (const dossierLegislatifRef of pointOdj.dossiersLegislatifsRefs || []) {
let reunionsAtDossierUid = reunionsByDossierUid[dossierLegislatifRef];
if (reunionsAtDossierUid === undefined) {
reunionsAtDossierUid = reunionsByDossierUid[dossierLegislatifRef] = [];
}
reunionsAtDossierUid.push(reunion);
}
}
}
}
}
}
const amendementByUid = {};
if (enabledDatasets & EnabledDatasets.Amendements) {
for (const dataset of datasets.amendements) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const amendementSplitPath of walkDir(datasetDir)) {
const amendementFilename = amendementSplitPath[amendementSplitPath.length - 1];
if (!amendementFilename.endsWith(".json")) {
continue;
}
const amendementFilePath = path.join(datasetDir, ...amendementSplitPath);
if (log) {
console.log(`Loading file: ${amendementFilePath}…`);
}
const amendementJson = fs.readFileSync(amendementFilePath, {
encoding: "utf8"
});
const amendement = AmendementsConvert.toAmendement(amendementJson);
if (amendementByUid[amendement.uid] === undefined) {
amendementByUid[amendement.uid] = amendement;
}
}
}
}
const documentByUid = {};
const dossierParlementaireBySenatChemin = {};
const dossierParlementaireByTitreChemin = {};
const dossierParlementaireByUid = {};
if (enabledDatasets & EnabledDatasets.DossiersLegislatifs) {
for (const dataset of datasets.dossiersLegislatifs) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const documentSplitPath of walkDir(datasetDir, ["documents"])) {
const documentFilename = documentSplitPath[documentSplitPath.length - 1];
if (!documentFilename.endsWith(".json")) {
continue;
}
const documentFilePath = path.join(datasetDir, ...documentSplitPath);
if (log) {
console.log(`Loading file: ${documentFilePath}…`);
}
const documentJson = fs.readFileSync(documentFilePath, {
encoding: "utf8"
});
const document = DossiersLegislatifsConvert.toDocument(documentJson);
if (documentByUid[document.uid] === undefined) {
documentByUid[document.uid] = document;
}
}
for (const dossierSplitPath of walkDir(datasetDir, ["dossiers"])) {
const dossierFilename = dossierSplitPath[dossierSplitPath.length - 1];
if (!dossierFilename.endsWith(".json")) {
continue;
}
const dossierFilePath = path.join(datasetDir, ...dossierSplitPath);
if (log) {
console.log(`Loading file: ${dossierFilePath}…`);
}
const dossierJson = fs.readFileSync(dossierFilePath, {
encoding: "utf8"
});
const dossier = DossiersLegislatifsConvert.toDossierParlementaire(dossierJson);
const titreDossier = dossier.titreDossier;
if (titreDossier.senatChemin && dossierParlementaireBySenatChemin[titreDossier.senatChemin] === undefined) {
dossierParlementaireBySenatChemin[titreDossier.senatChemin] = dossier;
}
if (titreDossier.titreChemin && dossierParlementaireByTitreChemin[titreDossier.titreChemin] === undefined) {
dossierParlementaireByTitreChemin[titreDossier.titreChemin] = dossier;
}
if (dossierParlementaireByUid[dossier.uid] === undefined) {
dossierParlementaireByUid[dossier.uid] = dossier;
}
}
}
}
let photoByUid = {};
if (enabledDatasets & EnabledDatasets.Photos) {
{
const jsonFilePath = path.join(dataDir, `photos_deputes_${
// TODO: Handle Legislature.All.
legislature === Legislature.All ? Legislature.DixSept : legislature}`, "deputes.json");
if (fs.existsSync(jsonFilePath)) {
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
Object.assign(photoByUid, JSON.parse(json));
} else if (log) {
console.log(`Ignoring missing file: ${jsonFilePath}`);
}
}
{
const jsonFilePath = path.join(dataDir, "photos_senateurs", "senateurs.json");
if (fs.existsSync(jsonFilePath)) {
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
Object.assign(photoByUid, JSON.parse(json));
} else if (log) {
console.log(`Ignoring missing file: ${jsonFilePath}`);
}
}
}
const scrutinByUid = {};
if (enabledDatasets & EnabledDatasets.Scrutins) {
for (const dataset of datasets.scrutins) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const scrutinSplitPath of walkDir(datasetDir)) {
const scrutinFilename = scrutinSplitPath[scrutinSplitPath.length - 1];
if (!scrutinFilename.endsWith(".json")) {
continue;
}
const scrutinFilePath = path.join(datasetDir, ...scrutinSplitPath);
if (log) {
console.log(`Loading file: ${scrutinFilePath}…`);
}
const scrutinJson = fs.readFileSync(scrutinFilePath, {
encoding: "utf8"
});
const scrutin = ScrutinsConvert.toScrutin(scrutinJson);
if (scrutinByUid[scrutin.uid] === undefined) {
scrutinByUid[scrutin.uid] = scrutin;
}
}
}
}
const questionByUid = {};
if (enabledDatasets & EnabledDatasets.Questions) {
for (const dataset of datasets.questions) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const questionSplitPath of walkDir(datasetDir)) {
const questionFilename = questionSplitPath[questionSplitPath.length - 1];
if (!questionFilename.endsWith(".json")) {
continue;
}
const questionFilePath = path.join(datasetDir, ...questionSplitPath);
if (log) {
console.log(`Loading file: ${questionFilePath}…`);
}
const questionJson = fs.readFileSync(questionFilePath, {
encoding: "utf8"
});
const question = QuestionsConvert.toQuestion(questionJson);
if (questionByUid[question.uid] === undefined) {
questionByUid[question.uid] = question;
}
}
}
}
const compteRenduByUid = {};
if (enabledDatasets & EnabledDatasets.ComptesRendusSeances) {
for (const dataset of datasets.comptesRendusSeances) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const datasetDir = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye"));
for (const compteRenduPath of walkDir(datasetDir)) {
const compteRenduFilename = compteRenduPath[compteRenduPath.length - 1];
if (!compteRenduFilename.endsWith(".json")) {
continue;
}
const compteRenduFilePath = path.join(datasetDir, ...compteRenduPath);
if (log) {
console.log(`Loading file: ${compteRenduFilePath}…`);
}
const compteRenduJson = fs.readFileSync(compteRenduFilePath, {
encoding: "utf8"
});
const compteRendu = ComptesRendusConvert.toCompteRendu(compteRenduJson);
if (compteRenduByUid[compteRendu.uid] === undefined) {
compteRenduByUid[compteRendu.uid] = compteRendu;
}
}
}
}
return {
acteurByUid,
amendementByUid,
documentByUid,
dossierParlementaireBySenatChemin,
dossierParlementaireByTitreChemin,
dossierParlementaireByUid,
organeByUid,
photoByUid,
reunionByUid,
reunionsByDay,
reunionsByDossierUid,
scrutinByUid,
questionByUid,
compteRenduByUid
};
}
/// Load data from big monolytic files.
/// Deprecated: Assemblée nationale open data no more uses monolytic files.
export function loadAssembleeDataFromBigFiles(dataDir, enabledDatasets, legislature, {
log = false
} = {}) {
const acteurByUid = {};
const organeByUid = {};
if (enabledDatasets & EnabledDatasets.ActeursEtOrganes) {
for (const dataset of datasets.acteursEtOrganes) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const acteursEtOrganes = ActeursEtOrganesConvert.toActeursEtOrganes(json);
for (const acteur of acteursEtOrganes.acteurs) {
// Keep the first existing "acteur", because the first wrapper is the most complete.
if (acteurByUid[acteur.uid] === undefined) {
acteurByUid[acteur.uid] = acteur;
}
}
for (const organe of acteursEtOrganes.organes) {
// Keep the first existing "organe", because the first wrapper is the most complete.
if (organeByUid[organe.uid] === undefined) {
organeByUid[organe.uid] = organe;
}
}
}
}
const reunionByUid = {};
const reunionsByDay = {};
const reunionsByDossierUid = {};
if (enabledDatasets & EnabledDatasets.Agendas) {
for (const dataset of datasets.agendas) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const agendas = AgendasConvert.toAgendas(json);
for (const reunion of agendas.reunions) {
if (reunionByUid[reunion.uid] === undefined) {
reunionByUid[reunion.uid] = reunion;
}
const day = reunion.timestampDebut.toISOString().split("T")[0];
let reunionsAtDay = reunionsByDay[day];
if (reunionsAtDay === undefined) {
reunionsAtDay = reunionsByDay[day] = [];
}
reunionsAtDay.push(reunion);
const odj = reunion.odj;
if (odj !== undefined) {
for (const pointOdj of odj.pointsOdj || []) {
for (const dossierLegislatifRef of pointOdj.dossiersLegislatifsRefs || []) {
let reunionsAtDossierUid = reunionsByDossierUid[dossierLegislatifRef];
if (reunionsAtDossierUid === undefined) {
reunionsAtDossierUid = reunionsByDossierUid[dossierLegislatifRef] = [];
}
reunionsAtDossierUid.push(reunion);
}
}
}
}
}
}
const amendementByUid = {};
if (enabledDatasets & EnabledDatasets.Amendements) {
for (const dataset of datasets.amendements) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const amendements = AmendementsConvert.toAmendements(json);
for (const texteLegislatif of amendements.textesLegislatifs) {
for (const amendement of texteLegislatif.amendements) {
if (amendementByUid[amendement.uid] === undefined) {
amendementByUid[amendement.uid] = amendement;
}
}
}
}
}
const documentByUid = {};
const dossierParlementaireBySenatChemin = {};
const dossierParlementaireByTitreChemin = {};
const dossierParlementaireByUid = {};
if (enabledDatasets & EnabledDatasets.DossiersLegislatifs) {
for (const dataset of datasets.dossiersLegislatifs) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const dossiersLegislatifs = DossiersLegislatifsConvert.toDossiersLegislatifs(json);
for (const document of dossiersLegislatifs.textesLegislatifs) {
if (documentByUid[document.uid] === undefined) {
documentByUid[document.uid] = document;
}
}
for (const dossier of dossiersLegislatifs.dossiersParlementaires) {
const titreDossier = dossier.titreDossier;
if (titreDossier.senatChemin && dossierParlementaireBySenatChemin[titreDossier.senatChemin] === undefined) {
dossierParlementaireBySenatChemin[titreDossier.senatChemin] = dossier;
}
if (titreDossier.titreChemin && dossierParlementaireByTitreChemin[titreDossier.titreChemin] === undefined) {
dossierParlementaireByTitreChemin[titreDossier.titreChemin] = dossier;
}
if (dossierParlementaireByUid[dossier.uid] === undefined) {
dossierParlementaireByUid[dossier.uid] = dossier;
}
}
}
}
const photoByUid = {};
if (enabledDatasets & EnabledDatasets.Photos) {
const photoByUid = {};
{
const jsonFilePath = path.join(dataDir, `photos_deputes_${
// TODO: Handle Legislature.All.
legislature === Legislature.All ? Legislature.DixSept : legislature}`, "deputes.json");
if (fs.existsSync(jsonFilePath)) {
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
Object.assign(photoByUid, JSON.parse(json));
} else if (log) {
console.log(`Ignoring missing file: ${jsonFilePath}`);
}
}
{
const jsonFilePath = path.join(dataDir, "photos_senateurs", "senateurs.json");
if (fs.existsSync(jsonFilePath)) {
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
Object.assign(photoByUid, JSON.parse(json));
} else if (log) {
console.log(`Ignoring missing file: ${jsonFilePath}`);
}
}
}
const scrutinByUid = {};
if (enabledDatasets & EnabledDatasets.Scrutins) {
for (const dataset of datasets.scrutins) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const scrutins = ScrutinsConvert.toScrutins(json);
for (const scrutin of scrutins.scrutins) {
if (scrutinByUid[scrutin.uid] === undefined) {
scrutinByUid[scrutin.uid] = scrutin;
}
}
}
}
const questionByUid = {};
if (enabledDatasets & EnabledDatasets.Questions) {
for (const dataset of datasets.questions) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const questions = QuestionsConvert.toQuestions(json);
for (const question of questions.questions) {
if (questionByUid[question.uid] === undefined) {
questionByUid[question.uid] = question;
}
}
}
}
const compteRenduByUid = {};
if (enabledDatasets & EnabledDatasets.ComptesRendusSeances) {
for (const dataset of datasets.comptesRendusSeances) {
if (dataset.ignoreForWeb) {
continue;
}
if (legislature !== Legislature.All && dataset.legislature !== Legislature.All && legislature !== dataset.legislature) {
continue;
}
const jsonFilePath = path.join(dataDir, dataset.filename.replace(/\.json$/, "_nettoye.json"));
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
const comptesRendus = ComptesRendusConvert.toComptesRendus(json);
for (const compteRendu of comptesRendus.comptesRendus) {
if (compteRenduByUid[compteRendu.uid] === undefined) {
compteRenduByUid[compteRendu.uid] = compteRendu;
}
}
}
}
return {
acteurByUid,
amendementByUid,
documentByUid,
dossierParlementaireBySenatChemin,
dossierParlementaireByTitreChemin,
dossierParlementaireByUid,
organeByUid,
photoByUid,
reunionByUid,
reunionsByDay,
reunionsByDossierUid,
scrutinByUid,
questionByUid,
compteRenduByUid
};
}
/**
* Read infos of a document or a division of a document from file system
*
* @param dataDir
* @param uid UID of a document or a division
* @param formats requested formats of the document in decreasing preference order
*/
export function loadAssembleeDocumentFile(dataDir, uid, formats) {
const documentsDir = path.join(dataDir, "Documents");
const documentDir = pathFromDocumentUid(documentsDir, uid);
const indexPath = path.join(documentDir, "index.json");
if (!fs.pathExistsSync(indexPath)) {
return undefined;
}
const index = fs.readJsonSync(indexPath);
for (const format of formats) {
for (const {
filename,
url
} of index[format] ?? []) {
if (filename === undefined) {
continue;
}
return {
format,
path: path.join(documentDir, filename),
url
};
}
}
return undefined;
}
export function loadAssembleePhotosDeputes(dataDir, legislature, {
log = false
} = {}) {
const jsonFilePath = path.join(dataDir, `photos_deputes_${
// TODO: Handle Legislature.All.
legislature === Legislature.All ? Legislature.DixSept : legislature}`, "deputes.json");
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
return JSON.parse(json);
}
export function loadAssembleePhotosSenateurs(dataDir, {
log = false
} = {}) {
const jsonFilePath = path.join(dataDir, "photos_senateurs", "senateurs.json");
if (log) {
console.log(`Loading file: ${jsonFilePath}`);
}
const json = fs.readFileSync(jsonFilePath, {
encoding: "utf8"
});
return JSON.parse(json);
}
export function pathFromDocumentUid(documentsDir, uid) {
const match = uid.match(documentUidRegex);
assert.notStrictEqual(match, null, `Unexpected structure for document UID: ${uid}`);
const groups = match.groups;
const documentType = path.join(documentsDir, groups.documentType ?? groups.documentType2);
const chambreDir = path.join(documentType, groups.chambre ?? groups.chambre2);
const republiqueDir = path.join(chambreDir, groups.republique ?? groups.republique2);
const legislatureDir = path.join(republiqueDir, groups.legislature ?? groups.legislature2);
const etat = groups.etat;
if (etat === undefined) {
fs.ensureDirSync(legislatureDir);
return path.join(legislatureDir, uid);
}
const etatDir = path.join(legislatureDir, etat);
let numero = "000000" + (groups.numero ?? groups.numero2);
numero = numero.substring(numero.length - 6);
const numeroMilliersDir = path.join(etatDir, numero.substring(0, 3));
fs.ensureDirSync(numeroMilliersDir);
return path.join(numeroMilliersDir, uid);
}
export function pathFromDossierParlementaireUid(dossiersDir, uid) {
return pathFromUid(dossiersDir, uid, dossierUidRegex);
}
export function pathFromReunionUid(reunionsDir, uid) {
const match = reunionUidRegex.exec(uid);
assert.notStrictEqual(match, null, `Unexpected structure for reunion UID: ${uid}`);
const chambreDir = path.join(reunionsDir, match[1]);
const republiqueDir = path.join(chambreDir, match[2]);
const legislatureDir = path.join(republiqueDir, match[3]);
const sessionDir = path.join(legislatureDir, match[4]);
const idDir = path.join(sessionDir, match[5]);
let numero = "000000000" + match[6];
numero = numero.substring(numero.length - 9);
const numeroMillionsDir = path.join(idDir, numero.substring(0, 3));
const numeroMilliersDir = path.join(numeroMillionsDir, numero.substring(3, 3));
fs.ensureDirSync(numeroMilliersDir);
return path.join(numeroMilliersDir, uid);
}
export function pathFromScrutinUid(scrutinsDir, uid) {
const match = scrutinUidRegex.exec(uid);
assert.notStrictEqual(match, null, `Unexpected structure for scrutin UID: ${uid}`);
const chambreDir = path.join(scrutinsDir, match[1]);
const republiqueDir = path.join(chambreDir, match[2]);
const legislatureDir = path.join(republiqueDir, match[3]);
let numero = "000000" + match[4];
numero = numero.substring(numero.length - 6);
const numeroMilliersDir = path.join(legislatureDir, numero.substring(0, 3));
fs.ensureDirSync(numeroMilliersDir);
return path.join(numeroMilliersDir, uid);
}
export function pathFromQuestionUid(dataDir, uid) {
return pathFromUid(dataDir, uid, questionUidRegex);
}
export function pathFromCompteRenduUid(dataDir, uid) {
return pathFromUid(dataDir, uid, compteRenduUidRegex);
}
// Get standard path for object with uid : republique > legislature > group objects by thousands
function pathFromUid(dataDir, uid, dataRegexp) {
const match = dataRegexp.exec(uid);
assert.notStrictEqual(match, null, `Unexpected structure for object with UID: ${uid}`);
const republiqueDir = path.join(dataDir, match[1]);
const legislatureDir = path.join(republiqueDir, match[2]);
let numero = "000000" + match[3];
numero = numero.substring(numero.length - 6);
const numeroMilliersDir = path.join(legislatureDir, numero.substring(0, 3));
fs.ensureDirSync(numeroMilliersDir);
return path.join(numeroMilliersDir, uid);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhc3NlcnQiLCJmcyIsInBhdGgiLCJFbmFibGVkRGF0YXNldHMiLCJkYXRhc2V0cyIsIndhbGtEaXIiLCJDb252ZXJ0IiwiQWN0ZXVyc0V0T3JnYW5lc0NvbnZlcnQiLCJBZ2VuZGFzQ29udmVydCIsIkFtZW5kZW1lbnRzQ29udmVydCIsIkRvc3NpZXJzTGVnaXNsYXRpZnNDb252ZXJ0IiwiTGVnaXNsYXR1cmUiLCJTY3J1dGluc0NvbnZlcnQiLCJRdWVzdGlvbnNDb252ZXJ0IiwiQ29tcHRlc1JlbmR1c0NvbnZlcnQiLCJkb2N1bWVudFVpZFJlZ2V4IiwiZG9zc2llclVpZFJlZ2V4IiwicmV1bmlvblVpZFJlZ2V4Iiwic2NydXRpblVpZFJlZ2V4IiwiY29tcHRlUmVuZHVVaWRSZWdleCIsInF1ZXN0aW9uVWlkUmVnZXgiLCJpdGVyTG9hZEFzc2VtYmxlZUl0ZW1zIiwiZGF0YURpciIsImxlZ2lzbGF0dXJlIiwiY29udmVydFRvSXRlbSIsInN1YmZvbGRlck5hbWUiLCJmaWxlRXh0ZW5zaW9uIiwibm9WYWxpZGF0aW9uIiwibG9nIiwiaXRlbVVpZCIsIlNldCIsImRhdGFzZXQiLCJpZ25vcmVGb3JXZWIiLCJ1bmRlZmluZWQiLCJBbGwiLCJmaWxlRXh0ZW5zaW9uUmVnZXgiLCJSZWdFeHAiLCJkYXRhc2V0RGlyIiwiam9pbiIsImZpbGVuYW1lIiwicmVwbGFjZSIsIml0ZW1TcGxpdFBhdGgiLCJpdGVtRmlsZW5hbWUiLCJsZW5ndGgiLCJlbmRzV2l0aCIsIml0ZW1GaWxlUGF0aCIsImNvbnNvbGUiLCJpdGVtSnNvbiIsInJlYWRGaWxlU3luYyIsImVuY29kaW5nIiwiaXRlbSIsIkpTT04iLCJwYXJzZSIsImhhcyIsInVpZCIsImFkZCIsImRhdGFzZXRMZWdpc2xhdHVyZSIsIml0ZXJMb2FkQXNzZW1ibGVlQWN0ZXVycyIsIm9wdGlvbnMiLCJhY3RldXIiLCJhY3RldXJzRXRPcmdhbmVzIiwidG9BY3RldXIiLCJpdGVyTG9hZEFzc2VtYmxlZU9yZ2FuZXMiLCJvcmdhbmUiLCJ0b09yZ2FuZSIsIml0ZXJMb2FkQXNzZW1ibGVlQW1lbmRlbWVudHMiLCJhbWVuZGVtZW50IiwiYW1lbmRlbWVudHMiLCJ0b0FtZW5kZW1lbnQiLCJpdGVyTG9hZEFzc2VtYmxlZURvY3VtZW50cyIsImRvY3VtZW50IiwiZG9zc2llcnNMZWdpc2xhdGlmcyIsInRvRG9jdW1lbnQiLCJpdGVyTG9hZEFzc2VtYmxlZURvc3NpZXJzUGFybGVtZW50YWlyZXMiLCJkb3NzaWVyUGFybGVtZW50YWlyZSIsInRvRG9zc2llclBhcmxlbWVudGFpcmUiLCJpdGVyTG9hZEFzc2VtYmxlZVJldW5pb25zIiwicmV1bmlvbiIsImFnZW5kYXMiLCJ0b1JldW5pb24iLCJpdGVyTG9hZEFzc2VtYmxlZVNjcnV0aW5zIiwic2NydXRpbiIsInNjcnV0aW5zIiwidG9TY3J1dGluIiwiaXRlckxvYWRBc3NlbWJsZWVRdWVzdGlvbnMiLCJxdWVzdGlvbiIsInF1ZXN0aW9ucyIsInRvUXVlc3Rpb24iLCJpdGVyTG9hZEFzc2VtYmxlZUNvbXB0ZXNSZW5kdXMiLCJjb21wdGVSZW5kdSIsImNvbXB0ZXNSZW5kdXNTZWFuY2VzIiwidG9Db21wdGVSZW5kdSIsImxvYWRBc3NlbWJsZWVEYXRhIiwiZW5hYmxlZERhdGFzZXRzIiwiYWN0ZXVyQnlVaWQiLCJvcmdhbmVCeVVpZCIsIkFjdGV1cnNFdE9yZ2FuZXMiLCJhY3RldXJTcGxpdFBhdGgiLCJhY3RldXJGaWxlbmFtZSIsImFjdGV1ckZpbGVQYXRoIiwiYWN0ZXVySnNvbiIsIm9yZ2FuZVNwbGl0UGF0aCIsIm9yZ2FuZUZpbGVuYW1lIiwib3JnYW5lRmlsZVBhdGgiLCJvcmdhbmVKc29uIiwicmV1bmlvbkJ5VWlkIiwicmV1bmlvbnNCeURheSIsInJldW5pb25zQnlEb3NzaWVyVWlkIiwiQWdlbmRhcyIsInJldW5pb25TcGxpdFBhdGgiLCJyZXVuaW9uRmlsZW5hbWUiLCJyZXVuaW9uRmlsZVBhdGgiLCJyZXVuaW9uSnNvbiIsImRheSIsInRpbWVzdGFtcERlYnV0IiwidG9JU09TdHJpbmciLCJzcGxpdCIsInJldW5pb25zQXREYXkiLCJwdXNoIiwib2RqIiwicG9pbnRPZGoiLCJwb2ludHNPZGoiLCJkb3NzaWVyTGVnaXNsYXRpZlJlZiIsImRvc3NpZXJzTGVnaXNsYXRpZnNSZWZzIiwicmV1bmlvbnNBdERvc3NpZXJVaWQiLCJhbWVuZGVtZW50QnlVaWQiLCJBbWVuZGVtZW50cyIsImFtZW5kZW1lbnRTcGxpdFBhdGgiLCJhbWVuZGVtZW50RmlsZW5hbWUiLCJhbWVuZGVtZW50RmlsZVBhdGgiLCJhbWVuZGVtZW50SnNvbiIsImRvY3VtZW50QnlVaWQiLCJkb3NzaWVyUGFybGVtZW50YWlyZUJ5U2VuYXRDaGVtaW4iLCJkb3NzaWVyUGFybGVtZW50YWlyZUJ5VGl0cmVDaGVtaW4iLCJkb3NzaWVyUGFybGVtZW50YWlyZUJ5VWlkIiwiRG9zc2llcnNMZWdpc2xhdGlmcyIsImRvY3VtZW50U3BsaXRQYXRoIiwiZG9jdW1lbnRGaWxlbmFtZSIsImRvY3VtZW50RmlsZVBhdGgiLCJkb2N1bWVudEpzb24iLCJkb3NzaWVyU3BsaXRQYXRoIiwiZG9zc2llckZpbGVuYW1lIiwiZG9zc2llckZpbGVQYXRoIiwiZG9zc2llckpzb24iLCJkb3NzaWVyIiwidGl0cmVEb3NzaWVyIiwic2VuYXRDaGVtaW4iLCJ0aXRyZUNoZW1pbiIsInBob3RvQnlVaWQiLCJQaG90b3MiLCJqc29uRmlsZVBhdGgiLCJEaXhTZXB0IiwiZXhpc3RzU3luYyIsImpzb24iLCJPYmplY3QiLCJhc3NpZ24iLCJzY3J1dGluQnlVaWQiLCJTY3J1dGlucyIsInNjcnV0aW5TcGxpdFBhdGgiLCJzY3J1dGluRmlsZW5hbWUiLCJzY3J1dGluRmlsZVBhdGgiLCJzY3J1dGluSnNvbiIsInF1ZXN0aW9uQnlVaWQiLCJRdWVzdGlvbnMiLCJxdWVzdGlvblNwbGl0UGF0aCIsInF1ZXN0aW9uRmlsZW5hbWUiLCJxdWVzdGlvbkZpbGVQYXRoIiwicXVlc3Rpb25Kc29uIiwiY29tcHRlUmVuZHVCeVVpZCIsIkNvbXB0ZXNSZW5kdXNTZWFuY2VzIiwiY29tcHRlUmVuZHVQYXRoIiwiY29tcHRlUmVuZHVGaWxlbmFtZSIsImNvbXB0ZVJlbmR1RmlsZVBhdGgiLCJjb21wdGVSZW5kdUpzb24iLCJsb2FkQXNzZW1ibGVlRGF0YUZyb21CaWdGaWxlcyIsInRvQWN0ZXVyc0V0T3JnYW5lcyIsImFjdGV1cnMiLCJvcmdhbmVzIiwidG9BZ2VuZGFzIiwicmV1bmlvbnMiLCJ0b0FtZW5kZW1lbnRzIiwidGV4dGVMZWdpc2xhdGlmIiwidGV4dGVzTGVnaXNsYXRpZnMiLCJ0b0Rvc3NpZXJzTGVnaXNsYXRpZnMiLCJkb3NzaWVyc1BhcmxlbWVudGFpcmVzIiwidG9TY3J1dGlucyIsInRvUXVlc3Rpb25zIiwiY29tcHRlc1JlbmR1cyIsInRvQ29tcHRlc1JlbmR1cyIsImxvYWRBc3NlbWJsZWVEb2N1bWVudEZpbGUiLCJmb3JtYXRzIiwiZG9jdW1lbnRzRGlyIiwiZG9jdW1lbnREaXIiLCJwYXRoRnJvbURvY3VtZW50VWlkIiwiaW5kZXhQYXRoIiwicGF0aEV4aXN0c1N5bmMiLCJpbmRleCIsInJlYWRKc29uU3luYyIsImZvcm1hdCIsInVybCIsImxvYWRBc3NlbWJsZWVQaG90b3NEZXB1dGVzIiwibG9hZEFzc2VtYmxlZVBob3Rvc1NlbmF0ZXVycyIsIm1hdGNoIiwibm90U3RyaWN0RXF1YWwiLCJncm91cHMiLCJkb2N1bWVudFR5cGUiLCJkb2N1bWVudFR5cGUyIiwiY2hhbWJyZURpciIsImNoYW1icmUiLCJjaGFtYnJlMiIsInJlcHVibGlxdWVEaXIiLCJyZXB1YmxpcXVlIiwicmVwdWJsaXF1ZTIiLCJsZWdpc2xhdHVyZURpciIsImxlZ2lzbGF0dXJlMiIsImV0YXQiLCJlbnN1cmVEaXJTeW5jIiwiZXRhdERpciIsIm51bWVybyIsIm51bWVybzIiLCJzdWJzdHJpbmciLCJudW1lcm9NaWxsaWVyc0RpciIsInBhdGhGcm9tRG9zc2llclBhcmxlbWVudGFpcmVVaWQiLCJkb3NzaWVyc0RpciIsInBhdGhGcm9tVWlkIiwicGF0aEZyb21SZXVuaW9uVWlkIiwicmV1bmlvbnNEaXIiLCJleGVjIiwic2Vzc2lvbkRpciIsImlkRGlyIiwibnVtZXJvTWlsbGlvbnNEaXIiLCJwYXRoRnJvbVNjcnV0aW5VaWQiLCJzY3J1dGluc0RpciIsInBhdGhGcm9tUXVlc3Rpb25VaWQiLCJwYXRoRnJvbUNvbXB0ZVJlbmR1VWlkIiwiZGF0YVJlZ2V4cCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2FkZXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vLyBMb2FkIGRhdGEgZnJvbSBmaWxlc1xuXG5pbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIlxuaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiXG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiXG5cbmV4cG9ydCB7IEVuYWJsZWREYXRhc2V0cyB9IGZyb20gXCIuL2RhdGFzZXRzXCJcbmltcG9ydCB7IGRhdGFzZXRzLCBFbmFibGVkRGF0YXNldHMsIERhdGFzZXQgfSBmcm9tIFwiLi9kYXRhc2V0c1wiXG5pbXBvcnQgdHlwZSB7IERvY3VtZW50RmlsZXNJbmRleCB9IGZyb20gXCIuL2Rvc3NpZXJzX2xlZ2lzbGF0aWZzXCJcbmV4cG9ydCB7IHdhbGtEaXIgfSBmcm9tIFwiLi9maWxlX3N5c3RlbXNcIlxuaW1wb3J0IHsgd2Fsa0RpciB9IGZyb20gXCIuL2ZpbGVfc3lzdGVtc1wiXG5pbXBvcnQge1xuICBBY3RldXIsXG4gIENvbnZlcnQgYXMgQWN0ZXVyc0V0T3JnYW5lc0NvbnZlcnQsXG4gIE9yZ2FuZSxcbiAgUGhvdG8sXG59IGZyb20gXCIuL3R5cGVzL2FjdGV1cnNfZXRfb3JnYW5lc1wiXG5pbXBvcnQgeyBDb252ZXJ0IGFzIEFnZW5kYXNDb252ZXJ0LCBSZXVuaW9uIH0gZnJvbSBcIi4vdHlwZXMvYWdlbmRhc1wiXG5pbXBvcnQgeyBBbWVuZGVtZW50LCBDb252ZXJ0IGFzIEFtZW5kZW1lbnRzQ29udmVydCB9IGZyb20gXCIuL3R5cGVzL2FtZW5kZW1lbnRzXCJcbmltcG9ydCB7XG4gIENvbnZlcnQgYXMgRG9zc2llcnNMZWdpc2xhdGlmc0NvbnZlcnQsXG4gIERvY3VtZW50LFxuICBEb3NzaWVyUGFybGVtZW50YWlyZSxcbn0gZnJvbSBcIi4vdHlwZXMvZG9zc2llcnNfbGVnaXNsYXRpZnNcIlxuaW1wb3J0IHsgTGVnaXNsYXR1cmUgfSBmcm9tIFwiLi90eXBlcy9sZWdpc2xhdHVyZXNcIlxuaW1wb3J0IHsgQ29udmVydCBhcyBTY3J1dGluc0NvbnZlcnQsIFNjcnV0aW4gfSBmcm9tIFwiLi90eXBlcy9zY3J1dGluc1wiXG5pbXBvcnQgeyBDb252ZXJ0IGFzIFF1ZXN0aW9uc0NvbnZlcnQsIFF1ZXN0aW9uIH0gZnJvbSBcIi4vdHlwZXMvcXVlc3Rpb25zXCJcbmltcG9ydCB7IENvbnZlcnQgYXMgQ29tcHRlc1JlbmR1c0NvbnZlcnQsIENvbXB0ZVJlbmR1IH0gZnJvbSBcIi4vdHlwZXMvZGViYXRzXCJcbmltcG9ydCB7IERvY3VtZW50VXJsRm9ybWF0IH0gZnJvbSBcIi4vdXJsc1wiXG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YSB7XG4gIHJlYWRvbmx5IGFjdGV1ckJ5VWlkOiB7IFt1aWQ6IHN0cmluZ106IEFjdGV1ciB9XG4gIHJlYWRvbmx5IGFtZW5kZW1lbnRCeVVpZDogeyBbdWlkOiBzdHJpbmddOiBBbWVuZGVtZW50IH1cbiAgcmVhZG9ubHkgZG9jdW1lbnRCeVVpZDogeyBbdWlkOiBzdHJpbmddOiBEb2N1bWVudCB9XG4gIHJlYWRvbmx5IGRvc3NpZXJQYXJsZW1lbnRhaXJlQnlTZW5hdENoZW1pbjoge1xuICAgIFt1aWQ6IHN0cmluZ106IERvc3NpZXJQYXJsZW1lbnRhaXJlXG4gIH1cbiAgcmVhZG9ubHkgZG9zc2llclBhcmxlbWVudGFpcmVCeVRpdHJlQ2hlbWluOiB7XG4gICAgW3VpZDogc3RyaW5nXTogRG9zc2llclBhcmxlbWVudGFpcmVcbiAgfVxuICByZWFkb25seSBkb3NzaWVyUGFybGVtZW50YWlyZUJ5VWlkOiB7IFt1aWQ6IHN0cmluZ106IERvc3NpZXJQYXJsZW1lbnRhaXJlIH1cbiAgcmVhZG9ubHkgb3JnYW5lQnlVaWQ6IHsgW3VpZDogc3RyaW5nXTogT3JnYW5lIH1cbiAgcmVhZG9ubHkgcGhvdG9CeVVpZDogeyBbdWlkOiBzdHJpbmddOiBQaG90byB9XG4gIHJlYWRvbmx5IHJldW5pb25CeVVpZDogeyBbdWlkOiBzdHJpbmddOiBSZXVuaW9uIH1cbiAgcmVhZG9ubHkgcmV1bmlvbnNCeURheTogeyBbZGF5OiBzdHJpbmddOiBSZXVuaW9uW10gfVxuICByZWFkb25seSByZXVuaW9uc0J5RG9zc2llclVpZDogeyBbZG9zc2llclVpZDogc3RyaW5nXTogUmV1bmlvbltdIH1cbiAgcmVhZG9ubHkgc2NydXRpbkJ5VWlkOiB7IFt1aWQ6IHN0cmluZ106IFNjcnV0aW4gfVxuICByZWFkb25seSBxdWVzdGlvbkJ5VWlkOiB7IFt1aWQ6IHN0cmluZ106IFF1ZXN0aW9uIH1cbiAgcmVhZG9ubHkgY29tcHRlUmVuZHVCeVVpZDogeyBbdWlkOiBzdHJpbmddOiBDb21wdGVSZW5kdSB9XG59XG5cbmNvbnN0IGRvY3VtZW50VWlkUmVnZXggPVxuICAvXigoPzxkb2N1bWVudFR5cGU+QUNJTnxBTENOfEFWQ0V8QVZJU3xERUNMfEVUREl8TEVUVHxNRVNTfE1JT058UElPTnxQTlJFfFBSSkx8UkFQUHxSSU5GfFJJT04pKD88Y2hhbWJyZT5BTnxDR3xTTikoPzxyZXB1YmxpcXVlPlJcXGQrKVtMU10oPzxsZWdpc2xhdHVyZT5cXGQrKSg/PGV0YXQ+QnxCVEF8QlRDfFRBUCkoPzxudW1lcm8+XFxkKykoLS4qKT8pfCgoPzxkb2N1bWVudFR5cGUyPk1JT04pKD88Y2hhbWJyZTI+QU58U04pKD88cmVwdWJsaXF1ZTI+UlxcZCspW0xTXSg/PGxlZ2lzbGF0dXJlMj5cXGQrKS1OKD88bnVtZXJvMj5cXGQrKSkkL1xuY29uc3QgZG9zc2llclVpZFJlZ2V4ID0gL15ETChSXFxkKykoTFxcZCspTihcXGQrKSQvXG5jb25zdCByZXVuaW9uVWlkUmVnZXggPVxuICAvXlJVKEFOfENHfFNOKShSXFxkKykoTFxcZCspKFtBU11cXGR7NH0pKElEQ3xJREZMP3xJRFMpKFxcZCspJC9cbmNvbnN0IHNjcnV0aW5VaWRSZWdleCA9IC9eVlQoQU58Q0cpKFJcXGQrKShMXFxkKylWKFxcZCspJC9cbmNvbnN0IGNvbXB0ZVJlbmR1VWlkUmVnZXg6IFJlZ0V4cCA9XG4gIC9eQ1JTKEFOfENHKShSXFxkKykoTFxcZCspKFNcXGQrKShPfEV8RCkoXFxkKykoTlxcZCspJC9cbmNvbnN0IHF1ZXN0aW9uVWlkUmVnZXg6IFJlZ0V4cCA9IC9eUUFOKFJcXGQrKShMXFxkKylRKEV8R3xPU0QpKFxcZCspJC9cblxudHlwZSBJdGVtQ29udmVydGVyPFQ+ID0gKGpzb246IHN0cmluZykgPT4gVFxuXG5mdW5jdGlvbiogaXRlckxvYWRBc3NlbWJsZWVJdGVtczxUIGV4dGVuZHMgeyB1aWQ6IHN0cmluZyB9PihcbiAgZGF0YURpcjogc3RyaW5nLFxuICBsZWdpc2xhdHVyZTogTGVnaXNsYXR1cmUsXG4gIGRhdGFzZXRzOiBEYXRhc2V0W10sXG4gIGNvbnZlcnRUb0l0ZW06IEl0ZW1Db252ZXJ0ZXI8VD4sXG4gIHN1YmZvbGRlck5hbWU6IHN0cmluZ1tdLFxuICBmaWxlRXh0ZW5zaW9uOiBzdHJpbmcgPSBcImpzb25cIixcbiAgeyBub1ZhbGlkYXRpb24gPSBmYWxzZSwgbG9nID0gZmFsc2UgfSA9IHt9LFxuKTogR2VuZXJhdG9yPHsgaXRlbTogVDsgZGF0YXNldExlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSB9LCB2b2lkLCB1bmtub3duPiB7XG4gIGNvbnN0IGl0ZW1VaWQgPSBuZXcgU2V0PHN0cmluZz4oKVxuICBmb3IgKGNvbnN0IGRhdGFzZXQgb2YgZGF0YXNldHMpIHtcbiAgICBpZiAoZGF0YXNldC5pZ25vcmVGb3JXZWIpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmIChcbiAgICAgIGxlZ2lzbGF0dXJlICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIGxlZ2lzbGF0dXJlICE9PSBMZWdpc2xhdHVyZS5BbGwgJiZcbiAgICAgIGRhdGFzZXQubGVnaXNsYXR1cmUgIT09IExlZ2lzbGF0dXJlLkFsbCAmJlxuICAgICAgbGVnaXNsYXR1cmUgIT09IGRhdGFzZXQubGVnaXNsYXR1cmVcbiAgICApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGxldCBmaWxlRXh0ZW5zaW9uUmVnZXggPSBuZXcgUmVnRXhwKGBcXFxcLiR7ZmlsZUV4dGVuc2lvbn0kYClcbiAgICBjb25zdCBkYXRhc2V0RGlyID0gcGF0aC5qb2luKFxuICAgICAgZGF0YURpcixcbiAgICAgIGRhdGFzZXQuZmlsZW5hbWUucmVwbGFjZShmaWxlRXh0ZW5zaW9uUmVnZXgsIFwiX25ldHRveWVcIiksXG4gICAgKVxuXG4gICAgZm9yIChjb25zdCBpdGVtU3BsaXRQYXRoIG9mIHdhbGtEaXIoZGF0YXNldERpciwgc3ViZm9sZGVyTmFtZSkpIHtcbiAgICAgIGNvbnN0IGl0ZW1GaWxlbmFtZSA9IGl0ZW1TcGxpdFBhdGhbaXRlbVNwbGl0UGF0aC5sZW5ndGggLSAxXVxuICAgICAgaWYgKCFpdGVtRmlsZW5hbWUuZW5kc1dpdGgoXCIuanNvblwiKSkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgY29uc3QgaXRlbUZpbGVQYXRoID0gcGF0aC5qb2luKGRhdGFzZXREaXIsIC4uLml0ZW1TcGxpdFBhdGgpXG4gICAgICBpZiAobG9nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBMb2FkaW5nIGZpbGU6ICR7aXRlbUZpbGVQYXRofeKApmApXG4gICAgICB9XG5cbiAgICAgIGxldCBpdGVtSnNvbjogYW55ID0gZnMucmVhZEZpbGVTeW5jKGl0ZW1GaWxlUGF0aCwgeyBlbmNvZGluZzogXCJ1dGY4XCIgfSlcbiAgICAgIGxldCBpdGVtOiBUID0gbm9WYWxpZGF0aW9uXG4gICAgICAgID8gSlNPTi5wYXJzZShpdGVtSnNvbilcbiAgICAgICAgOiBjb252ZXJ0VG9JdGVtKGl0ZW1Kc29uKVxuXG4gICAgICBpZiAoaXRlbVVpZC5oYXMoaXRlbS51aWQpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBpdGVtVWlkLmFkZChpdGVtLnVpZClcbiAgICAgIHlpZWxkIHsgaXRlbTogaXRlbSwgZGF0YXNldExlZ2lzbGF0dXJlOiBkYXRhc2V0LmxlZ2lzbGF0dXJlIH1cblxuICAgICAgaXRlbUpzb24gPSBudWxsXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiogaXRlckxvYWRBc3NlbWJsZWVBY3RldXJzKFxuICBkYXRhRGlyOiBzdHJpbmcsXG4gIGxlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSxcbiAgb3B0aW9ucyA9IHt9LFxuKTogR2VuZXJhdG9yPFxuICB7IGFjdGV1cjogQWN0ZXVyOyBkYXRhc2V0TGVnaXNsYXR1cmU6IExlZ2lzbGF0dXJlIH0sXG4gIHZvaWQsXG4gIHVua25vd25cbj4ge1xuICBmb3IgKGNvbnN0IHtcbiAgICBpdGVtOiBhY3RldXIsXG4gICAgZGF0YXNldExlZ2lzbGF0dXJlLFxuICB9IG9mIGl0ZXJMb2FkQXNzZW1ibGVlSXRlbXM8QWN0ZXVyPihcbiAgICBkYXRhRGlyLFxuICAgIGxlZ2lzbGF0dXJlLFxuICAgIGRhdGFzZXRzLmFjdGV1cnNFdE9yZ2FuZXMsXG4gICAgQWN0ZXVyc0V0T3JnYW5lc0NvbnZlcnQudG9BY3RldXIsXG4gICAgW1wiYWN0ZXVyc1wiXSxcbiAgICBcImpzb25cIixcbiAgICBvcHRpb25zLFxuICApKSB7XG4gICAgeWllbGQgeyBhY3RldXIsIGRhdGFzZXRMZWdpc2xhdHVyZSB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBpdGVyTG9hZEFzc2VtYmxlZU9yZ2FuZXMoXG4gIGRhdGFEaXI6IHN0cmluZyxcbiAgbGVnaXNsYXR1cmU6IExlZ2lzbGF0dXJlLFxuICBvcHRpb25zID0ge30sXG4pOiBHZW5lcmF0b3I8XG4gIHsgb3JnYW5lOiBPcmdhbmU7IGRhdGFzZXRMZWdpc2xhdHVyZTogTGVnaXNsYXR1cmUgfSxcbiAgdm9pZCxcbiAgdW5rbm93blxuPiB7XG4gIGZvciAoY29uc3Qge1xuICAgIGl0ZW06IG9yZ2FuZSxcbiAgICBkYXRhc2V0TGVnaXNsYXR1cmUsXG4gIH0gb2YgaXRlckxvYWRBc3NlbWJsZWVJdGVtczxPcmdhbmU+KFxuICAgIGRhdGFEaXIsXG4gICAgbGVnaXNsYXR1cmUsXG4gICAgZGF0YXNldHMuYWN0ZXVyc0V0T3JnYW5lcyxcbiAgICBBY3RldXJzRXRPcmdhbmVzQ29udmVydC50b09yZ2FuZSxcbiAgICBbXCJvcmdhbmVzXCJdLFxuICAgIFwianNvblwiLFxuICAgIG9wdGlvbnMsXG4gICkpIHtcbiAgICB5aWVsZCB7IG9yZ2FuZSwgZGF0YXNldExlZ2lzbGF0dXJlIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIGl0ZXJMb2FkQXNzZW1ibGVlQW1lbmRlbWVudHMoXG4gIGRhdGFEaXI6IHN0cmluZyxcbiAgbGVnaXNsYXR1cmU6IExlZ2lzbGF0dXJlLFxuICBvcHRpb25zID0ge30sXG4pOiBHZW5lcmF0b3I8XG4gIHsgYW1lbmRlbWVudDogQW1lbmRlbWVudDsgZGF0YXNldExlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSB9LFxuICB2b2lkLFxuICB1bmtub3duXG4+IHtcbiAgZm9yIChjb25zdCB7XG4gICAgaXRlbTogYW1lbmRlbWVudCxcbiAgICBkYXRhc2V0TGVnaXNsYXR1cmUsXG4gIH0gb2YgaXRlckxvYWRBc3NlbWJsZWVJdGVtczxBbWVuZGVtZW50PihcbiAgICBkYXRhRGlyLFxuICAgIGxlZ2lzbGF0dXJlLFxuICAgIGRhdGFzZXRzLmFtZW5kZW1lbnRzLFxuICAgIEFtZW5kZW1lbnRzQ29udmVydC50b0FtZW5kZW1lbnQsXG4gICAgW10sXG4gICAgXCJqc29uXCIsXG4gICAgb3B0aW9ucyxcbiAgKSkge1xuICAgIHlpZWxkIHsgYW1lbmRlbWVudCwgZGF0YXNldExlZ2lzbGF0dXJlIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIGl0ZXJMb2FkQXNzZW1ibGVlRG9jdW1lbnRzKFxuICBkYXRhRGlyOiBzdHJpbmcsXG4gIGxlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSxcbiAgb3B0aW9ucyA9IHt9LFxuKTogR2VuZXJhdG9yPFxuICB7IGRvY3VtZW50OiBEb2N1bWVudDsgZGF0YXNldExlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSB9LFxuICB2b2lkLFxuICB1bmtub3duXG4+IHtcbiAgZm9yIChjb25zdCB7XG4gICAgaXRlbTogZG9jdW1lbnQsXG4gICAgZGF0YXNldExlZ2lzbGF0dXJlLFxuICB9IG9mIGl0ZXJMb2FkQXNzZW1ibGVlSXRlbXM8RG9jdW1lbnQ+KFxuICAgIGRhdGFEaXIsXG4gICAgbGVnaXNsYXR1cmUsXG4gICAgZGF0YXNldHMuZG9zc2llcnNMZWdpc2xhdGlmcyxcbiAgICBEb3NzaWVyc0xlZ2lzbGF0aWZzQ29udmVydC50b0RvY3VtZW50LFxuICAgIFtcImRvY3VtZW50c1wiXSxcbiAgICBcImpzb25cIixcbiAgICBvcHRpb25zLFxuICApKSB7XG4gICAgeWllbGQgeyBkb2N1bWVudCwgZGF0YXNldExlZ2lzbGF0dXJlIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIGl0ZXJMb2FkQXNzZW1ibGVlRG9zc2llcnNQYXJsZW1lbnRhaXJlcyhcbiAgZGF0YURpcjogc3RyaW5nLFxuICBsZWdpc2xhdHVyZTogTGVnaXNsYXR1cmUsXG4gIG9wdGlvbnMgPSB7fSxcbik6IEdlbmVyYXRvcjxcbiAge1xuICAgIGRvc3NpZXJQYXJsZW1lbnRhaXJlOiBEb3NzaWVyUGFybGVtZW50YWlyZVxuICAgIGRhdGFzZXRMZWdpc2xhdHVyZTogTGVnaXNsYXR1cmVcbiAgfSxcbiAgdm9pZCxcbiAgdW5rbm93blxuPiB7XG4gIGZvciAoY29uc3Qge1xuICAgIGl0ZW06IGRvc3NpZXJQYXJsZW1lbnRhaXJlLFxuICAgIGRhdGFzZXRMZWdpc2xhdHVyZSxcbiAgfSBvZiBpdGVyTG9hZEFzc2VtYmxlZUl0ZW1zPERvc3NpZXJQYXJsZW1lbnRhaXJlPihcbiAgICBkYXRhRGlyLFxuICAgIGxlZ2lzbGF0dXJlLFxuICAgIGRhdGFzZXRzLmRvc3NpZXJzTGVnaXNsYXRpZnMsXG4gICAgRG9zc2llcnNMZWdpc2xhdGlmc0NvbnZlcnQudG9Eb3NzaWVyUGFybGVtZW50YWlyZSxcbiAgICBbXCJkb3NzaWVyc1wiXSxcbiAgICBcImpzb25cIixcbiAgICBvcHRpb25zLFxuICApKSB7XG4gICAgeWllbGQgeyBkb3NzaWVyUGFybGVtZW50YWlyZSwgZGF0YXNldExlZ2lzbGF0dXJlIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIGl0ZXJMb2FkQXNzZW1ibGVlUmV1bmlvbnMoXG4gIGRhdGFEaXI6IHN0cmluZyxcbiAgbGVnaXNsYXR1cmU6IExlZ2lzbGF0dXJlLFxuICBvcHRpb25zID0ge30sXG4pOiBHZW5lcmF0b3I8XG4gIHsgcmV1bmlvbjogUmV1bmlvbjsgZGF0YXNldExlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSB9LFxuICB2b2lkLFxuICB1bmtub3duXG4+IHtcbiAgZm9yIChjb25zdCB7XG4gICAgaXRlbTogcmV1bmlvbixcbiAgICBkYXRhc2V0TGVnaXNsYXR1cmUsXG4gIH0gb2YgaXRlckxvYWRBc3NlbWJsZWVJdGVtczxSZXVuaW9uPihcbiAgICBkYXRhRGlyLFxuICAgIGxlZ2lzbGF0dXJlLFxuICAgIGRhdGFzZXRzLmFnZW5kYXMsXG4gICAgQWdlbmRhc0NvbnZlcnQudG9SZXVuaW9uLFxuICAgIFtdLFxuICAgIFwianNvblwiLFxuICAgIG9wdGlvbnMsXG4gICkpIHtcbiAgICB5aWVsZCB7IHJldW5pb24sIGRhdGFzZXRMZWdpc2xhdHVyZSB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBpdGVyTG9hZEFzc2VtYmxlZVNjcnV0aW5zKFxuICBkYXRhRGlyOiBzdHJpbmcsXG4gIGxlZ2lzbGF0dXJlOiBMZWdpc2xhdHVyZSxcbiAgb3B0aW9ucyA9IHt9LFxuKTogR2VuZXJhdG9yPFxuICB7IHNjcnV0aW46IFNjcnV0aW47IGRhdGFzZXRMZWdpc2xhdHVyZTogTGVnaXNsYXR1cmUgfSxcbiAgdm9pZCxcbiAgdW5rbm93blxuPiB7XG4gIGZvciAoY29uc3Qge1xuICAgIGl0ZW06IHNjcnV0aW4sXG4gICAgZGF0YXNldExlZ2lzbGF0dXJlLFxuICB9IG9mIGl0ZXJMb2FkQXNzZW1ibGVlSXRlbXM8U2NydXRpbj4oXG4gICAgZGF0YURpcixcbiAgICBsZWdpc2xhdHVyZSxcbiAgICBkYXRhc2V0cy5zY3J1dGlucyxcbiAgICBTY3J1dGluc0NvbnZlcnQudG9TY3J1dGluLFxuICAgIFtdLFxuICAgIFwianNvblwiLFxuICAgIG9wdGlvbnMsXG4gICkpIHtcbiAgICB5aWVsZCB7IHNjcnV0aW4sIGRhdGFzZXRMZWdpc2xhdHVyZSB9XG4gIH1cbn1cblxuZXhwb