@tricoteuses/senat 2.22.5 → 2.22.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/lib/src/model/ameli.d.ts +4 -0
  2. package/lib/src/model/ameli.js +3 -3
  3. package/package.json +1 -1
  4. package/lib/aggregates.d.ts +0 -52
  5. package/lib/aggregates.js +0 -930
  6. package/lib/aggregates.mjs +0 -713
  7. package/lib/aggregates.ts +0 -833
  8. package/lib/config.d.ts +0 -10
  9. package/lib/config.js +0 -16
  10. package/lib/config.mjs +0 -16
  11. package/lib/config.ts +0 -26
  12. package/lib/databases.d.ts +0 -2
  13. package/lib/databases.js +0 -26
  14. package/lib/databases.mjs +0 -57
  15. package/lib/databases.ts +0 -71
  16. package/lib/datasets.d.ts +0 -34
  17. package/lib/datasets.js +0 -233
  18. package/lib/datasets.mjs +0 -78
  19. package/lib/datasets.ts +0 -118
  20. package/lib/fields.d.ts +0 -10
  21. package/lib/fields.js +0 -68
  22. package/lib/fields.mjs +0 -22
  23. package/lib/fields.ts +0 -29
  24. package/lib/git.d.ts +0 -26
  25. package/lib/git.js +0 -167
  26. package/lib/index.d.ts +0 -13
  27. package/lib/index.js +0 -1
  28. package/lib/index.mjs +0 -7
  29. package/lib/index.ts +0 -64
  30. package/lib/inserters.d.ts +0 -98
  31. package/lib/inserters.js +0 -500
  32. package/lib/inserters.mjs +0 -360
  33. package/lib/inserters.ts +0 -521
  34. package/lib/legislatures.json +0 -38
  35. package/lib/loaders.d.ts +0 -58
  36. package/lib/loaders.js +0 -286
  37. package/lib/loaders.mjs +0 -158
  38. package/lib/loaders.ts +0 -271
  39. package/lib/model/agenda.d.ts +0 -6
  40. package/lib/model/agenda.js +0 -148
  41. package/lib/model/ameli.d.ts +0 -51
  42. package/lib/model/ameli.js +0 -149
  43. package/lib/model/ameli.mjs +0 -84
  44. package/lib/model/ameli.ts +0 -100
  45. package/lib/model/commission.d.ts +0 -18
  46. package/lib/model/commission.js +0 -269
  47. package/lib/model/debats.d.ts +0 -67
  48. package/lib/model/debats.js +0 -95
  49. package/lib/model/debats.mjs +0 -43
  50. package/lib/model/debats.ts +0 -68
  51. package/lib/model/documents.d.ts +0 -12
  52. package/lib/model/documents.js +0 -151
  53. package/lib/model/dosleg.d.ts +0 -7
  54. package/lib/model/dosleg.js +0 -326
  55. package/lib/model/dosleg.mjs +0 -196
  56. package/lib/model/dosleg.ts +0 -240
  57. package/lib/model/index.d.ts +0 -7
  58. package/lib/model/index.js +0 -7
  59. package/lib/model/index.mjs +0 -5
  60. package/lib/model/index.ts +0 -15
  61. package/lib/model/questions.d.ts +0 -45
  62. package/lib/model/questions.js +0 -89
  63. package/lib/model/questions.mjs +0 -71
  64. package/lib/model/questions.ts +0 -93
  65. package/lib/model/scrutins.d.ts +0 -13
  66. package/lib/model/scrutins.js +0 -114
  67. package/lib/model/seance.d.ts +0 -3
  68. package/lib/model/seance.js +0 -267
  69. package/lib/model/sens.d.ts +0 -146
  70. package/lib/model/sens.js +0 -454
  71. package/lib/model/sens.mjs +0 -415
  72. package/lib/model/sens.ts +0 -516
  73. package/lib/model/texte.d.ts +0 -7
  74. package/lib/model/texte.js +0 -256
  75. package/lib/model/texte.mjs +0 -208
  76. package/lib/model/texte.ts +0 -229
  77. package/lib/model/util.d.ts +0 -9
  78. package/lib/model/util.js +0 -38
  79. package/lib/model/util.mjs +0 -19
  80. package/lib/model/util.ts +0 -32
  81. package/lib/parsers/texte.d.ts +0 -7
  82. package/lib/parsers/texte.js +0 -228
  83. package/lib/raw_types/ameli.d.ts +0 -914
  84. package/lib/raw_types/ameli.js +0 -5
  85. package/lib/raw_types/ameli.mjs +0 -163
  86. package/lib/raw_types/debats.d.ts +0 -207
  87. package/lib/raw_types/debats.js +0 -5
  88. package/lib/raw_types/debats.mjs +0 -58
  89. package/lib/raw_types/dosleg.d.ts +0 -1619
  90. package/lib/raw_types/dosleg.js +0 -5
  91. package/lib/raw_types/dosleg.mjs +0 -438
  92. package/lib/raw_types/questions.d.ts +0 -419
  93. package/lib/raw_types/questions.js +0 -5
  94. package/lib/raw_types/questions.mjs +0 -11
  95. package/lib/raw_types/senat.d.ts +0 -11368
  96. package/lib/raw_types/senat.js +0 -5
  97. package/lib/raw_types/sens.d.ts +0 -8248
  98. package/lib/raw_types/sens.js +0 -5
  99. package/lib/raw_types/sens.mjs +0 -508
  100. package/lib/raw_types_kysely/ameli.d.ts +0 -915
  101. package/lib/raw_types_kysely/ameli.js +0 -7
  102. package/lib/raw_types_kysely/ameli.mjs +0 -5
  103. package/lib/raw_types_kysely/ameli.ts +0 -951
  104. package/lib/raw_types_kysely/debats.d.ts +0 -207
  105. package/lib/raw_types_kysely/debats.js +0 -7
  106. package/lib/raw_types_kysely/debats.mjs +0 -5
  107. package/lib/raw_types_kysely/debats.ts +0 -222
  108. package/lib/raw_types_kysely/dosleg.d.ts +0 -3532
  109. package/lib/raw_types_kysely/dosleg.js +0 -7
  110. package/lib/raw_types_kysely/dosleg.mjs +0 -5
  111. package/lib/raw_types_kysely/dosleg.ts +0 -3621
  112. package/lib/raw_types_kysely/questions.d.ts +0 -414
  113. package/lib/raw_types_kysely/questions.js +0 -7
  114. package/lib/raw_types_kysely/questions.mjs +0 -5
  115. package/lib/raw_types_kysely/questions.ts +0 -426
  116. package/lib/raw_types_kysely/sens.d.ts +0 -4394
  117. package/lib/raw_types_kysely/sens.js +0 -7
  118. package/lib/raw_types_kysely/sens.mjs +0 -5
  119. package/lib/raw_types_kysely/sens.ts +0 -4499
  120. package/lib/raw_types_schemats/ameli.d.ts +0 -539
  121. package/lib/raw_types_schemats/ameli.js +0 -2
  122. package/lib/raw_types_schemats/ameli.mjs +0 -2
  123. package/lib/raw_types_schemats/ameli.ts +0 -601
  124. package/lib/raw_types_schemats/debats.d.ts +0 -127
  125. package/lib/raw_types_schemats/debats.js +0 -2
  126. package/lib/raw_types_schemats/debats.mjs +0 -2
  127. package/lib/raw_types_schemats/debats.ts +0 -145
  128. package/lib/raw_types_schemats/dosleg.d.ts +0 -977
  129. package/lib/raw_types_schemats/dosleg.js +0 -2
  130. package/lib/raw_types_schemats/dosleg.mjs +0 -2
  131. package/lib/raw_types_schemats/dosleg.ts +0 -2193
  132. package/lib/raw_types_schemats/questions.d.ts +0 -235
  133. package/lib/raw_types_schemats/questions.js +0 -2
  134. package/lib/raw_types_schemats/questions.mjs +0 -2
  135. package/lib/raw_types_schemats/questions.ts +0 -249
  136. package/lib/raw_types_schemats/sens.d.ts +0 -6915
  137. package/lib/raw_types_schemats/sens.js +0 -2
  138. package/lib/raw_types_schemats/sens.mjs +0 -2
  139. package/lib/raw_types_schemats/sens.ts +0 -2907
  140. package/lib/scripts/convert_data.d.ts +0 -1
  141. package/lib/scripts/convert_data.js +0 -354
  142. package/lib/scripts/convert_data.mjs +0 -181
  143. package/lib/scripts/convert_data.ts +0 -243
  144. package/lib/scripts/data-download.d.ts +0 -1
  145. package/lib/scripts/data-download.js +0 -12
  146. package/lib/scripts/datautil.d.ts +0 -8
  147. package/lib/scripts/datautil.js +0 -34
  148. package/lib/scripts/datautil.mjs +0 -16
  149. package/lib/scripts/datautil.ts +0 -19
  150. package/lib/scripts/images/transparent_150x192.jpg +0 -0
  151. package/lib/scripts/images/transparent_155x225.jpg +0 -0
  152. package/lib/scripts/parse_textes.d.ts +0 -1
  153. package/lib/scripts/parse_textes.js +0 -44
  154. package/lib/scripts/parse_textes.mjs +0 -46
  155. package/lib/scripts/parse_textes.ts +0 -65
  156. package/lib/scripts/retrieve_agenda.d.ts +0 -1
  157. package/lib/scripts/retrieve_agenda.js +0 -132
  158. package/lib/scripts/retrieve_cr_commission.d.ts +0 -1
  159. package/lib/scripts/retrieve_cr_commission.js +0 -364
  160. package/lib/scripts/retrieve_cr_seance.d.ts +0 -6
  161. package/lib/scripts/retrieve_cr_seance.js +0 -347
  162. package/lib/scripts/retrieve_documents.d.ts +0 -3
  163. package/lib/scripts/retrieve_documents.js +0 -219
  164. package/lib/scripts/retrieve_documents.mjs +0 -249
  165. package/lib/scripts/retrieve_documents.ts +0 -298
  166. package/lib/scripts/retrieve_open_data.d.ts +0 -1
  167. package/lib/scripts/retrieve_open_data.js +0 -315
  168. package/lib/scripts/retrieve_open_data.mjs +0 -217
  169. package/lib/scripts/retrieve_open_data.ts +0 -268
  170. package/lib/scripts/retrieve_senateurs_photos.d.ts +0 -1
  171. package/lib/scripts/retrieve_senateurs_photos.js +0 -147
  172. package/lib/scripts/retrieve_senateurs_photos.mjs +0 -147
  173. package/lib/scripts/retrieve_senateurs_photos.ts +0 -177
  174. package/lib/scripts/retrieve_videos.d.ts +0 -1
  175. package/lib/scripts/retrieve_videos.js +0 -461
  176. package/lib/scripts/shared/cli_helpers.d.ts +0 -95
  177. package/lib/scripts/shared/cli_helpers.js +0 -91
  178. package/lib/scripts/shared/cli_helpers.ts +0 -36
  179. package/lib/scripts/shared/util.d.ts +0 -4
  180. package/lib/scripts/shared/util.js +0 -35
  181. package/lib/scripts/shared/util.ts +0 -33
  182. package/lib/scripts/test_iter_load.d.ts +0 -1
  183. package/lib/scripts/test_iter_load.js +0 -12
  184. package/lib/strings.d.ts +0 -1
  185. package/lib/strings.js +0 -18
  186. package/lib/strings.mjs +0 -18
  187. package/lib/strings.ts +0 -26
  188. package/lib/types/agenda.d.ts +0 -44
  189. package/lib/types/agenda.js +0 -1
  190. package/lib/types/ameli.d.ts +0 -5
  191. package/lib/types/ameli.js +0 -1
  192. package/lib/types/ameli.mjs +0 -13
  193. package/lib/types/ameli.ts +0 -21
  194. package/lib/types/compte_rendu.d.ts +0 -83
  195. package/lib/types/compte_rendu.js +0 -1
  196. package/lib/types/debats.d.ts +0 -2
  197. package/lib/types/debats.js +0 -1
  198. package/lib/types/debats.mjs +0 -2
  199. package/lib/types/debats.ts +0 -6
  200. package/lib/types/dosleg.d.ts +0 -70
  201. package/lib/types/dosleg.js +0 -1
  202. package/lib/types/dosleg.mjs +0 -151
  203. package/lib/types/dosleg.ts +0 -284
  204. package/lib/types/questions.d.ts +0 -2
  205. package/lib/types/questions.js +0 -1
  206. package/lib/types/questions.mjs +0 -1
  207. package/lib/types/questions.ts +0 -3
  208. package/lib/types/sens.d.ts +0 -10
  209. package/lib/types/sens.js +0 -1
  210. package/lib/types/sens.mjs +0 -1
  211. package/lib/types/sens.ts +0 -12
  212. package/lib/types/sessions.d.ts +0 -5
  213. package/lib/types/sessions.js +0 -84
  214. package/lib/types/sessions.mjs +0 -43
  215. package/lib/types/sessions.ts +0 -42
  216. package/lib/types/texte.d.ts +0 -74
  217. package/lib/types/texte.js +0 -16
  218. package/lib/types/texte.mjs +0 -16
  219. package/lib/types/texte.ts +0 -76
  220. package/lib/typings/windows-1252.d.js +0 -2
  221. package/lib/typings/windows-1252.d.mjs +0 -2
  222. package/lib/typings/windows-1252.d.ts +0 -11
  223. package/lib/utils/cr_spliting.d.ts +0 -28
  224. package/lib/utils/cr_spliting.js +0 -265
  225. package/lib/utils/date.d.ts +0 -10
  226. package/lib/utils/date.js +0 -100
  227. package/lib/utils/nvs-timecode.d.ts +0 -7
  228. package/lib/utils/nvs-timecode.js +0 -79
  229. package/lib/utils/reunion_grouping.d.ts +0 -9
  230. package/lib/utils/reunion_grouping.js +0 -361
  231. package/lib/utils/reunion_odj_building.d.ts +0 -5
  232. package/lib/utils/reunion_odj_building.js +0 -154
  233. package/lib/utils/reunion_parsing.d.ts +0 -23
  234. package/lib/utils/reunion_parsing.js +0 -209
  235. package/lib/utils/scoring.d.ts +0 -14
  236. package/lib/utils/scoring.js +0 -147
  237. package/lib/utils/string_cleaning.d.ts +0 -7
  238. package/lib/utils/string_cleaning.js +0 -57
  239. package/lib/validators/config.d.ts +0 -9
  240. package/lib/validators/config.js +0 -10
  241. package/lib/validators/config.mjs +0 -54
  242. package/lib/validators/config.ts +0 -79
  243. package/lib/validators/senat.d.ts +0 -0
  244. package/lib/validators/senat.js +0 -28
  245. package/lib/validators/senat.mjs +0 -24
  246. package/lib/validators/senat.ts +0 -26
@@ -1,209 +0,0 @@
1
- import { DateTime } from "luxon";
2
- import { buildOdj } from "./reunion_odj_building";
3
- import { norm } from "./string_cleaning";
4
- const PARIS = "Europe/Paris";
5
- const STOPWORDS = new Set([
6
- "de",
7
- "du",
8
- "des",
9
- "la",
10
- "le",
11
- "les",
12
- "l",
13
- "d",
14
- "et",
15
- "en",
16
- "au",
17
- "aux",
18
- "pour",
19
- "sur",
20
- "sous",
21
- "à",
22
- "a",
23
- "aux",
24
- ]);
25
- function toReunion(e, dossierBySenatUrl, uid) {
26
- const date = norm(e.date) ?? e.date;
27
- const { startISO, endISO } = deriveTimesForEvent(e);
28
- const startTime = startISO ?? e.startTime ?? null;
29
- const endTime = endISO ?? e.endTime ?? null;
30
- return {
31
- uid,
32
- chambre: "SN",
33
- date,
34
- type: e.type || "",
35
- organe: e.organe || undefined,
36
- startTime,
37
- endTime,
38
- captationVideo: e.captationVideo === true,
39
- titre: e.titre,
40
- objet: e.objet || "",
41
- events: [e], // TODO remove
42
- odj: buildOdj([e], dossierBySenatUrl),
43
- };
44
- }
45
- export function buildReunionsByBucket(events, dossierBySenatUrl) {
46
- const out = { IDS: [], IDC: [], IDM: [], IDO: [], IDI: [] };
47
- if (!events?.length)
48
- return out;
49
- for (const e of events) {
50
- const kind = classifyAgendaType(e?.type);
51
- if (!kind) {
52
- continue;
53
- console.warn("Can't determine type of reunion");
54
- }
55
- const bucket = typeToSuffixStrict(kind);
56
- const uid = makeReunionUid(e.date, kind, e.id, e.organe ?? null);
57
- out[bucket].push(toReunion(e, dossierBySenatUrl, uid));
58
- }
59
- // Tri stable par bucket (date + heure, inconnus à la fin)
60
- for (const k of Object.keys(out)) {
61
- out[k].sort((a, b) => {
62
- const da = DateTime.fromISO(`${a.date}T${a.startTime || "23:59:59.999+02:00"}`, { zone: PARIS }).toMillis();
63
- const db = DateTime.fromISO(`${b.date}T${b.startTime || "23:59:59.999+02:00"}`, { zone: PARIS }).toMillis();
64
- return da - db || (a.organe || "").localeCompare(b.organe || "") || (a.titre || "").localeCompare(b.titre || "");
65
- });
66
- }
67
- return out;
68
- }
69
- function normalizeNoAccents(s) {
70
- return (s || "")
71
- .trim()
72
- .normalize("NFKD")
73
- .replace(/[\u0300-\u036f]/g, "");
74
- }
75
- function classifyAgendaType(typeLabel) {
76
- const s = normalizeNoAccents(typeLabel || "").toLowerCase();
77
- if (/\bseance\b.*\bpublique\b/.test(s))
78
- return "SP";
79
- if (/\bcommissions\b/.test(s))
80
- return "COM";
81
- if (/\bmission\b.*\bcontrole\b/.test(s))
82
- return "MC";
83
- if (/\boffices\b|\bdelegations\b/.test(s))
84
- return "OD";
85
- if (/\instances\b|\decisionelles\b/.test(s))
86
- return "ID";
87
- return null;
88
- }
89
- function typeToSuffixStrict(kind) {
90
- switch (kind) {
91
- case "SP":
92
- return "IDS";
93
- case "COM":
94
- return "IDC";
95
- case "MC":
96
- return "IDM";
97
- case "OD":
98
- return "IDO";
99
- case "ID":
100
- return "IDI";
101
- }
102
- }
103
- function organeInitials(input, maxLen = 8) {
104
- if (!input)
105
- return "";
106
- const clean = normalizeNoAccents(input)
107
- .replace(/['’]/g, " ")
108
- .replace(/[^A-Za-z0-9\s]/g, " ")
109
- .replace(/\s+/g, " ")
110
- .trim();
111
- if (!clean)
112
- return "";
113
- const parts = clean.split(" ");
114
- const letters = [];
115
- for (const raw of parts) {
116
- const w = raw.toLowerCase();
117
- if (!w)
118
- continue;
119
- if (STOPWORDS.has(w))
120
- continue;
121
- // Take two first letter if alphanumeric
122
- const two = raw.slice(0, 2);
123
- if (/[A-Za-z0-9]/.test(two))
124
- letters.push(two.toUpperCase());
125
- }
126
- const out = letters.join("");
127
- return out.slice(0, maxLen);
128
- }
129
- export function makeReunionUid(dateISO, kind, agendaEventId, organe) {
130
- const ymd = dateISO ? formatYYYYMMDD(dateISO) : "00000000";
131
- const suffix = typeToSuffixStrict(kind);
132
- const org = organe && suffix !== "IDS" ? organeInitials(organe) : "";
133
- let base = `RUSN${ymd}${suffix}${org}${agendaEventId}`;
134
- return base;
135
- }
136
- export function formatYYYYMMDD(dateYYYYMMDD) {
137
- const [y, m, d] = dateYYYYMMDD.split("-");
138
- return `${y}${m}${d}`;
139
- }
140
- // Extract hours/minutes from French text like "à 10 h 30", "de 10 h à 12 h", etc.
141
- function parseTimeOriginalFR(timeOriginal) {
142
- if (!timeOriginal)
143
- return { start: null, end: null };
144
- const txt = (timeOriginal || "")
145
- .replace(/\u00A0/g, " ") // nbsp → space
146
- .replace(/\s+/g, " ") // espaces multiples
147
- .toLowerCase()
148
- .trim();
149
- // 1) "de 10 h 30 à 12 heures", "de 10h30 à 12h", "de 9 h à 11 h 15", etc.
150
- const reRange = /\bde\s+(\d{1,2})\s*(?:h|:)?\s*(\d{1,2})?\s*(?:heures?)?\s*à\s*(\d{1,2})\s*(?:h|:)?\s*(\d{1,2})?\s*(?:heures?)?/i;
151
- const mRange = txt.match(reRange);
152
- if (mRange) {
153
- const h1 = clampHour(+mRange[1]), m1 = clampMinute(mRange[2] ? +mRange[2] : 0);
154
- const h2 = clampHour(+mRange[3]), m2 = clampMinute(mRange[4] ? +mRange[4] : 0);
155
- return { start: toIsoTime(h1, m1), end: toIsoTime(h2, m2) };
156
- }
157
- // 2) "à 10 h 30", "à 10h", "A 10h30", "A 9 heures", etc.
158
- const reAt = /\b(?:a|à)\s*(\d{1,2})\s*(?:h|:)?\s*(\d{1,2})?\s*(?:heures?)?/i;
159
- const mAt = txt.match(reAt);
160
- if (mAt) {
161
- const h = clampHour(+mAt[1]), m = clampMinute(mAt[2] ? +mAt[2] : 0);
162
- return { start: toIsoTime(h, m), end: null };
163
- }
164
- // 3) "10 h 30", "15h", "9 heures" sans 'à' / 'de ... à ...'
165
- const reBare = /\b(\d{1,2})\s*(?:h|:)?\s*(\d{1,2})?\s*(?:heures?)?\b/;
166
- const mBare = txt.match(reBare);
167
- if (mBare) {
168
- const h = clampHour(+mBare[1]), m = clampMinute(mBare[2] ? +mBare[2] : 0);
169
- return { start: toIsoTime(h, m), end: null };
170
- }
171
- return { start: null, end: null };
172
- }
173
- function clampHour(h) {
174
- return Math.max(0, Math.min(23, h));
175
- }
176
- function clampMinute(m) {
177
- return Math.max(0, Math.min(59, m));
178
- }
179
- function toIsoTime(h, m) {
180
- return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:00.000+02:00`;
181
- }
182
- export function deriveTimesForEvent(ev) {
183
- const directStart = ev.startTime ?? null;
184
- const directEnd = ev.endTime ?? null;
185
- const fromText = parseTimeOriginalFR(ev.timeOriginal);
186
- const startISO = directStart ?? fromText.start ?? null;
187
- const endISO = directEnd ?? fromText.end ?? null;
188
- return { startISO, endISO };
189
- }
190
- export function extractSommaireBlocks($, idx) {
191
- const blocks = [];
192
- // lignes du sommaire avec lien
193
- $("cri\\:tm5 a[href^='#'], cri\\:tm3 a[href^='#'], p.tm5 a[href^='#'], p.tm3 a[href^='#']").each((_, a) => {
194
- const href = $(a).attr("href") || "";
195
- const targetId = href.startsWith("#") ? href.slice(1) : null;
196
- const text = norm($(a).text() || "");
197
- const startIndex = idx.get(a) ?? idx.get($(a).closest("p")[0]) ?? null;
198
- if (!text || startIndex == null)
199
- return;
200
- blocks.push({ text, startIndex, targetId });
201
- });
202
- return blocks;
203
- }
204
- export function parseISO(iso) {
205
- if (!iso)
206
- return null;
207
- const dt = DateTime.fromISO(iso, { setZone: true, zone: PARIS });
208
- return dt.isValid ? dt : null;
209
- }
@@ -1,14 +0,0 @@
1
- import { AgendaEvent, Reunion } from "../types/agenda";
2
- export declare function jaccard(a: Set<string>, b: Set<string>): number;
3
- export declare function jaccardTokenSim(a: string, b: string): number;
4
- export declare function isNoiseBlock(text: string): boolean;
5
- /**
6
- * Score robuste pour "bloc court vs event long":
7
- * - coverageBloc = |A∩B| / |A| (critère principal)
8
- * - jaccard en secondaire (utile quand les 2 sont longs)
9
- * - bonus time optionnel (déjà chez toi)
10
- */
11
- export declare function scoreSommaireBlockForEvent(blockText: string, ev: AgendaEvent): number;
12
- export declare function scoreVideo(agenda: Reunion, agendaTs: number | null, sameOrg: boolean, videoTitle?: string, videoEpoch?: number, videoOrganes?: string[], timeAmbigious?: boolean): number;
13
- export declare function dice(a: string, b: string): number;
14
- export declare function normalize(s?: string | null): string;
@@ -1,147 +0,0 @@
1
- import { parseISO } from "./reunion_parsing";
2
- import { normalizeText } from "./string_cleaning";
3
- export function jaccard(a, b) {
4
- if (!a.size || !b.size)
5
- return 0;
6
- let inter = 0;
7
- for (const t of a)
8
- if (b.has(t))
9
- inter++;
10
- return inter / (a.size + b.size - inter);
11
- }
12
- export function jaccardTokenSim(a, b) {
13
- const A = new Set(normalizeText(a).split(" ").filter(Boolean));
14
- const B = new Set(normalizeText(b).split(" ").filter(Boolean));
15
- if (A.size === 0 || B.size === 0)
16
- return 0;
17
- let inter = 0;
18
- for (const x of A)
19
- if (B.has(x))
20
- inter++;
21
- return inter / (A.size + B.size - inter);
22
- }
23
- export function isNoiseBlock(text) {
24
- const t = normalizeText(text);
25
- // très génériques / institutionnels / bruit
26
- if (!t)
27
- return true;
28
- if (t.length < 6)
29
- return true;
30
- // Ex: "article 78", "ord re du jour", "organisation des travaux"
31
- if (/^article\s+\d+/.test(t))
32
- return true;
33
- if (/\b(organisation des travaux|ordre du jour|suspension|reprise de la seance)\b/.test(t))
34
- return true;
35
- if (/\b(vice presidente|president|secretaire|ministre|rapporteur)\b/.test(t))
36
- return true;
37
- return false;
38
- }
39
- /**
40
- * Score robuste pour "bloc court vs event long":
41
- * - coverageBloc = |A∩B| / |A| (critère principal)
42
- * - jaccard en secondaire (utile quand les 2 sont longs)
43
- * - bonus time optionnel (déjà chez toi)
44
- */
45
- export function scoreSommaireBlockForEvent(blockText, ev) {
46
- const evText = `${ev.titre ?? ""} ${ev.objet ?? ""}`;
47
- const A = tokens(blockText); // tokens du bloc
48
- const B = tokens(evText); // tokens de l'event
49
- if (A.size === 0 || B.size === 0)
50
- return 0;
51
- const inter = intersectionSize(A, B);
52
- const coverageBloc = inter / A.size; // 🔥 clé
53
- const jac = jaccard(A, B);
54
- // bonus inclusion brut (utile sur des expressions exactes)
55
- const bNorm = normalizeText(blockText);
56
- const eNorm = normalizeText(evText);
57
- const inclusion = bNorm.length >= 10 && eNorm.includes(bNorm) ? 0.12 : 0;
58
- // bonus heure (si tu l'as)
59
- const timeBonus = timeProximityBonus(ev.startTime ?? null, blockText);
60
- // combine: coverage domine
61
- const score = Math.max(coverageBloc, jac) * 0.85 + Math.min(1, jac) * 0.1 + inclusion + timeBonus;
62
- return Math.max(0, Math.min(1, score));
63
- }
64
- function intersectionSize(a, b) {
65
- let inter = 0;
66
- for (const x of a)
67
- if (b.has(x))
68
- inter++;
69
- return inter;
70
- }
71
- function tokens(s) {
72
- const stop = new Set(["de", "du", "des", "la", "le", "les", "et", "au", "aux", "sur", "en", "d", "l", "un", "une"]);
73
- return new Set(normalizeText(s)
74
- .split(" ")
75
- .filter((w) => w.length >= 3 && !stop.has(w)));
76
- }
77
- function timeProximityBonus(eventStartISO, blockText) {
78
- if (!eventStartISO)
79
- return 0;
80
- const dt = parseISO(eventStartISO);
81
- if (!dt)
82
- return 0;
83
- const eventMin = dt.hour * 60 + dt.minute;
84
- const hints = extractHourHints(blockText);
85
- if (!hints.length)
86
- return 0;
87
- let best = Infinity;
88
- for (const x of hints)
89
- best = Math.min(best, Math.abs(x.h * 60 + x.m - eventMin));
90
- if (best <= 30)
91
- return 0.1;
92
- if (best <= 60)
93
- return 0.06;
94
- if (best <= 120)
95
- return 0.03;
96
- return 0;
97
- }
98
- function extractHourHints(text) {
99
- const t = (text || "").toLowerCase();
100
- const out = [];
101
- const re = /\b(\d{1,2})\s*h\s*(\d{2})\b/g;
102
- let m;
103
- while ((m = re.exec(t)))
104
- out.push({ h: Number(m[1]), m: Number(m[2]) });
105
- return out;
106
- }
107
- export function scoreVideo(agenda, agendaTs, sameOrg, videoTitle, videoEpoch, videoOrganes, timeAmbigious = false) {
108
- const objetS = dice(agenda.objet || "", videoTitle || "");
109
- const titleS = dice(agenda.titre || "", videoTitle || "");
110
- const titleScore = Math.max(objetS, titleS);
111
- let timeScore = 0;
112
- if (agendaTs && videoEpoch) {
113
- const deltaMin = Math.abs(videoEpoch - agendaTs) / 60;
114
- timeScore = Math.exp(-deltaMin / 60);
115
- }
116
- let orgScore = 0;
117
- if (agenda.organe && videoOrganes && videoOrganes.length) {
118
- const agendaOrg = agenda.organe;
119
- orgScore = Math.max(...videoOrganes.map((v) => dice(agendaOrg, v)));
120
- }
121
- if (timeAmbigious) {
122
- return 0.6 * titleScore + (sameOrg ? 0.4 : orgScore * 0.4);
123
- }
124
- return 0.3 * titleScore + 0.3 * timeScore + (sameOrg ? 0.4 : orgScore * 0.4);
125
- }
126
- function tokensDice(s) {
127
- return normalize(s).split(" ").filter(Boolean);
128
- }
129
- export function dice(a, b) {
130
- const A = new Set(tokensDice(a)), B = new Set(tokensDice(b));
131
- if (!A.size || !B.size)
132
- return 0;
133
- let inter = 0;
134
- for (const t of A)
135
- if (B.has(t))
136
- inter++;
137
- return (2 * inter) / (A.size + B.size);
138
- }
139
- export function normalize(s) {
140
- return (s ?? "")
141
- .toLowerCase()
142
- .normalize("NFD")
143
- .replace(/[\u0300-\u036f]/g, "")
144
- .replace(/[^\p{L}\p{N}\s-]/gu, " ")
145
- .replace(/\s+/g, " ")
146
- .trim();
147
- }
@@ -1,7 +0,0 @@
1
- export declare function normalizeText(t: string): string;
2
- export declare function decodeHtmlEntities(s?: string | null): string;
3
- export declare function stripTrailingPunct(s: string): string;
4
- export declare function dedupeSpeaker(raw: string): string;
5
- export declare function fixApostrophes(s: string): string;
6
- export declare function norm(s?: string | null): string;
7
- export declare function normalizeSpaces(s: string): string;
@@ -1,57 +0,0 @@
1
- export function normalizeText(t) {
2
- return (t || "")
3
- .toLowerCase()
4
- .normalize("NFD")
5
- .replace(/\p{Diacritic}/gu, "")
6
- .replace(/[^a-z0-9\s]/g, " ")
7
- .replace(/\s+/g, " ")
8
- .trim();
9
- }
10
- export function decodeHtmlEntities(s) {
11
- if (!s)
12
- return "";
13
- return s
14
- .replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCodePoint(parseInt(h, 16)))
15
- .replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(parseInt(d, 10)))
16
- .replace(/&amp;/g, "&")
17
- .replace(/&lt;/g, "<")
18
- .replace(/&gt;/g, ">")
19
- .replace(/&quot;/g, '"')
20
- .replace(/&apos;/g, "'");
21
- }
22
- export function stripTrailingPunct(s) {
23
- return s.replace(/\s*([:,.;])\s*$/u, "").trim();
24
- }
25
- export function dedupeSpeaker(raw) {
26
- let s = norm(raw);
27
- s = stripTrailingPunct(s);
28
- const dupPatterns = [/^(.+?)\s*[.]\s*\1$/u, /^(.+?)\s*,\s*\1,?$/u, /^(.+?)\s+\1$/u];
29
- for (const re of dupPatterns) {
30
- const m = s.match(re);
31
- if (m) {
32
- s = m[1];
33
- break;
34
- }
35
- }
36
- return s.replace(/\.\s*$/, "");
37
- }
38
- export function fixApostrophes(s) {
39
- let out = s;
40
- out = out.replace(/\s*’\s*/g, "’");
41
- out = out.replace(/\b([dljctmsn])\s*’/gi, (_, m) => m + "’");
42
- out = out.replace(/’\s+([A-Za-zÀ-ÖØ-öø-ÿ])/g, "’$1");
43
- out = out.replace(/\s+([,;:.!?])/g, "$1");
44
- return out;
45
- }
46
- export function norm(s) {
47
- return (s || "")
48
- .replace(/\u00A0/g, " ")
49
- .replace(/\s+/g, " ")
50
- .trim();
51
- }
52
- export function normalizeSpaces(s) {
53
- return s
54
- .replace(/\u00A0/g, " ")
55
- .replace(/\s+/g, " ")
56
- .trim();
57
- }
@@ -1,9 +0,0 @@
1
- import { z } from "zod";
2
- export declare const configSchema: z.ZodObject<{
3
- db: z.ZodObject<{
4
- host: z.ZodString;
5
- password: z.ZodString;
6
- user: z.ZodString;
7
- port: z.ZodCoercedNumber<unknown>;
8
- }, z.core.$strip>;
9
- }, z.core.$strip>;
@@ -1,10 +0,0 @@
1
- import { z } from "zod";
2
- const dbSchema = z.object({
3
- host: z.string().trim().min(1, "Must not be empty"),
4
- password: z.string().trim().min(1, "Must not be empty"),
5
- user: z.string().trim().min(1, "Must not be empty"),
6
- port: z.coerce.number().int().min(0).max(65535),
7
- });
8
- export const configSchema = z.object({
9
- db: dbSchema,
10
- });
@@ -1,54 +0,0 @@
1
- import { validateChain, validateInteger, validateNonEmptyTrimmedString, validateNumber, validateOption, validateString, validateStringToNumber, validateTest, } from "@biryani/core";
2
- function validateDb(data) {
3
- if (data === null || data === undefined) {
4
- return [data, "Missing value"];
5
- }
6
- if (typeof data !== "object") {
7
- return [data, `Expected an object got "${typeof data}"`];
8
- }
9
- data = { ...data };
10
- const errors = {};
11
- const remainingKeys = new Set(Object.keys(data));
12
- for (const key of ["host", "password", "user"]) {
13
- remainingKeys.delete(key);
14
- const [value, error] = validateNonEmptyTrimmedString(data[key]);
15
- data[key] = value;
16
- if (error !== null) {
17
- errors[key] = error;
18
- }
19
- }
20
- {
21
- const key = "port";
22
- remainingKeys.delete(key);
23
- const [value, error] = validateChain(validateOption([validateString, validateStringToNumber], validateNumber), validateInteger, validateTest((value) => 0 <= value && value <= 65535, "Must be an integer between 0 and 65535"))(data[key]);
24
- data[key] = value;
25
- if (error !== null) {
26
- errors[key] = error;
27
- }
28
- }
29
- for (const key of remainingKeys) {
30
- errors[key] = "Unexpected item";
31
- }
32
- return [data, Object.keys(errors).length === 0 ? null : errors];
33
- }
34
- export function validateConfig(data) {
35
- if (data === null || data === undefined) {
36
- return [data, "Missing value"];
37
- }
38
- if (typeof data !== "object") {
39
- return [data, `Expected an object got "${typeof data}"`];
40
- }
41
- data = { ...data };
42
- const errors = {};
43
- const remainingKeys = new Set(Object.keys(data));
44
- {
45
- const key = "db";
46
- remainingKeys.delete(key);
47
- const [value, error] = validateDb(data[key]);
48
- data[key] = value;
49
- if (error !== null) {
50
- errors[key] = error;
51
- }
52
- }
53
- return [data, Object.keys(errors).length === 0 ? null : errors];
54
- }
@@ -1,79 +0,0 @@
1
- import {
2
- validateChain,
3
- validateInteger,
4
- validateNonEmptyTrimmedString,
5
- validateNumber,
6
- validateOption,
7
- validateString,
8
- validateStringToNumber,
9
- validateTest,
10
- } from "@biryani/core"
11
-
12
- function validateDb(data: any): [any, any] {
13
- if (data === null || data === undefined) {
14
- return [data, "Missing value"]
15
- }
16
- if (typeof data !== "object") {
17
- return [data, `Expected an object got "${typeof data}"`]
18
- }
19
-
20
- data = { ...data }
21
- const errors: { [key: string]: any } = {}
22
- const remainingKeys = new Set(Object.keys(data))
23
-
24
- for (const key of ["host", "password", "user"]) {
25
- remainingKeys.delete(key)
26
- const [value, error] = validateNonEmptyTrimmedString(data[key])
27
- data[key] = value
28
- if (error !== null) {
29
- errors[key] = error
30
- }
31
- }
32
-
33
- {
34
- const key = "port"
35
- remainingKeys.delete(key)
36
- const [value, error] = validateChain(
37
- validateOption([validateString, validateStringToNumber], validateNumber),
38
- validateInteger,
39
- validateTest(
40
- (value: any) => 0 <= value && value <= 65535,
41
- "Must be an integer between 0 and 65535",
42
- ),
43
- )(data[key])
44
- data[key] = value
45
- if (error !== null) {
46
- errors[key] = error
47
- }
48
- }
49
-
50
- for (const key of remainingKeys) {
51
- errors[key] = "Unexpected item"
52
- }
53
- return [data, Object.keys(errors).length === 0 ? null : errors]
54
- }
55
-
56
- export function validateConfig(data: any): [any, any] {
57
- if (data === null || data === undefined) {
58
- return [data, "Missing value"]
59
- }
60
- if (typeof data !== "object") {
61
- return [data, `Expected an object got "${typeof data}"`]
62
- }
63
-
64
- data = { ...data }
65
- const errors: { [key: string]: any } = {}
66
- const remainingKeys = new Set(Object.keys(data))
67
-
68
- {
69
- const key = "db"
70
- remainingKeys.delete(key)
71
- const [value, error] = validateDb(data[key])
72
- data[key] = value
73
- if (error !== null) {
74
- errors[key] = error
75
- }
76
- }
77
-
78
- return [data, Object.keys(errors).length === 0 ? null : errors]
79
- }
File without changes
@@ -1,28 +0,0 @@
1
- // import { validateNonEmptyTrimmedString } from "@biryani/core"
2
-
3
- // const acteurUidRegExp = /^PA\d+$/
4
- // const organeUidRegExp = /^PO\d+$/
5
-
6
- // export function validateSenateurUid(input: any): [any, any] {
7
- // const [value, error] = validateNonEmptyTrimmedString(input)
8
- // if (error !== null) {
9
- // return [value, error]
10
- // }
11
- // if (!acteurUidRegExp.test(value)) {
12
- // return [value, 'Invalid "acteur" unique ID']
13
- // }
14
- // return [value, null]
15
- // }
16
-
17
- // export function validateOrganeUid(input: any): [any, any] {
18
- // const [value, error] = validateNonEmptyTrimmedString(input)
19
- // if (error !== null) {
20
- // return [value, error]
21
- // }
22
- // if (!organeUidRegExp.test(value)) {
23
- // return [value, 'Invalid "organe" unique ID']
24
- // }
25
- // return [value, null]
26
- // }
27
- "use strict";
28
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ZhbGlkYXRvcnMvc2VuYXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IHsgdmFsaWRhdGVOb25FbXB0eVRyaW1tZWRTdHJpbmcgfSBmcm9tIFwiQGJpcnlhbmkvY29yZVwiXG5cbi8vIGNvbnN0IGFjdGV1clVpZFJlZ0V4cCA9IC9eUEFcXGQrJC9cbi8vIGNvbnN0IG9yZ2FuZVVpZFJlZ0V4cCA9IC9eUE9cXGQrJC9cblxuLy8gZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlU2VuYXRldXJVaWQoaW5wdXQ6IGFueSk6IFthbnksIGFueV0ge1xuLy8gICBjb25zdCBbdmFsdWUsIGVycm9yXSA9IHZhbGlkYXRlTm9uRW1wdHlUcmltbWVkU3RyaW5nKGlucHV0KVxuLy8gICBpZiAoZXJyb3IgIT09IG51bGwpIHtcbi8vICAgICByZXR1cm4gW3ZhbHVlLCBlcnJvcl1cbi8vICAgfVxuLy8gICBpZiAoIWFjdGV1clVpZFJlZ0V4cC50ZXN0KHZhbHVlKSkge1xuLy8gICAgIHJldHVybiBbdmFsdWUsICdJbnZhbGlkIFwiYWN0ZXVyXCIgdW5pcXVlIElEJ11cbi8vICAgfVxuLy8gICByZXR1cm4gW3ZhbHVlLCBudWxsXVxuLy8gfVxuXG4vLyBleHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVPcmdhbmVVaWQoaW5wdXQ6IGFueSk6IFthbnksIGFueV0ge1xuLy8gICBjb25zdCBbdmFsdWUsIGVycm9yXSA9IHZhbGlkYXRlTm9uRW1wdHlUcmltbWVkU3RyaW5nKGlucHV0KVxuLy8gICBpZiAoZXJyb3IgIT09IG51bGwpIHtcbi8vICAgICByZXR1cm4gW3ZhbHVlLCBlcnJvcl1cbi8vICAgfVxuLy8gICBpZiAoIW9yZ2FuZVVpZFJlZ0V4cC50ZXN0KHZhbHVlKSkge1xuLy8gICAgIHJldHVybiBbdmFsdWUsICdJbnZhbGlkIFwib3JnYW5lXCIgdW5pcXVlIElEJ11cbi8vICAgfVxuLy8gICByZXR1cm4gW3ZhbHVlLCBudWxsXVxuLy8gfVxuIl0sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUEiLCJpZ25vcmVMaXN0IjpbXX0=
@@ -1,24 +0,0 @@
1
- "use strict";
2
- // import { validateNonEmptyTrimmedString } from "@biryani/core"
3
- // const acteurUidRegExp = /^PA\d+$/
4
- // const organeUidRegExp = /^PO\d+$/
5
- // export function validateSenateurUid(input: any): [any, any] {
6
- // const [value, error] = validateNonEmptyTrimmedString(input)
7
- // if (error !== null) {
8
- // return [value, error]
9
- // }
10
- // if (!acteurUidRegExp.test(value)) {
11
- // return [value, 'Invalid "acteur" unique ID']
12
- // }
13
- // return [value, null]
14
- // }
15
- // export function validateOrganeUid(input: any): [any, any] {
16
- // const [value, error] = validateNonEmptyTrimmedString(input)
17
- // if (error !== null) {
18
- // return [value, error]
19
- // }
20
- // if (!organeUidRegExp.test(value)) {
21
- // return [value, 'Invalid "organe" unique ID']
22
- // }
23
- // return [value, null]
24
- // }
@@ -1,26 +0,0 @@
1
- // import { validateNonEmptyTrimmedString } from "@biryani/core"
2
-
3
- // const acteurUidRegExp = /^PA\d+$/
4
- // const organeUidRegExp = /^PO\d+$/
5
-
6
- // export function validateSenateurUid(input: any): [any, any] {
7
- // const [value, error] = validateNonEmptyTrimmedString(input)
8
- // if (error !== null) {
9
- // return [value, error]
10
- // }
11
- // if (!acteurUidRegExp.test(value)) {
12
- // return [value, 'Invalid "acteur" unique ID']
13
- // }
14
- // return [value, null]
15
- // }
16
-
17
- // export function validateOrganeUid(input: any): [any, any] {
18
- // const [value, error] = validateNonEmptyTrimmedString(input)
19
- // if (error !== null) {
20
- // return [value, error]
21
- // }
22
- // if (!organeUidRegExp.test(value)) {
23
- // return [value, 'Invalid "organe" unique ID']
24
- // }
25
- // return [value, null]
26
- // }