From 8de9c150d5e9f400a3c88bfc4aa92ce747e30327 Mon Sep 17 00:00:00 2001 From: antoinewg Date: Thu, 2 Apr 2026 11:26:07 -0400 Subject: [PATCH] dfsf --- .gitignore | 1 + .idea/.gitignore | 3 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/pythonProject2.iml | 10 + Fiche explicative | 444 ++--- RSA.xlsx | Bin 53991 -> 54031 bytes RSA_UDS.txt | 1667 ++++++++++++----- UDS - Copie.py | 1331 ++++++------- UDS.html | 116 +- UDS.py | 1316 ++++++------- amĂ©lioration | 18 +- checkpoint.py | 1332 ++++++------- modele texte RSA.txt | 173 +- selenium.py | 78 +- test.txt | 225 ++- uds.js | 190 +- visualisation | 96 +- 19 files changed, 3858 insertions(+), 3163 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/pythonProject2.iml diff --git a/.gitignore b/.gitignore index 9a474f2..5b60995 100644 --- a/.gitignore +++ b/.gitignore @@ -186,3 +186,4 @@ cython_debug/ hs_err_pid* replay_pid* +RSA.xlsx diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1a8f1f8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b7e2173 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/pythonProject2.iml b/.idea/pythonProject2.iml new file mode 100644 index 0000000..0c48917 --- /dev/null +++ b/.idea/pythonProject2.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Fiche explicative b/Fiche explicative index 505e65d..2a2a8f1 100644 --- a/Fiche explicative +++ b/Fiche explicative @@ -1,222 +1,222 @@ -📄 FICHE SIMPLE – GĂ©nĂ©rateur UDS / RSA -🎯 À quoi sert cet outil ? - -Cet outil permet de : - -➡ Transformer un fichier texte (.txt) contenant des informations sur des poteaux -➡ En plusieurs fichiers Excel remplis automatiquement -➡ À partir d’un template officiel UDS ou RSA ------------------------ - -Le tout fonctionne directement dans le navigateur, sans installation. - -đŸ§© Ce dont vous avez besoin - -✅ Un fichier texte (.txt) avec les donnĂ©es des poteaux - -✅ Le template Excel correspondant : - -UDS.xlsx si vous choisissez UDS - -RSA.xlsx si vous choisissez RSA - -✅ Le nom du releveur - -✅ La hauteur Bosch (ex: 1.5) ---------------------- - -đŸ–„ïž Comment utiliser l’outil - - -Étape 1 – Choisir le type de document - -SĂ©lectionnez le type: - -uds → pour gĂ©nĂ©rer des grilles UDS - -rsa → pour gĂ©nĂ©rer des grilles RSA - - - -Étape 2 – Importer les fichiers - -TĂ©lĂ©chargez le template Excel - -TĂ©lĂ©chargez le fichier texte (.txt) - - - - -Étape 3 – Entrer les informations - -Nom du releveur - -Hauteur de l_dcwmpi?`FhBnPM6q5JlC(+uYw`eo>Mp|l}i+n>=V$xg8IUw+gXU??IVXjK+sHPRw5bdMoQMu5OP@H$-vipF<`OwSOrhx}f z+Mc<1`H9%~>yqzFrRdsNFUCR{oGAg+cONDj`;U;0Y`fKj%~)|v5F9!bM(UWm+FzV| zI@m;`SiIckkWG|sx_({WRg=D}qKwv}H)J$VH*V|Dabe`l5x0+=RVO&RQv& zJCH};cf+I=Yf>NOU-0TumPZq|?MlX-m&QMy%w|5OPL){65a6IOIdDzb%qOg?QOUogwR4D)a!)#1{)b-H8aYt07Gt|ZJj+szE zQ*4Fy9aYQe2qgNjrCHKGe1?b|6D?Z%iLk3)|(O+LF(Ezdb*x-3)P`lv0T_xSdiC?(&+?m|0RgU1(~ zPM;r~Vp~JC)A+_6vU?OS(%F$3boZiLuyZ8IkKXtZn{OL~bXT1}OcrN~Wbh~QZN&P? z#E%eSm*dV&J4tRozF>DNq4fP$=f|Z@5lYL~OZ*J&Zpvq~H%7gnrJOTZRr9x`-Y3Xe$|Ui}UupF6B$cu&#;@Q=E3IeJtL*s-*71vgqva zny8HQm_l4d%D`>^Ui0=;Tk)FS%2c~{B4x?-uhMrb22Qn~=_{6L73?2&qWIi)K#HaE z>ygr=Y@$zg?jrrvUG8$7qGeE@!`Us{=-`6ug|V(`7=2&oV0(h?j~OrDP9J)n!C>Bd z^J_4_3?IEwLKtuNp7~F1tByCC(Sjd?!Z* zUir`SizMWvI|B`AU+g?>Trqk5If|bqHW{Rj460xFu~SQ9CR(gwI9n~;<6GoO>8-we zgofrv%7Kr)ipQ!RM;&c3Y-%}l>DUb%xARHKo4JPwkBHnV8|VJv6aQ@GZbn(hx`LN^ zj161octv<^$Wv?eD*Iog-zC|-+7H^vZ@-W__tb{!p`MPS{B_x#lsy9rxjM9EIBoIz zafd_1p25w>m#q#Qpe#IueiTj*iNc|r5MhSu7oqlFJT~}Pbx&{WR zL-`>thiKIk`X=vm?QT71ITRK{f5=bzXXDsIcs{W|szuVY8Lpqkv5pTaI@ zKW6YU2s&qU+<1nT=D`U+D`DOkUUg0S>^t;gEr*}le#Rb&$nfWFiao#M!N)(;aomSA z-}3gm{Drd9{1;kPgj$Es2N?Yrb=A?RpFG=8ohmvutTjqATHAGZY!h>j|FDs6OY1K+ zvfFLAQS!&<-~S48W!*ENXCyifo%zW6?HJ9_$$)#Ixl@N{2anFOSoH`=ng&U5)YjE4 zl3lxv8lCP5-r*PvYe7p*Sc!cU5colIvXJ&{{i{GhOTx+2kE54k+&BDLVye06Lm$^w z{N$yH;q0N+J|Fc$*!7oK$XKtIvr7$e?@UjzZLb&MSx17`XiAhX73Fm)&ri@Nvucxg zt4nfRIdn~}RO1hnSY?gHYST{JB=lWiSh-qIaAwPil5_xVQ*zh5*E~Pu>y?6{Rf%Y4 zYtM`_=$4@4?YoDAnTj5HG^)$JkK3Mp{1G?$mMQ5_X$uoo|3NKNmJ|z@j8XMT#S6Ei z4C#OBHucI#a5pjr!F|HK=FeVmUNG_~lOh&{SE|Gjfu%9JT#eWFl8U|U9i*HQBFu+H`jW$CGnBbQIzeqKuTE@6j=NLARG(Z#NyYme=- zkF06N?h&-oiFwFu8J>5Zk>hF!*Hu6;#z(6_{Qo_Ss~d69&Rt(PN9aG$B!>j zG&Qm(KlD1j#L$Few|MAvY>B1`%RchZi+G8pX`TIsjAHje#;%Q*Ix=h$8aUsJ(_S6C z8(7}YJ;={j-oCHTJXAMX`0l5Th6Sq1u<|`fn+S_jg*;gKJkqAavQ;Zs`8?C+14>Ty zC*AT)ndj^CkyE^@_a;y0|Hn^9!reO&zkeT~_I3lEXf#+V;3q~8f~85YG|*L&X|FwyR3eW)C?JGp6(B}m z5@13b2v8j7vRCbY{+7i~wi8`MMT4%UI`;SLAThdwN(8+?MFK^Z6uk9LpBJ#Vu-noY zFzT=ATzglzlO$&?%_?ci7|Qr$)uYpKV24O}cq;QC`B$`m^>}$%*4`DGHakV~nfARK z8~tJ zY{)&H;z|h(P~di z&xCv5D}Ah?!9?VYmT!?0>*bJT%i9S=dSh}ijJOXG7~ioQy3!NH-?%rJrPUP(w8D3i zxd#;0??K^rce(qv)ZeV4Z{kjUZqN?*1`7)6_q@aJZgTf6tG}5*-)ubf*oA&wK?Hq{;VAkx11s8{fr7|Sk2sT7OA!5% zfeoF{KmlII(0vRn=m`djqaM<$jx(d(b!c)%HZ%((1$Z4rt1_~nU$8Kuof!quA&g|` zT1F=L1s%^6NH8B=Ii6`GUHx&IMysIT&S~9j!8V$B2i3AJTvv%Q-Ob&e)DDWNI6GMb(@*w>_Lx225=}ul)9N;|2CSMh>OEpL`)ZX+dr-0!;6BN zZ(AbkHDt>J3i74N?2T$Q#7;hU(swm3XP;H%U)D+rTCC8wxF_n__T#?7kD_DMa-pf0 zwt6t7{xf}%+KTgQl1a6YbQN>~-(9wynQH|Z-Y_Ix;-u~f4 zs*v>|Q}S0XVKVkx5TlogZ^7*!ZlpC?A4(;EfKuxgwsU-_x_9 z+vq95ix@phFMY5bEy%zPOiBS>htW0+oUmC5fLYNA3|z2D3COfq(4w@0=tTx10$@_~ zaYk;~ngrh@-lIhs#ep@CpdSOPhA>is7YRCrQ5snDw;3Hh{JMTycK+@C63&tQsa5IG zlAKM$2diemb_EZjWH%f0rdpI&rEhDg)DJDsw9sdir_Sg+*R0iXTCUox@t3{lTKQo2 z$D0b_h4sDd&8jTMtFn2NpY)4|G=<4ZLCPjSJuZ8y4fS=qgow5@`HDQ$%`l^C>e*K8 z;b+8If8+U#$%_w$XDD_oM|I`B9DAEfOR`y?KhbwlUz!{ zGbMNtqeYpe4<(MGMHo2ttw4yr#lQ|*;Rq63=p?X$4=qA;4_E=AMTieAG$|toY>Fem z6m}2Mk60uKj%HGzzp${OztOUwmsq4B5J-Pp;GfuPG+lVU?s3j(z+m;^cip`7QU@pU&D+M9)k=8@OZM60O+X6}EXqZ~7^X)KCr^t!_w# zcaqOGZLW09QhKrj(ft7BIi96fN+6sGg;y!10$v4hI_i^<>dmFo+ zd-ptrya@R*lg~#kGcT=^VM;Bm-zJI-Jj{q~;)YyzKffuT`Z~MAWVITRzJg9_C-+nI z+1$7+&27k9H*>C0zgx!tm7IU*qCygMx23N4r))^+veIr7UFIH_P?V>R)28Bg?JGI2 zZ_{1gbec%YUVERxdG-={sZepIUOwiow3+{>q;bz{jrDs)nOhzdl2>6JUwK<=#yi>u6+=N|IVz<5)sE@sOAc(l*`(;QSFnoZ>Vm4}9Fkuz|B6=4AG^+YmdF9;H7SgOB38>~5sVnV3Q(2MYb6BQWGaqQ{Z8eD$uB;lZUz%!9)pr%<{LuqF4fGGQ!u%+(TyTj$%UELqp zK{kLE6WORYaLTp5MSJ2ee=VU9nxE z&n;-OducS_kWQ;7iWxguE9o=9CN_n58Ruw{JC^#RBR85t+DMXjJ*Ryir z5%0J6Nb=E3$5mg!U-DzsFW>J4H3P(pL%q`;Lg2aek<&K#(Jaus}wK&b1c zlZ5W6y!Mc|n5tL>Mo*mw5;Krw#=O3kHuW<^X+;NX3J+?jB{O-3)i|WJt$gX#c>qbw zH1O<6d(&uE>V^=*%2oWz65oGm#u8(!cX4Kd?}C5RNqyGP3O99?dW*X}M!ZmC*%;-*rK{*1)M&T6bcVkEHU*Tu+lgu8+@{d>E_Mh=7GZm3@I>)iUdqhv zh4@-MZ-Pn_eebm!3R)_{7Ls=_LHxRlMF-0tdmUa9Z92uC{Md_d>1-1nyTxO#BTJG^ zQtTs-y@;0Np9SmmN@ml29xv8><>kP4v+Na*^M#Fsj)GDvgS9*h$GYsuXFjUOqdp&d zrdcm0bw$Jl{PW)g9g-sRABg3Oc=}xc2UmoGejM@Fd)W%(BQ40FGP7oWq`_F z`w>&;+9%A?1$g{c{>$3`Jtzs*eofl;o7J|E9GOchu?{?xee2pJ@5{gv>u`8z!v_!J zkXdAyg3R*6v)RZjf46~{@xf!z*=}SO84e<| zLh$Ukk{ORU-NRegGLVl8@XASHcx4S9W+1~|WL5;8B_x1nks(9|k57ui)3nNFJazQo zmF4khmlzYcyJ*$eQj1~PjAD2W$7MIZj?uL4$(Qs<6UWx~>+lS#8* zi!PoRhNwdTzYu9|c^<$8HqA>NbUeDG6`(nXn1|}A|SA$U;MlJ6s zJNu|~`W^txjmWu-T>fhfuvh?179ee{?=bx9i&nzbREcSJW zD!n*UWoTwODZ9P8vC53gvr&>wEa-5u`{|D{dXeo(C0%`wOouDmYm8`yXL)!;QP`$o zC%;Bz^HC1${0+?|Dx2f!{3h#B(NnEc;Mn%oSENLF=vE+- zP{r+EjnEEic@4)lvTM-W;?8z+XLU{U*-s9^{`;NUd&y3{kn`6Kow!gzZ5zhcGck8W zMl4@_`2L~9*PJ!&TEV(@LF6tCk=-H(Q8_Ow@eejiJ%WTuLUB?X@c~s)drniE(9MZQ znAPBv)S2xnf8Q+0x`1j2uPGmcoK1n}I_538p*q*=MLEUEZ=NasPCp^DrPqkf=R!`wtdPN_Eeu<#eeF_gH%`Z9lU_2$PQ-I=arQprwd*OOF zfK88W>vip$6;r_Zq?pQ0S%jU~9zH-ElV*kCo)tI~4w)4aur zdaI_($)qF-|^RvNCk)ywxBIq!FVbBsehVJKQfmkT0{T_5p-U}Rtes@6rZi-y( z6-q8~^TIaWxVrIk#*0kE`XowShD|0zroL4tGnsBY`bm>ZlnaN>&d0E^%$dyN(VIsi zYJLViAq<)j)@9AHcy}|cDB_~|Lo~K?kXCglsiaEx5<6LjVY@`k*%%+%$mqlb6qQ@K z*02)fS~WUri7SD9oe`6=l6_)hq!fF4uf)hpJ|mL0{(RGAw!>mBcXP;<%#CytL{_)P zm!fVLrYpu=73c!Cj4$~<_d?|kj$mNK&A3EA|f_HsS)@3L+gijdwZKVH&3Hx zpUb#8NUYH@o{myXl{@P3N>$;g_TupH_FJen?^M;!axH3c!XaN$kL`ugmUAH1!>)OD z^PNYzT8M$>t+Kp}XN4FGX6b&6^S`70h>y)t%iCrKyAvfU{S!K!cN9By7=sF%_bpNN8&zB|HyzW%(8kYs zBH`V!%u>bLo#{oCh1V~w4NmNIZ)rua6bQZn%lr>szJ4I&?syTd_J?_G%GU@4r9!LI zr3K7kwS))LF=At1KHfxm zmJ=p`kDBK^BAXUlY6_-#-$0qxtTM7M9vrzDz#ImeB1Pw{?^R2TuUn5`ov8b|I>`X0 zH?d{UpsoH{AFAH1ne!|#xrv$2-K-*DFc}M(JNMimiT6bPp~yZrsm-l7i`6&6?Sncw$wy6Zae{K^yw>MJ7;o7jW2Cg zR-rsMzxlN%y{H=6oe~Qm2?Hc=|NLw76R0I2G`+)S;GEsTf_Ac-o&GaNO*mD@kt1TO zzet$-TwANwiGaSdREM-)C}VkE?3s9;M7=T)k6Dan@~e|7nTk z`A)BYvLEEW4e8n}^kfdz6d2nMhqaqhq0e;1&N4n_B&R%=a?*OzVW&@T2D5^D@Ly+A z$0k>O*BTtlYGo(<^jP}DpH00kGmR0rC$5v#Q{04-w13^KE~)P+PntM3G4^~2 ztPk?v3Mm|D>B_ldj4l+RR<&V^deI)NK=QwKrjjco8~^OHU9&ni-8xlw<;HpDXTPsf)VODsED>y0Jyk>18i{Nm3J7O|6k@;&_GwR&v%HMX@lFe@XzDbj6x zg6RACLu%b=t%G^wl_3r}9^q&X5o($L;|rP(3gpLpjQMr<8V>yTiT&`2XnzqN?w-%x zxHAh+(>c8zu#&Wr|M}?OUu1`F`gG-y53K2fYyYR-y?dGdw=&iYt7jPhmrfmoZF0rO z%5U=PV(m{5e?RxfU93t2mfUPstg?U)-Z_2yAI(Avb0vq1+JkZ7|FxtrN4iz`WCh3I zO@I6JGXliFVE1}jZG{+g%j)&NG;osZu9E}&@J`%4vl}{Ne?1-53%o@BZ(9ep*0nf< z^wvN*Z>U->*Pj%-5YJ~=on~eKE9)8&?Lvh8U zJe9?*fh$uOW1i_*@C~m0pMooqHP_`)AKI35dnAwp|m_gGQfm%lAZ5sBczibYj&y1z_PmkuGhzWHc_lF*Qsp z$l;bZjQRI^I}jdYZJ4kzH3gnu)Dx`Mi8TnXxfpK#ir>4m!QuYrcA;WU`Guk)jm{g; zSB5b76z>r3Y9)hB2f^VV;qvA-Dju#6a)D^jU!ukOOkrp3E3-YSKe>9aiy!!dQIRzk z1yT}VI&fuf^$O2)-|Rtkk2Q~T;kyn6r$(&jSH5}n-ZQ8ykS#bHJ$=Wgf9XPaQZ?&~ zG}{6qZfJUO%|p4?95rB&$SO7AuaCczr#!nl#++QOb7X$i-=})GBu7Tx0YjPvl*Z(m z8;tVPa-FB(>5Vt^4H0!0V+q1n+&!ybSrnAcXKRHH+*jro=p4Jq z3Y7KF(}z0>umkrDG7DsdH-Z|0#Q7WWQ{~|cK&4o;s6}+HIbbA<7I0e zOKVXM(-0H5+}2VYIdFj}%}(T@`(kUGCw2>ZkJW&6e)+}OR~r9XUF<|2oD3eP8(TB8 zuW>}LwF9%CXA>&QQG-A%i!? z3X8J`KgYs0Yu~P{9zK&OqkTFe-_mojALViI{R={~SyY{^VH(c6`fd8|y8MeW*!l|( zAPeo(X75^a;kHbnF4#czxSD**bs)$mScgtPhXV~7>rTlh_35Umx)vU_9{7{m)3@vk zT{Blgz~(%m&gB}`Y`oroJ5I@$&cseBk7|kX3NHQPB-8#)Ojjnh#+=;wY;AA!|5=tCD6E|eZ4(Mmzn}Wwwo6VqECv^fxG{Qi=pC!263(0 zTv3RVbpxlQE8u##{d-fx=$9crDN&M~e!$`)kCqe*_%x zXM^0GLFjhgo!|sg>%)Nuu0ar9__U@5F9>+$ zeV~FJ6M)_Dnbwzju)%D2sQ)sUTcqh~@2s7^+3M!1hn<+x0}!s!&4I8M^*>7{OhART>On-w{IP@PL`TRxyP>M~eHU}X1w^(-i8H-Y7R!wN8 z?g3}nJ@%gD6aEfV*5bO+zgur*CJE1|gBW(5Nk3~cZ>v>wCX@U$p^Mns;y z5+&snADVSyJ)HAbaH5K-Hp@`0e)Q7xkDE@w$iYnZ0dNfzFXCg=e!$17SyeBPoC~j6 zz`%z-4*-YS7P!0XekyF!n}YA{Wc+EDYL$)_kZ&Uh;Tn&-hlHR5|cf^Hfk5csp? znd=8YMr=6=QbA}cmod-6Ea^lm5Dpbzgm~)Mfq;X6LzpGNC`A?q9s)3{(uLdKzF#SG z#q*NEcKsM{z|JW{SnpcsZ~o4cSSAgSaVlkXuJ=v~xoXsw>RW@)b#p{c81qmU9+(%A z@_^VFf)WKq?^4ktR%8|~+WXWDW}QABmWo(e^$!P7x1beEUt&UnI00E)FLXT;#G0+9 zqcWn22NsJ9RROO?-UoOaeU<8zcIJ$pmc7O-^MQZAe%hcz#bY`ey>G02dOu19dj6CE zV}j7I6HrjA7(_z5J&ZsNKnwn`7J%~wJO+sZ<9IeW~=fFFcGw4NxuAfA9Cc-<{SEXOVJJ%}K~fo0@&eI;y{rH<)rERgx* z^#d@XO4mO&_zt8aGNCqz-15OVG8LaDBrC=T69$$FILcLO1M5v6WkLT2{h-zrZ~69j zmXSQp5WWrt0WM!>-&#s9{S9%pVeHroVndiURLbJ6_hy`5*%*{MX*O3WJW}~6fEqq9 z)2tB2>aq7hDcR1jDq5@PMV{@eVtxOi7Sskvrn|9O|1b<}LlOk+g6}Osma8gohun`h z6t)FUxlT$g%vwqNrQyU)0rlJRVD<;j4&L2yRwM)6&k#VBro6EiFfl|*R&N<;y1YRW z?ILQ-gWaygIF@cu01sK1b&_s4z@6*~#P=dGL{gr>B=lw+whC|- zjkPce@KmUqfO1I;1GeB3Vkr{`;S(&u34jhc*%0P@f`h7!H~aW{w2zDUnpx!fs+e9i zYZ%9$&IBOT=8K&%@nI(5FHa4CtItxXdkkW^!dIqNj{~xP&*Jwg9HJiboS>Qr@Lch@ z@O^jKqq^mc9+c98^BFPlp2W8GCbV?3*mIs;E;0{Q>r90YS?`%OD*=LaE;B6DY^7jM zQLdL2sB$j=5Dne(xDdWOEItShNznu7u(gl_9txuO%O4s3Y%j(RxLc$*ddMTxb`U;0 zhc#)G_H_j`<5pSVZr9q@lv_44S_8nCmOOxl<-x`>N)*(%^{3Y&lTY_eAXIcgXTCWde}Cm1;K zw_(LN25|3GuX^CMZ7@WZVcc4N**yOySIXB_r~Rb%Xfp(54&eXbbkce_p@1+gXMn?VKz#7h z4TpF+H!`i{Fxl{q2SL3q4?YiHiGzG^+(vlYJ9vC zqESbX>57Hm2ybr#5#H!geaOJpr_{DA8eARJk05d(DPN{$90(_%9gV>p(w3Fqm+P87 zD>b(F=AKk}=WG*&fAr0B*+r*t5QDtPw{p)t$HDMthD#i_XGx#9vS?}0uw``>x z(%I52(rY<2r?)DGLo#_6y~-J$4w9s&mCk-{>xf)gn6)owP-T-EtN6OogN_%y3t{q4 zNhurIps?upR|3T&_o@{f8j8NzkmTihRVEFR2w(Pq-^|o&hp@9_Hq25k zvfQf{lp2HXi}QG_-J=~0o?UZ85f!R*y7=cr;F1VJW1RXJ_OvPF`n;>#8!O`D|HZ<;IN*kEP!v*Sy}LBXV=_>4avZAqOg=QwzM;} zv!K%=Z01@)XuQ+l{lKLl=#lOZ;0G8AyZ#u$Ol(7*;w{dubuY*0*^K5b+6o$e@`0= zE5|<{(Pi-WI71%`Y$e#cGg$RzX&$K075Xi+O|5*LH_(O8PoN8eKoua%(}+mCSp-H9 zO`tL^=y}v)D;+HGCc$eMXd4i(=fG@kIUDQ4`9!^(n4LKdkM-4Yn<)*C%HgPZrxhph z{A+E~xXDOxqB597ObTy=_IL7C4+dL#mav#wRMbTJMEFGR2I`M&;I9(lUIP{dreT4r zM3A?@I~pU{RYcPIr=6L)Hi~qWt;2X%`bPzQ1FHwFaU+UywO&gaZEoYuw_Dp+Zt3j7 z5;YI#wD($v~qEh})JXZFyXCX!vQPvGO+Y2yk9+ds(16 z9=vk@afJw&#JVbyQWukZUpgoRu=L!F_`;)qRC+mDZ}!?kTMz;(Ok z_Uxcb@{8L{+B#jZs=Qd8#UsQ#VP~9bo-5t@mn#7~BOwYqBBDmK#ou1Gzch^_UhXOW z9T#tx3Ze|UFm1DAo5DRKp2lh3x2_Ri(=;RJY-lW$hZezAHVrp*HVrlf zbiHx4v6S+~7I>6UG%C?fhk(BJv1uS5+t?=UAgA(R0fa2T7dUk2Y}VkQua|5C5HfT> zFb|FDld|e~}EP)a6L4YDtV>ZCJ$%weXup{ebZM z6{X0nJByR0wGNA$!hngq)k~%?%GOoG$OXQNhyV*Xb>O5oCouU{t8*S|CL6^tCV;^F(%4q!AeouGW#aR5@EZLP3jpvC+zsp7 zs)nH_cE`)gX0Zl96SR*_0AB$dZ1zP)F4pWj6t$7}?5dOa^LQT}8)1ObNeGnwmEm^D z+&{EQkK6Ei^Lz90AnC}JX9rNOkl3jWx&_VL*9dCE-{9Fd+seS=>Tpaz#){F;?CBvO zD&*AEb_I|BaKth!Fo}PO*v-}lN+K^*F|2_>-gTnf-Qr(4uAD(*AM}wofb5-ndLeN( zwY}g-C-#4U2@X}h9Yy)qd^^{{5s20oz3>4poMc;e4f?IUcPubO_yBx@K^74liSjKE zV*ED5%Rp{}agEwYa|FZ+z~5K$?j-i z7zD=*Y><-KYEdeHMF3u5PwvBKQo|ZJ$p_xKx&hpIUl1e#;K3K9{e7aLx$oteox$&K zmWJ>I;Gfik0oExL!h;1SA7qNB5xCvaIGYg&yXtUVB@rk(aidR9Vz%(@Np`or=8J?66uMLchCV^XaXl$0hv0ejTi0JDA zM8xNw^;%`V`x=r(1(Ln1tvn^n(pzDYBIa3)#CndO6j(PU*Tj@cxDt3n+~0v1Tx`YW(1h9Ac} zHMd>a)CW`niN+VxGuuMGX7}o*mPM{cK~Xumu5OYq!i7y>6V0>$DKesak$z>}9%FzvNw` zo8*b831)jxSw^Wj!Y{P|zXU4WCmWr`z(y;T-qpp3JNV2N6-eC$Fk1;+4NpH2fa=2o z6pS%V__V%n9&!Qf+a*Ai!F>;vG&Lu;7{keMseL~sg%aP{1a>V4e0YAN9ew5!E8vU2 z`DFq~{IiB#E(kWE02Wv5KNJq8f7AiTE1;HmIL8WZ-XKLABI)5^^XQ%h6RHH9uAxF z7=;%Xhomf!++<2SR%LRx1G1`L(IM)U{ zStE4`p7z6lj7Kr#k`0mgO!fOd%Mm5=>qafvfEO(8Smas=vrm)*cY@O&IbZF4P!>z+ zrA+6!zstqbFxX3xd~Jgw`RBoQ6X?%ZSn$Li_{490nEf%&^v(c@F&&J$cn=TvsVrCr z++J=S#Kp1R@5?kF&oxA1N|9U+AA1pU(uBDnqS4=q!Qn}M(tZqr!~xUZ zI>X@&A5i$#5sQ1m&IlJKTQx|X3P@0oN)ng_)et`Ww(dHOM%17zVDCE!b3yCV)3$sl zc|6*J3Il}GGAJKBAe`_TD8{&9wD*bnS9yUK+5-m{Q#b&he--A<`)R2o$zBy-OacGn zsfOZ<{)F%xPHau|F20{i%QOW%XvGUsp3swE@G2-B5Z0=9qt* z6GH5{{T;5kfOBBzCP7)652H0~(c2yibY`IR!n<648eAp#=L6+hA;bqRdNdROh+-JcSR0W`-22}x4s^CMU0-#W+l_$6d1gE3lm85MM$W_Y? zdJ*mlps?PrPd)a?;D@G-?6Noj&xDx*Lc@R`;S9mK_l{eNX$l+DE(; zm=uR^8X;L}pT;H&x6T1#s3Gb7JCx>t(07;r0z+1R1m0$NpkoYhA10h`$FG0Uq z04VPJ$*6%<1TaVzK{87uKFZeM779paogj>g*GcI3V4e&v1oY|+H{u?Q@y#H71=s`{ zgGmB#Z8#H3Y=KS*mB8)I@(0#y3jm`3>3L8asqf8<*+8bH*|qD+p4;E~;PU7%1@)|& z15|)HZZHp^t1!>Z*9DX{P$GRVljz;{a4isOpC1?FJmmq=1r)5+2fJ#HFrH;laymYp z{}}|B7hn=R^0sAw!_9gW{EGoYfC3{lBog2}Adg!ffZ-YL8e}CcZqKe^6y>+CG`nbH z^GHiyLCN&mKqE~|%`h?03e3Heyyer=a42yg9SS@HW{?wks@Seb9K0g8 z4rvh5nzsM~8w%l$9Xfv04-kHQp|7fGY4l@O8Ku*oS2*+1C}UD#c2en!z;}Y@`_%V1i4q$0Ip0 zKMhAxsy*P;66=yvjq3NknFq$7tIfF%0<8M5`lUfA((J2Q0iT<4ju^k z8v<X4*Lz#`JV+XMZoA_-Z%m6LV(@j;d-_l?xFm9ShTqKjabV&gLK$m==DswK}x#wtxA6o(CWsYk0)o$Lp+`Wk8}47r>L3{~(Nr z>I^%Pt`YcC#D4OfuYsHJZd3xzvTSfK<9CeU|3FYLnYUe&e;S5IWJA@9{a!mrULb$; zVYdqQwnp|gk|Ah!c4TjJagV6@=G6ql<7TG0u9@I}uOlUbK3>EMjrGtBlZz}mTE1jp zioDs9JGL3hK2k z>KbB;k&SlXAFy1`ZP{|)#cZ^DuQty5X&X5t+_(DSku%gkz$xYUF^jI%0u`c~*`|0` zCp^%Se_O=S0yR|j8R}sRO;UIe$<1eF|DtNR;&Rv2#Dc?j(+c9Sw;!8Ge^}Et5QlxY zl^fAa>80r!?{w?(tF5dpbuX(tVP2@B6?0^IHqUpB?pnl=;q}-%v|L-5forM-l#5da z9uiZbr*CZEmXh~)*TOY1Rk#-^nH@^DTqzJ5kOk4#f7iH)T^)s}wBI&;h7x`W1x&v+ z*mKzARIiG~J)@3S@YZ!uZp>fA;!5K6y|v!NeB?boMy;Q|!D7E|8aSjf?kW06V`=CK zbJ({L6ME?lmfe`^`W

UL!+Ui}r^{m3}2%nh&v9lkz$H8k+Va4*b|n6Z^)7u~Pjz zf9smxM;-A`A*#g>WTBZyjeDx*GV6or{u%Rk!NmrP6cTZWus8T{0VKH^xG9%3d<3Kec|RO!yGNG zL?SjkLH}$sbQq$PS|0La;#D;={Qk+j`Ao7zR7se>Ng%1AEUlr_$-Kw@C9j?p zDPD=7u_1ayC7qRRydn6xDr6*M!z|Z}+0Ti-P~r8=w+})z$}*o9Ck5XqC+FTV@H4c~ z^y996h*8b9th0RgpUnOY9_-!==X5j6OvpiBelK!E09An&WRU z8cOvP&#TH)^iD>YREJYY2QGGWLAjmK=m)t7-=%A+pZM&Bso6F!-lU><&H9$vXxsK| z{(X$|_Jc&O4SRlSv(hw^uI@`$;{-yMWEE?Dh4o#f$x?e;7ImRBb}X~AH>!^jr#`!x zJuY9=G*Z0RXa3rY!A2+UXX(gSlMFhQS5+^-fB*4WdWABt&As};x6bs35AuAya<-kllcBg z^P4Xx+59(ir7Q*Y*V|B}Y<#&^+=Tlv9q#M*`84FmwL+IV#7vbgOfVduZReP4ab(;a zWwxq`o7#BmT@iag+*Cx$Se;TVL+_Vf$HHbHp<0Pn+I(F=+j8Xrg-Zd+%2@XTiLoX+ z>QD|{zjeBms&}gMn0U{pZ9CQ8n%SJ&@fRrRJdb6b7k8p*P~vKU#Gaq5V9&ueJFydx zQ3h?}A~uM!INnz}^?$QaBMHlVW-0Vek1Wvx8_uyrl;FcJ?R!Mleds-A#Nuld>6+l&=gc9bsY2AJT2^^<~L9t&Y? zN(;_-6|K8V#dJ4{vkG!#JmJ^G7slSeewfRT7aI|EUo}c0=aiV)RcbqpLnZ9)(Hw4* zZB|oFa@8jdPg*tbz3-=K zO=BXtmx`YVQn@|CwHyvXpC@-kwPt*Zoc+=HWL;Ro;26Dt-Y?z|rtW2~(ny(t`-yA5 z-15!#4x#A>%S0a$rE5e(C07jfJFuNG&5wOEFehwJ%;?z8@!s`$QpLnZRrWEMe33QW z%)26@m%DZE^B3Rh3#XZhta4u7m^7;!?0ejDOURG7i!YD(R9=rl%Oa=nBde_Pufm)w zPP$l6b6=Vt2kWE8Kk5zM&{1JBZ9jD8!$!q9AI6V-=|aqs8d0Hd1e+mFVO}$<8;N{( zEkqrt%dpJ-r6X|}Utf+D$dJx3Tg*wco)1;I+wYr5I8>Y*@S`aIptDUez23L`oEHd< zxkEqf6>cnP)5f>jF%pv1sVBdmjPOdg(e^76Ff0vDyiIYn{G6<-bb0IIZh_E`I@x-e z7UTC7VvoA`3B*JQ^~nu}pte^m6W@A>a7{;?_!T|cj%QXU@9sJwhe%#9(>D*OF6D5V3N^-!bX z14_yNdU7t_{@}7c)nK6RW;n*QC+V)Pwb(@m8VW=%0Jsi$G`uoI&(dlwMSKf zpm}|Q!I|KVcKom7`lGUk(>diJ_0kt2G0BJWZIT(XMu-32N)h!XovYYr5Jo2=k;NyYOk^2FZ+0$_1orHpeXb#MM;2I zOsKN#iE>Jv`eWi1QOgfv8dWmaewNC0v2ugEnD_Tf zQ|@v3n7%^t@X4}S1z&bkcIzu9o%O%-yr(_1GH1#duPGby=yYoKt=nJKg!#HOb$U{uxo~#! zc;@aaFIk=r)|W>N$uHdF$l(n;;P7bU0PZ;T5wuYgwG}P)$g?fGFCtWO)K8ZW{d#z8 ztcGp(eD&@R=7pDv{)z{p5thJIo0mN_Kx~mhCWAxUTAt@!oI0aJS)>aYVmLNAe{_U#f`2U;U3vYv@+ry)?W)T?J&<3f zuT%XnH#%OBE=PAmpL3L0Sm~{03}u;-YyPb`gUC~bVrhP4ogWs(EQ3gRM7>)aW;+{Q z)K6Xcf^a*RF^SK`sKX{vz7HUpBimt`^4BaMwmKJ`Z;Jf6(b@B=BqjP#;L!87N zCtaT%A$a_&RV-KiKt-SvZ{x zS!;;G!qP$a3vG|9CVUR~J?FfJJ1I@@fXkmJ_W1LlQPL4MTtTD$v#DXi5!-VYY{PXS zeboC8y=jFuZBLHpTnieF;f<##d`W0_o~|&HVE0ku5B^gfq}}93Uc?8e*;Q^6lvcV{ z7EAG;u6S>mEMr|Z-=WpZPYchfv>qnj_p z#I`uD&oc=rQldZ$aOz&JjBf~ip8Wmj3^x89CExfwfKELpMorC{7alCjR4OvNo!*qc z19b+;t4{a3c8L1ZEt{s>UXy$CN((c0&tt=Wr@8Jlt%4}?SQhzt|DEUdiDT`q*D0LW ze6(v#-xyRj5?U6GvrUwmwJ?*)CP?!IoUK?CxmvaGMSPOGR$jb4aCS7%Qt0YuwIdx< zgzwgVt-QU#BtO9sX5z5*@HL_3nF|+&whJa9CgNk9O{MnZPflSPsWV0J(XpW#`lKS2seyfCiu%#imz!Ac2RPKe(XjnkqMv1n-cq0XT5tn zHZOC}E9fT^wub~i|4yJmANNI^yzOMxZDy-}Pqtlykwa%Bh}2%wVE+82c%^!$bm?o!_5PeZ}SZ*GB6Jb;HFp$j2ce%aAj~sA$cT zHgB&vH;ORSBfcf?Fh;-Q$nM?eLcfCKox3x+>@>707eTYBg5 zF5=a*PrBJucqVRTbulS4&pgXXCM&b=`gwu`!ZG?^S|z>Ix_kfSQqC1C87U7`BO?h)UCgVYcz>|N8;PnVXT`t|P!F_ClhvAs`!ZFJS0PX12o?)MKHbR<`JuM(CP z#88EPm=$50`t*&l^CfD_k-AJps`jf~RbQFXaz!vIyJJ|YaV|>GgsJakbjwRY<6~Hv zog2^qqq$n`O%$L1OK+Cfi$Y0v&n&q_I2J-G(;I>bVofoGxCaO7mt<8!0~=+1cDW8c z;~!6t=UY0Y_4daK|G5ba&5Kqc1Ii%V>-ABt|8J5^-zKtdNGsp7!C`BwOyIYJft(^Q zj4Dn}VaS|aFnimHimz*2a-)Bp?u}cQG3jusm`uf%dTot(b&r<9tM>Db#ArV3)!dYD zH+aJ-{pmcyTjfqSud$BJpWvYyk9pJ&yttqR;YXX8P=fP#fwLGz>LanI)teRe3Q@_*CxJ4<#=aFkj0vzleT z)3g;;TcYzC`fl!gdCpNYY)?UO#m<^bJ(32?XLO&iDovYjd`d{d?#}Ji_4YaT;jPTU%yR4@coEKGhV$u zvi;Rzm!}suzU$mn`eRY$ujS`w|876~?cl$A3!lvt+aS2&#Qcv;sywsOXYPoM%@pVV z-~W$$av-nB=4}UbSXhfM{E45m`S}qw#`?Q`mkmT(-cPJ(KXKin?{1LT^Q?%R$h3#=*sr^j zYVO{-q#bl*$)3R64;xh6JD%*S{I}-X+$)TUy$hLr#F8d@+Iij8J?ZQ!mNOoMK;i+-hn43R#1|Q0`|6nu{kT*-j`Eo;YWMoBxTt{fdzhKkoTg;;o8}4Byj4vm+;dTK?Yl>rd(mueI;D zUvijrD`TZ#2-l4@jD|nNk9sX!W`0j$&(3Cvg@2aZ3Oj0D|5Rb$*1B#jwL7m_a#uF5 zzR9|1zP0ydt^H@NHC2}9`uV>UUUGDHIh|<-VpZ`N! zQ*6@t{r>wlYb=*PCZ*k=SyXG;SGw=c`Fr&@?o65&9;l~Lzf*9k$oi*mv_Aj)@V&Ul zprXuGigf74mv$pO5go7WysW#fdOZ9G}}oFC)s$yw)g zWsr_WWsm@#cZ>j$ypshlh)zCnPM@hMAI#)Cug_Fl1!jf-nda?a<}4s{S~r;a;JiL# zc8td-*Iu$^5;#41&m~p14QD|r E0By<+x&QzG delta 22906 zcma%jcRZDE_s~=!TC9TThlIc5PXFHiwLa3(cSEux!$4Fqr3kEZg>mnpJGUQI9jl$VMC4#Ltsf-mgsw}{ZrN1ItvVCCE^}?x z*y7yTd}S`F!wYQvgGqMB8IyTE8l-x=2nMW zqa^&bEw3a>l?I4kRzD3LTrG*85gxDK)|s4O?vi_Mm3g?=mh~~wQF}w2c7^s}n%2Ye zPsXz;kz7PVgxv>4Ow)_iC+nl8PepT*{Ax-WI{j^f`_wJxT8o}Z(G1QM&JB@ZH@?bX zdy9*H-F4Q#37&R;6?O1ifBSfK)tB|X#<&Q7qV?l%UKHB|+2yI~;Sh}?^g17VR4zGD z>WSXQ*!PnAQ_s>Czs?7^%e})m?Y85sAnU6T5#0r6M*6~mC^ zgzVAxwubpb%W_%Y%nBzVKkO=ot09(yMrH6Ak-P~h$uBPdmjf^O7z_of_?xWtwcctL z<%ylsRND3bq2KVrIDzVRJ|!h zByk>im^d$cO+!tQ3n$mAO44Iv>b3dY>1$?S(FZO?|9~6GtfXFp9nh8gOrAD4p^GPJ zUxfXdH`QqOGzxOpdXYc(YgkI^m_uDm^x1+1JHxkRxy`a4s5AnfPSJ-)f3ZzSIPtOL zS65ffjDh=Lvct87L2F5zszJ7~Bjx)u@^Z$zx4X{^EHqlwkoWptS_^wwc<*x7OM+0Y zvmyRz?`?ht7TNh%<%C~)r>qchGn?6r>{8AH&Bk*Ie&h)%V{A9;ANwBpj{V?@du}1} zY|Bm}@A?lzw%HRkhrYY4DPq3|RuPB^I~)+zUUj)G5dqZ z)~c2n=1mVAST967k)4IGp#zsr1T1i^o?#hrpa^t4W!gJ`RsL4Kj(HhIxZ^PQ57B4s z+1eu*v%sPVJ z@Hm^U9aolUR_KvWhAzd)Tu8>G(Ph&0&F4--+dek9rqdR*yMEL;}@d0dND504XX za{1_f=f}2=a))TiWB%EMj{N?stP0Wo`U! znhBT;J|X*jlIhZmopEQcCki)XHIm*AVMV(-=06$A2-B zmnNTDBlD*Yo-?SCeD!k^MR!~r_0hVdjIp8af=t@Vl^j~V_)x!X+6Mi@ROzxNBWJzx ztLV>I(t41BZ{PA?G7o%TebsgQURTCY^4nb&T0MtQKi+8@^A|(M{k922Ps(TUvtP^U z+^)M>+^gkH_nlef#z3#DBC({j|CC(&qWjC35++B-HSR3F*flZ#-H6%XI_+uc1L&(K z<`^4M-t+9ND|zm&9QRMHM^5%N^1hiJo9ey#C8^5O1ue&M4w|~FL3~eTNl5w6>$Q+F z{^cyB>@M_jIKo%q7^9U(`j3cE1!YDn&-96iWQ8C`E3fqFhysNcMl0`^b5Bdz29oc2 zE0;2Ll4GN6ZT`Ps%>VmVE0Q0^jjda-mfyNzs~I)aVD4lxTe}GISm#3%ZJuf{6DG zrfW?Gy+BD9dFtr?iwHtx%yHQnTWu<1bqA`u*P=@c-=Hqq*06=03Y|O_+u%ZIiecm$ zblUY|J&jqRmq-pfcjHrQ?Bw#1mtjw&F5n(PKX1P5d?Lk$d-(JE z%fcts7jOYTZ@*l4Qq4x!NR&Xwoh0ZlR%9l2{aB1z(8G#`o!2gy8g9c9Tf>rc%x_wo zQA-2*yi{M?awhtv#(?eORLJ%>6FuAeucC(<8aOTqclZ@MQG`4zF|kb~G8>h6PB&Tm zS(H4p!Sj+(hd)OOaidnFV~b_2($ZzeNFSm^)=g=pQYdnEhqZr8>GeAL?hIRVhkE3* z6xK~CrBYPnERMB*Md|e<`fe**bEtYG8Mq*+RO%gmxl&R|*gJA|m9>9b=^I*=ffa4c zK!Q#@eI8wO`Xm7n+JTlC4bh$iZz41a)p;}%)k%VHXg(^TgV}*-Pw>Sv@C5<7mg*GR zgpLgTp6WEgHFVb*cJ#uTqwt%+4^6_zhCa(k0qKfjK1`ifD|GaF+{2Y<^tR{6eC1## zkM8QomucgG`y*AjUXtGql{xcoq;>BPtVf!PItX?i#Yj-k#)ov6?+7!$UF&g@RX_FQ zjtn`L?AH$yi8XPWGDB_RQ8%|sYmq-pSkuX`U7Ln~5s9qG`LSR4EK1{ia79eOzB1={ z1C%grGJC$hR#A~DB;+&vi`4$-(}S8SubeK8dGq{UYQ-#6Z_%F5gtb(mCw~NA>=n7)W+WhyOzvYV!`nIfv%7kAIX~6QeY{7#5@k8Lz;v89aC)6& zs-~6lk$~(f!^O-Lmz^?4HoG?{5bOLoJ8n} z%OA#$M4vMV4Zr+h;z-gtpU@LxAATOmIEQYhp+gVT9R24_90`0#PD=sa#OTP=yuhs2`Z0IT^|UQuQ}4qAf}h1G@ML(dG^Crel5%?EF8OV>y_3d;tDj3Eac(!K0#BEH%Vnav@$6k(vhS8~ zQkv+%(&-oWf!q%1#v9jeaBB5>j1Jnp^PR?pzwvM}^|gPJ|md6oO4sX&U7 zlS*zNGxNfx&!tn815BDx3ai4(X*AuhpBZ_2t@l9*Hea)xNz0UY8m$%|Jms#K_A%gR zx}Dr6_}uPNpGkGCjDNkqp?#Qr%c!$=_UW)z2T{(cIlXbsY_&A2CT-lS@HjL((+P-o zmu$0a+Gxh5!gqZrDkyn%@-Xj!4OMR;{G+ehLUUVB_%xY%y{8ds0#!h_a%lYfX{o$T zO^D)D>&H*uYQyozlBw%Mjma?C5TI%5va+qpII23pMKwWmz9BUo6?q z|CX$0hDa8DsCBMkkCwDs#6MM$fhGsfCj=W|hHIE~$n}(^r>3?vevf9Qs6UatGtQTH z+*L(B-;Ack?Dy~a(T%J!iI6ij-#x^6$JBkDaMC~SR8XJJ+C8^(_-#=0{7JFPuXjxr^U{W(%9X!^Cr=K^$MDdi_es=yD@J4+Umi?5GjK4CtYZC7`c+}kv| zyPDil)wg|9Gmdl|%CF&$+nE`6+LTLbtdVd&6Z@s??!*)=0E(8qmB!At=sk@J+c+X8oQ_UE&m z)^)w@2q#Z*lwfy(+9|!$l-6gSh3@9iu31!z(ru)ios_7Ke_jO;UTFgjdOo$Z$Dd`NCw|!zY;Ad%xNvWF5ewFF7TC-@a6OM zVbOwi$Y!fl`fm5g=h)FlD@vu**{x2)DyT6E&ai84O$Iz-yZKW{C0XR{zU|UAcP@5# zFm)%-p)%HGdTaFX9f}C3^}{0h+M|{<%@L|*d2r?$zbb}tpGjd275dW9YmFU-@dp#> z#k&>KE?jWP3~MmbVkE1Ik~lq;MsTWoxR)U4=v#0XkpWTjk9+BAx02|E_&fzrf@?3A z?tR|1R>5W`B6hx|kY;ws$MjHQxRl5m3u;I)VJfXS4cr4gyT0Ruj`Ou>MIFGx0%SGpc>9>*)NTU*e5U|J2@}%qlFDaof-*;V&BN< zj(o^oa8${D_50k8)^ zK_74BojDg*YB><|^w?KPyH*uKtxu&Y+E-57wHhFz4lLRtqAo1@Afg^Dh9IK;tK7S7 z2T$0wzJNc5+=8zZA>wUVe2<6*u-Ju&hOqdJ5Q1+ug5_Vx*T%4TAmE+yg-ZuMmA09{ zA5Rg1o7zlakrff|z@i``n!%zRBHo2XEkrbj#k*jYYXV>uQcL)w2YiL}9xOgVL@QW? zo+Gj~EWbiT8(1tyL|a&FLPR@oJnKW?c!Tgq6?^!~EFwC<;ua!0!Xha#e1j7#G9aQe zEOH~F3s@x)UgZk>F~s%CX~?cs1Cia}yG#(#9TpuC@jfg*KtvB%3`ayySbPx(j3fyg z$qWAY2ENkf4T~QU(FYbkBO(eG#}LsM7FQ4vf<@@?6JVt)u$BDa&ooECGNcb-ksT5J zVNnzjAHkv`B0h#iJwyzE#e0Yt2#zOq7#zf*$B0dAl*uu+vgFl9Zf-6Xa)Azys@^Z!K>nM`g4A%7Ij`pKdfreIfP7Bp2Ome0SnpOT`1=n^P7>O;CyXnsyM7> zsa|&kbA3nDP1$HD@uKFAhe8{@~=RA`j7U(e6! zp`Vv>C-+Nhch0sKdt*MYXM5$@gmG>=HP<}9wG%$WI9@ol*ecbxd?Pf+#ayOsR(tfG zy8-i3_!rA3`rG-1xCHJB71f|PO7ELKc2lW40oR6?dOhg|%p4}660N@9N2LVxk2~d+ zh<)AQ3n9ja8gJ;X>E<(SjH^RCi;y}*dDHpoZsV`tbz#s}->$F&_;$|tF~(>8>K9{& zkw-L4-7lZ9ZLjRo242)nV#?U~x^y?Q*4Dp*Xqk+Pj+@a|{O9=9cdK5zE4QYMox;}` zox_8F6d%}S<`e3Gtn4rKmF_(-QpWq z<4RFNF`8$FY5Kg!WE9K!%x7KXamgsco(-Db4I{^vj^NH_1eA&@ z-o4?_DXYav64&CN5maw%K zwJQGoL@s0#^xT4a627BzFJkzeo!|x4MKiDX8`Fe@qliJbK;M z{H|eH{V2A2%)^!&)>Uj7y?2K-?S+W?htA+1hlR6U$F?aTQxOF zviZD0L_$VI{za7Z9#qNehcT2W-Qf`W#;3YhpW_^3aE9>2edgf#sx8lPHC%oPcI&K}@j4)UnI<&k1LG zU*)xUty*j8`TpOY|Nf=ss#!eiKbw|a-By*U~*E-#f@&|Iu3zJ$p0FSJf2&!y4`sHnM7tZQ(?#CftwafG3m>x zW;r+87~F84SACV9NLXH`rs(Bmxa^zbRc0}o6+jd`u6~ict?(98x1Pv3hstIWOM9+V z`!F4&?A7DMH(T%0wK1qjd$ic7bm#`YGhi!Z5Hp%|D}r3GT_%er&xqB%jy~C1z=}sh z*v%@&p4UM?&fd)=KNxqpw3nEfmxZGv6gTeVd0nWdn@Qzjh*gnCk?L(H_oicSm#1bI z#JI7^_LB`$&MhixsiU$zCKD!;rNRRGOfh9{3Q1xjbeq7tttpy}hcP+lm>y-_cPR86 zFm9(D-hnno%3>WwsAICpn{rWeA8jzl$KAG%V+_(SjPePdIm-vGT7Zl)X|F#FXpCD>iN|LB5{h24?G){ZsnWiw6gwr-cFJMm|d^ zkndvP+<3`of^?M!TaETc60|kGyQN9>W9#>tKQ*+w*n>?O*;!dHX zLjRwZMM%ouD^*cyn{gyMx~m4af{lIJWbAL&oNSP>cD)pL_#my0K8wN_V3ph&o;Rj? znQM4At0&T$l4JaS=8}hd65f5v5W#j#uK0?%JBD>^-F$@F@l=0L{PCnSP*c^x*K(mv zfW7Ly;IA|yUfO)U5G))tYjq~DoXVQCw!(TR(qoNyIa@m_!66 zzxL*qt|c+Qm8{z%?uc{vCEAAX(ec(?+#F_akzNcPzD9I*@OWcCrsFKp$A_XP$SJP8 zykI_Izdbld!YMK$wjAm@5&s-|6Zh^A!H+8viU*#?N5xgHI;m%e^~Bvz7wG$#-tIc_ zt|7I-|8V##rMQaQyK7N6kt9zAF&9;p0Ts&v8wTq?kJ*(Kv#wTP&Lve`xL}tl&?j_U zh>`VyoN7zk5biBjB5`lKH*p;XeWIT|!VgdgaR}U>={am~td@sf3;__3@FMM_Lx3U%ATgg!t%LO*FqtneXi7RkIcs8L?#}R|MhbG==ODf5Tp$Ygnplk2?lAWZvPiI4B5A;qD|G0Wk@pF3HU_QBbJ9uvH zf1K`1AjX0zCcGm=id2Z|qu(F<*V)h9opzyLue%W;RW?HxO!xo05cHpw_-m%V1loCX z0+akt7fH>M{hx+%_kL{TM)rT%yR7Wem$*d({?pkr!cPdD&i;v`BJA(qVgk4#EfAcL z5S7qBW_Q2+P|vc#r5V2T-z#eYC_Ne6@_*C?fmb(N1UtK7`_kwCSP$*_Re9EP= zp!n6lyNkd9mAn@R5Ry*v6W`6tuGx-g_dhkyyhBOL0(vkB&9gy-IoP<&yU~xKo~wjST#U`Gag>W>oN0N&iZVPu zWy3mk8dmNHk!RoK9y3pU9~lteW&cs;Nk? z%&e9gYGaJH{2v9*~lL1=5 zL}X$*&6Cvy_*J)ujMS?`dgj_3R=lwD!Mu&6SDbt6^2Jz`jCGa3=2s$j>m|{Op^ttIX-?ON!m9H!CD&?el?mO~x>Wr`KR-npFyobTM|i+PIIdWryw(o!t*A zPH#z1@9SkN&x{#G_NUZ?%b_otAJJHd9@ zD#rT;Myxn8w>svgHZ&+Q4^%50T&`x!VU=6}=lS!jceF-IVGTL9zvba5X9T!T1rVa7@;W1(-RnOlCaS0zue za})SjAZ2~^!C0Fmuz=;xkdXtud{QH&vThOP{+tNrfQjPG{MEAW0$kn8)kXt1b~hOn z2Z66C!0uU^qQ~;Pe@2KKcp@UU_P@e#PRz zpAz4_EiC`;Chi(|T8nzh)0kWvZ+BRUsf9H!EW?!A6g|d>?xtb7Wnm!ae`Cxp(lu+v z`?_}W#_VeMto3#U@WH=uRQW|wfogH5;PFreEXiYt4k5ja2V{nUXl^K;wErm z&w6kOz#^TtF2)yQ6i;fHyaAgyNFW6Ry8+IEP9ya+PE?H%?=v5s9$*j;acWB`5VTP9WOApY-x6Azq%pjkT%lYFgLyATA1#ZXKNh==Sv=r;%%*=XQN z;NAYc7|d8CGY3(f4WiKKulut!qpL>*1_j@yssNSXijomuX}xFm2R1lh}1NE#SIepgU^XLa2;BwofkfniX>^U z6KNz!&dXasH4w;?(nZSMBdCDNcBP+Dz6-B|jL7|ISy4kFf5M;bDtrf~u+M?!W7l({ zh`9MxQSyh{|Kw&_|54PS$b<|j1L@VfPXKU0lE(v00JRW_f-9t5kPL`1qp))FC4H6R9CyA>aJa(f7UjOP`xHk)f@sJ4P}_L|AdSK`V465+CPpj+Bp(Ak z-vLk%%_#vGH-0*qN3p&d;5-3zD{I$70@dlk#{+;dKs;(NOa&@}O_r;Nhb~jp3EQRK z#9=ZxcYZiUecYkUh3%fD`X| z3M;u#o{Ctas__2(;g4Mo-#%97PSaa4T#jg6NxFDE$s~HOkJ<_@Yq$J4TFvKu=i9HN zEV6f>0zcFvL2xAKWsWjr^9*kVSzra&^>VeKPFR*RT+`G7!8>#VvGO4fqO%Z4@-P7o zK#}@qoVevRwc#2lbm1l`4K*Jn@~9g8=%yEg2K?yeP@hfPD;m-ChcK-fO*{r7PpWSG z6};)lLbZ|Et@`&)r{!S3vFRXw8}0gY&A$GDDFx!IaD!z4O0d_UEZrjIogYKMF{++F zU3+bS>rD9$z#)}*rMir_)#^fRI+9{ z@)o#i#>rbnE&J^#NbuzE!V|Yi861&dTbOZbBFu$J!%&h7pKZ@soX!kjW;L#LU%WxAJXdBW2tQIf~&K&(%qFqO-f0_?2ifEOTO*{8+3AD8Bd z0`C+l7i{|a;40cynEO#O<-4;EQSQfWcmb8CYV+^{m&^`O06HWp;I9o+kVcDB+K)G{*Hq9# zn*}YKUUAt*VNECgOeg?1o>kDsO$ns920Kff3Ph0v9r64AO z`y~WgXyvutCjOc|Y||?*Qh*7Z38r2h?d&-@D?`cOjk-OKVJx^nR|9|fE#L=SPe7Iq zhQQf5M?0UvCvpzC+V<`Q91SA=+K_X*B|sbdhK!NH5R~q!cAL>xo zLg)joy}cYUDbOfTpBkwM79hpVFh+hk0yS8H!Ru!B*Fd`nGB=@?Y}^H86EM#C`Q89? z-2U07R=_pRO-R2o!C=a5>_{DSo&Rj_SM+jC2qVp}K@22nuO!E{5nhr=B=hb#TSidW z=PBK(+fxeQXQARvTy??yQH~aIWBUeX5m}C@IWK1c*YlW7uiN$wpBmfC?S(L_V-}>? zl9}fAuIPR&`0%r3w#=|FEWwGpoK}{LYovfpq>cnV41US#b~~&?tGII7#%EctxF8-g zraB#qh3e!%Qr(iO~xbbBHJz zhU7)^7O-(r@y1Lm&x{5(f}fQZDa`Y!1m-i`SGnJz({TjY!ng|9;=!E=pbNA4INmKS zh$Wy#kmymv3#$d#KDHbez<`6E6bE6@b@Mhwd47d)x$9fkW*D0g`}NjEeKv?Y$#Y# z32)rLp^#zhD#=deIpY}+9JS*9&-wMURCi|%_2o~DcvlW@*68i0>QS%g3Ef4j{ zDtlE9-;7V*tQHu=8y}=YIKMaIAFv13Ss+x(z5#N}wOVr)2$<`42f2dN!D-^Oaa=c& zP{2xhjsgK|5{3ugbd$BN1t#02?6y3jBM(Zq4b*W_CK>$9l;3hP1 zqf>mh;pS(c?R%<}z(LZCHY6C|@o&ym|0j~Vp}ic1GZ{9cabM+rlz|WcDkS*66 z-{_qnt&t7zVCO6~9wj=X=Wb2`bK#+ByL4vNNg$M7T{9WZSREvDzCVt`fSkYPq*}57 z&3J)~&4d*d1>Wg&90!QivQBy*pa?)F;M_@AUo+s?b;*Lftqr5U&mxcFj}xAd8nu%A zy#<_h($_m+6Cem?l?rTv;3R^2AeF24!6|bk7%>9x7bp`>a*Ks^I3~^4!bq~BN6HET z$WDX&1Uijbu*3KY!|e9x2LK|~!!U?Q)GL0Nt`JEh&bc^Gw};lMnbDF%ldW z_l;qYMwEqseNiAv^*2hm93(3lZ|LmI!kH73;I!f-P;k2);AM=l#5%r`AWk(O|BD3x zcn;jYyXK2j1q*58=lzw1f1qg@;444_Uw8BI%EG;Ps@ERz00Ea!rF}osm0~@NPT5z2=P(v3SX` ztzBj91*^*7ED(jqe~_>s92!&vGio@sfsGE?MnvPG%X5ARYz_UbakBOSH}*gu`2~=D zWmhXLv!8bjUQ+QdFu|#+ysJ)btz7eU-|FHcaJhN66g){gzi&KMI|Uda06ZZz710~P z%Ie{VcweFHhMeQfq|ERUF=BZp$L;EP^mOE7ucn40+ zNh1&%AbsIdU{N#Y<lfo#5pFQn11Q32TN_>NRVdzt{B!-Weuqo%hxY=c;JuckSyuL5R} zSvLH`8ypwL#XQKT2007Y2nq(NpQ9EAW%0U5iD-!KL~{cxyk3I+9h955RRWj8oJ^*H zv>6T*CyE2bwavcGxqaG7dF0D#2W+?Vk|Q%y%3kl1Z*+GSq-V{*m)7o=Pd-fGdlTtf zU>gUnbC|EW0wR)P7`I(810^BIw%lTA?C_OQRhOd#W+`pS1zAxml_(6dqqSOR^>9)2 zimRkyoTO#BGWBni?*boS@ckkQ!UtS)scomZrN7}K-3m0h zsqEF^82x$)sOnHTOfT?hX<-w&K}kBcc(2?+jT}<8fy4v&uy-{&P4^^J zICHU_HVcHKI?PXzl8JClON6Gb48lM)c^hV_|76x*)4&B7@JxIi_Qk@C8Xs_g^31Ss zLGFJlNa+lQk5bam0p#Pj1^al#ePei02(Irirg+V)BJ?W?u4emXolOJ=BGe{KwU5^S zKv+NE#4w{yLTF3}C@gNd8{h*vfv;ez6U*F*MCqRzi`2<2dQew5;HF{nPAr}Zt-}-( zL^uREW<28lo#B58HBz!F;F7fw4416FSddj0c>wIdtpUIYgjpT7T|{ax%XxT1V4{C4 z0NjEA1Okn(mk_+#Q?~*xUvQ!8h=mX?4Kv$%*l~NS?&Gxn2EMLGgBkz`ej+eKS4#_G zIqD05ega!0f48ro#XGACYyz8s8vx3lTVPzl2T~8rs6x1|?{nTx$1>Oe5KOYw@XX&F zLBQ{i@eC2KD+gj5#2@>33`ozO{|A=y_ieMs*Fd8QIDJVaDE4r^?Xh8`IBsJ8#x2*# z0-{YyCxn5K7pY}IHn%o*-(+O=8`tMK!-$zUFUZ1>uEq9ymzT* z`bZQ#=RxlU7fIO`-r+UU_4cTHUNeRlbMagagfG6TgHXap5!m?F20C2r3OcW#4vc(C-h22M*EDd2zu;z=EkFjyDx&JMskeHUNovFQP|Att1Ydg9^ogVz-O`s^?FYv;k zQsY~27;?A(GcMvmAQ*5ZB)R){Z$9(dI|<$dNG;ai_-EY|m_vZZbU7cX?C`RHxxl;- zvD}^k#w+mfH3{t{;j=7u_!vde_p3($u>Jbb23k#gmr}ieG_4MO{%#SI;9J1H@uj!~ zG7!yJz#>rw6GIo;>p1HP;aG+EW2?$2*qddOv2khBOT!Z^hbB*t@cbvYz zSpxQj={_89YJigdAMUL2*n|J&$8d|v1*3KUE_Cx5Xg!fe42dle0&vTa$_0$82eUkc zt#tMuYX1FsHDhIegaP`Ck?$Z%;98WPvZ>#_dA}TPJupb)f&^bCXrq6Ct{#uIf7(h~ zdr+&Y7Eg^Qk%KOK8^SlM!!^jJQ)N&f77RFG+JKNUr*Rh~|0LG&!;z_qJ%58Udd^Q$ z#RAg5Us6E}2N$gx50T=R9Z2;2gK97ffCm^mIa**e0wV2cR6jg7p_A1e{uh?FI@U?4 zi{#KuW91QLY2_MaNPd4R0m>p6O8hB| zf6}zA(-2-UAUG_YLuc#n1hN0(sGa0zjMoa6K=J^0*;s8*Jw56SU82gXM zCrOqEJ8!^@8Z5iqa5Jj(P(5%%iwn|BfcXjBxx&qVH3}Y}90oHl7uwcY$vSy(3p`Q- zY}4Hsp2H1$1c^cW**xNbw4JbK^+N6Nq~v2zystfIayJ3^{vCPLYj@Wm{o3@xb{Auf z2htqZC0I9PZt4E;51oOMnsL0qAZ4;Evy`hXKKhhO~1g#dqIr zFRPPFM=cHZtVY4K6lTJwt-R)Ut*)z175>ofDJfh(2&@8AZ%fEnonvYP8v@kBz8kiI z8K&pVr&ZVS3QKUMa~rgvYY5lfG+KBI2uMCm7pvYFoNkva;Kz8a2woC?7_*TgFujA{#NP2Dso-fs~T{2n8lip zmlS42_2V06w^0sdfO&kj<`6Oi^e_c{AKz#6fh1b_a@!Te0pQ773-;{hYcA%k$P^Y} z$9>E4LOjdMZ={_Ent|uIrT`s>n|(0JGTJNcYpVhOnyM2aV{pp_I|(-kTo4HdyaR-< zN|);{-at(PG{T>10VeWE(?x$N$$-<~b6&Q-AN{)a6=ZfMu4`?V1)A$Jy?L1x?7_0Eq6+aZ& zi!CsI;DJnn_ZU!~&p*Hcn&#mR4Q?q!BY=tcnJ!HK?M7xW@Q%^QG^`GQ5q>(Iyf;w9 zCkdz+U=T&lfiU!a*0K0*@st}Fz#v1klwBtCaqj>K9(oOXAx+MHU`@h9fxo;E{Fx{w zVR0I%<30GN^$|t~q86ci_!x*X0_*}0*njM^u(cNgfE)iGR1lcX44h;ICaLhBBJkzb zx3Un-;5`8TEp;HH3_O|hFh%}80Onj=HF$JH?&nS4o3w*!1dwsW&N{R+Ig+xA zTd&#K+$AWnxs|AMjM~)g%_HzX$XVt^pDbpCusT%3#7*K1G|w9vnqHf;O$n+RbP3MA z3g?iI3MsARnpU>B8o>>bX64?|8C7_0*rh#4KvZ(ZmAblFqSzD>XP*gziJw_xA#+T4r&&wzzEV`=2Q(N5kD*?My|iq3$k+NFn{-J z{rK8?%EHA*)V2}y7FTiBGeyfAROWu`vKQL#jD7nRoSzo^^!^IJB;ATa44-dBEF)%c zG{V{S>+S$uuR`F)Ty*2d&(a}xoX)?V!Tov)u?>t(NUQrO-4V0vt4XL+!IR1RvFkl|btcvR|Czxpv|~E!nY?tdApwXSMQ} zc@3!QaL!Ha zD^GiMZWg}NjG+ zh~uT^?+Pu*`}hnKWhZ5I(e4~s$tn6gcka9&D*A+EXJjeOpcfomZO0F?Io{AMUb-FW zNnfM7jMdu|JvMsD1l84B>u+cs;2Js7fgO7!rQi4NSblXpol^TjDW<81Wd2qYnPdZy zc=_GF8gJm5bId zcO%pS7v_fJm3SWLuHicxB$_ezctX}V*p}tskblf*{4RH+(1L!bbiNB~jnd=HnHYYX zcrT^O@5*UgUpgJWlL(y&tz%zX!bYjSgPyLg@_B#wz|IoK z&8fS^2nD~?Flxf&=iX)TQc7!Iukt)Qb>n>%NA%U3PoxOKnx4EAWyQ6r*QConySPF2 zwVsEtgV6i^(7jdIZ8 zb(7r}%-Sb+uyQAvJ;@bYSiIRm5`|IoHXC-l&1$8f!|n#?w7MKS`T2CHC* znNKd6dFCP!TMH&UwEL9|~=P0bCcXGL0i8}sJ(++j$Tgm-y0fPAK zv51>2S3|BIxpqvmfaBs~C^t$+{qDOr?A=j^ZLiK3$V|5-)OAI8dR6MhJ)+GzV51vO zATRa$1cipn-SVJAb^tvN=jA=*f4ot1)WGEUS=B2a$m}>hw2h22SIJvCDJ|=Z;^cQ) z9}1+lL|xT#N3{CsZEB7DdnnKG$Yvr+yqKwAH1uxEA)PChGK%>e!ap}QO z=vAzZ^^Lv=<*UC{&Wo+xI-fn`uR(tmgKGE6^1cKJbw6);=%1;6!t%tlrseECTi*v&x0xu*8$!qz=Fx_zcadLN+jg5j`D5g`4X90X zUzkl8)(!SQY`s_Th@^)jpM)*{i&V42IbJ{0sfu0)mKD<*4r^6JT;C*v@|zxKmDjxt z5-v|9w0*ej=C>vI=%(^{1|j8`u-6w`Sa>0JLsOe14qIbB`%_Ie$LFvPDm~Vp7W;;% z+`@R>Z%w?nIGNC4k|lqC){@01&&DsYpS$6dX!4N=0;*=SU(&YKTj=^s=lB@EI>&Cd zqRSVJv-@wF&c^p%G|Mu2q{Gv7)KHCQ8M~WHvh_=?q=TQTs6gf0o0bQpAq2g$(IQe^ z&}kWiCQX8zyCl5#l+!TpR|WhGB6Hi#X#!+AB-Ds$6NB8?)BPSpiYKyX)a#$h|BmUk zQSu37DVW!T792A^-O4E{iilk=_#xvVTl>o8`?oTu?|!D&Xe|TL6GBA+R)LLUq(o17 z=`E<54f}$JNIlUi>(6cPPIKO>)AFm8PlZO(4~o$SLPu!h$L%902yAes%-v&V{6h~& zqZ~iCWTx!!3EpeaKQpxRjr8nhR9o~GP+P?7V z499Toc~#A_oCDo5XBr}o*NX(AgGZMKp19zuq?Twks(CxZ>BC*#1s7g9U9F(O`2p<= zksS5k;P_^}W;H7(nRxPEbFFMYZi})wI@t80$?<0-W?N*m8|_6l{l{rXHKDI=OZ0(j z_a4+Vy>9lgBkkm-qmiA~KmP1pnp5Xb;cqu3c{+Mj;v|(^xeiD^Vi%9NP4I@O>A+`H z&`L06e$EAj#Y1t9Yuhq)r*(cE=ws3ixq1pZeM>*wslWa_1H~CN3f8X12ZXKci_^C4 zBl9m_U%7oiDeu-mNQ?S>hfL1r2MK2?#P9kPcC%H>EvxmcUZ!8W+FdmeSaGD>7bj=r z@W9SO{K+VL*tehsX44KZ#98y;EPSS#Z)U{&se1sHNdPvo**GHfPv;DY3?aJ$IfE8l^4EZwI@zkH7kG z{lUe3OFz5`Fon zhaE}Uh(&c@us^So$vje0&U0l@JvbolTdHUx^?PC!n)U5pS%wjWz zOisRiMJ$+VBYrNePr&2RSzVP1lXd3-q2OXl#V@pEjT84snQm+_Vx6U`Hh*$GEj@BH{vd}5Zp%=6p0I&%i?GYGUna3uft?}HkF~(7Yrd}L z*kdKm!g+)0iG|GL-u!w;6|MFo zdK$q6FG#-j5bnM=^N6PWNi-eERZV!{Soq5~epo}*$`TPy?sxA^q9sQvoPss1U!1vR z`XVRezzH`uGTbk&86o2QwNZs{{$$+G#a14AIieJ4STc%^UEFqSwRCvCaK#zMvVMDc(U!jhN zP3_j5(0TC?szUF0T9?R?L|V)GRY& zlbXD{xf=sA(8D83XNWIx0kZ za^^434Ok1XiZz{{tHx{&&@j;p-_77?9w_B&RmHAi{Yr^8G*EP+BK+^-$=OZsUF(z( zOo+;HdNef){nka1eC=ZREF^g_n}dNe>vO3Uyezxspmr<263iGP?w6+UGA4^y<=Y!M4h@G%&aSk=}M7h-~Oa^<5`Rt=6hOBXgO}` zA@=wg@><6NQ>a{Pr0C;p7_nH*vD29@b-n`jMYXj>(k;6I)-}&X21K3O8|b4vtaget zvPR5CnOQdvm7m&Ho|*qp+AzyIp9Iw&c${hOxEX(Wk*4bSvY#4h0W%q{fLy`v_R3O1 zK%fY{u3#0)5W^Xt9Wj{h9zzel3;;jP;4*Wv((x`p@h?RaLv>f^TaJju4g zOD<84MUd*$#>GV8rsqVHo(JleZmWg`HH!Q02poLEGnSFSv2;-F&94>CE90G~!&`XV zD1t5T)W^8e9$eETbgY~AF!i%0x%_h4KaGOD%lua)2SK;+cVWATMd1>P|F^BVFZIo< zb}sVdn;u#4;NZFi^)+)B2pkLjUm;Yyw8ebciKf}}nnLS#rp#FJHR4_B-IrC(E`>WC z!UXut0`%_{eVr8Q-_X$gu{rofT6juk&7YnTY?&v_EW43(LKIr&r_!O?kq*{^qKBanaL~(r=hp z#aAi(UHNq9hn)ebdOB0TyYG3TcDI%1k-^#f%0EOlxm>-x<0;#V8FQmATWTEb63>&; zpYA`)kolQNv0&u#b8m{>BAE`K|Ni~;{rTndy4p5+9-i@SlSKA%-p^aC6Yi}^ytl_L z?REdT@3-gneXH4U!U1^7!Tqb*Kkb_&eQT3jlV7bDzW;(>c&q#I^7$I?A71=-v7T|V zVY|rY2M2UmSlw3iESj=e@TeMNeQf?^1Bur66MyheTwnO-;?|P5S%wbGz9FkzE?ju0 z^E)?PcboF6{5IV>$BtvWS(8**Ae9 zmRd=Z{7zr9j#yypQWCqrHh86Q3dk)>r3xB8P+%sqX#QCT5@3*hIv7=6#b;Y_Z zLRt+zc2~4H4(={L8pPI`KZmcNl-d;ekj+B@M-w!V21!}?h0#jN0S26Ge3E^heVbe?5* zg+#4-pr3tD=?aEjC%zs{Tyyzp-KUqu#obkMM|+aZaxFyv1o=Fh`F;BS`Hva49B2Bk ze$L?O41Z}easC=D4SVHz3||F)J=Kr+&$jvC@k%yM_{qbQozM9(zMMSioURPw - - - - - Générer UDS/RSA - - - -

Générer UDS/RSA

- -

Télécharge le template Excel (UDS.xlsx or RSA.xlsx) et le fichier texte (.txt). Entrer le nom du releveur et la hauteur de l'appareil de mesure.

- - - - -
-
- - -
-
- - -
-
- - - - - - - - - -
Pyodide non chargé.
- -

Downloads

-
- -

Log / Output

-

-
-
-
-
+
+
+
+  
+  
+  Générer UDS/RSA
+  
+
+
+  

Générer UDS/RSA

+ +

Télécharge le template Excel (UDS.xlsx or RSA.xlsx) et le fichier texte (.txt). Entrer le nom du releveur et la hauteur de l'appareil de mesure.

+ + + + +
+
+ + +
+
+ + +
+
+ + + + + + + + + +
Pyodide non chargé.
+ +

Downloads

+
+ +

Log / Output

+

+
+
+
+
     
\ No newline at end of file
diff --git a/UDS.py b/UDS.py
index 3bc93ef..c61cb4e 100644
--- a/UDS.py
+++ b/UDS.py
@@ -1,658 +1,658 @@
-import sys
-from openpyxl import load_workbook
-import shutil
-import random
-import re
-from datetime import date
-# =================================================================
-             #CODE POUR CRÉER L'EXCEL DE L'UDS ET RSA AVEC UN FICHIER TXT QUI SERT A NE PAS RECOPIER LES DONNÉE POUR SAUVER DU TEMPS
-            # le but du code est de linker deux dictionaire, le dictionnaire cell qui contient la valeur les cellule des variables et
-            # dictionaire valeurs qui contient les valeurs des variables, le dictionaire valeur sera créer au fure et a mesure dans la lecture du fichier txt
-            # pour déterminer que la fiche du poteau est finie on met --- a la fin ce qui va arreter la lecture et commencer le processus de la création de l'excel
-            # deux variable vont etre créer champs et val qui seront le link entre les deux dictionaire ce qui va faire en sorte de link la valeur avec les cellule car les deux dictionaires ont les mee variable
-            # il y a quelques regles pour certaine variable les ''if'' dans la section ou on lie le fichier txt et quelques autre dictionnaire pas besoin de les comprendre pour comprendre le code
-            # on déclenche le code avec deux arguments si c'est un uds rsa et ou le fichier text se trouve par exemple rsa C:\Users\Antoine\PycharmProjects\UDS\PDF.py rsa C:\Users\Antoine\PycharmProjects\UDS\test.txt
-            # donc (ou se trouve le script)+(argument 1:rsa ou uds?) +(argument 2:ou se trouve le fichier texte), il faut faire la commande dans cmd.
-# =====================================================================
-
-if len(sys.argv) < 2:
-    print("manque de parametres: argument 1 = type de fichier,argument 2 = fichier path")  #python C:\Users\Antoine\PycharmProjects\UDS\UDS.py rsa C:\Users\Antoine\PycharmProjects\UDS\RSA_UDS.txt
-    sys.exit()
-typeDoc = sys.argv[1]
-docTxt = sys.argv[2]
-nom_du_releveur = input('Nom du releveur: ')
-hauteur_bosch = input("rentrer la hauteur de l'appareil par rapport au sol lors des mesures: ")
-
-cells = {}
-if typeDoc == "uds":
-
-    cells = {
-        "poteau": "B4",
-        "projet": "K3",
-        "révision": "O3",
-        "travaux": "B3",
-        "diametre": "H3",
-
-        "adresse": "K4",
-        "plan": "H4",
-        "code_barre": "N6",
-        "pro_poteau": "K7",
-        "annee_inspection": "H5",
-        "parc": "K5",
-        "option_HQ":"N5",
-        "longueur": "C6",
-        "classe": "D6",
-        "annee": "H6",
-        "circonference": "K6",
-        "p/r":"D7",
-        "usage_commun:": "O7",
-        "angle": "K13",
-        "lclc": "K14",
-        "nbe_transfo": "L15",
-        "type_transfo": "K15",
-        "equip": "K16",
-        "gradation": "K17",
-        "lampadaire":"K18",
-        "las":"K19",
-        "montage_HQ":"K20",
-        "portee_lache":"K21",
-        "portee_pre:": "K22",
-        "portee_sui:": "N22",
-        "malt":"N21",
-        "reseau":"N20",
-        "cabinet":"O19",
-        "luminaire":"N18",
-        "traverse":"O17",
-        "las":"N16",
-        "fosse": "O14",
-        "hauteur_transfo": "O15",
-        "hauteur_top": "A11",
-        "portee_pre:": "B14",
-        "portee_sui:": "C14",
-
-        "hauteur_mt1": "A14",
-        "conducteur_mt1": "C14",
-        "phase_mt1": "B14",
-        "deri_mt1": "D14",
-
-        "hauteur_mt2": "A15",
-        "conducteur_mt2": "C15",
-        "phase_mt2": "B15",
-        "deri_mt2": "D15",
-
-
-        "hauteur_mt3:": "A16",
-        "conducteur_mt3": "C16",
-        "phase_mt3": "B16",
-        "deri_mt3": "D16",
-
-        "hauteur_bt1": "A23",
-        "conducteur_bt1": "B23",
-        "visee_bt1": "C23",
-        "deri_bt1": "D23",
-
-
-        "hauteur_bt2": "A22",
-        "conducteur_bt2": "B22",
-        "visee_bt2": "C22",
-        "deri_bt2": "D22",
-
-        "hauteur_bt3": "A21",
-        "conducteur_mbt3": "B21",
-        "visee_bt3": "C21",
-        "deri_bt3": "D21",
-
-
-        "hauteur_bt4": "A20",
-        "conducteur_bt4": "B20",
-        "visee_bt4": "C20",
-        "deri_bt4": "D20",
-
-        "hauteur_bt5": "A19",
-        "conducteur_bt5": "B19",
-        "visee_bt5": "C19",
-        "deri_bt5": "D19",
-
-        "hauteur_bt6": "A18",
-        "conducteur_bt6:": "B18",
-        "visee_bt6": "C18",
-        "deri_bt6": "D18",
-
-        "hauteur_toron1": "A27",
-        "proprio_toron1": "B27",
-        "toron1_existant": "C27",
-        "deri":"D27",
-        "type_toron1": "J27",
-        "nbe_de_cable_toron1": "L27",
-        "diametre_toron1": "K27",
-        "rupture_toron1": "M27",
-        "deg_sol_toron1": "N27",
-        "ancre_toron1": "O27",
-
-        "hauteur_toron2": "A28",
-        "proprio_toron2": "B28",
-        "existant_toron2": "C28",
-        "deri_toron2": "D28",
-        "type_toron2": "J28",
-        "nbe_de_cable_toron2": "L28",
-        "diametre_toron2": "K28",
-        "rupture_toron2": "M28",
-        "deg_sol_toron2": "N28",
-        "ancre_toron2": "O28",
-
-        "hauteur_toron3": "A29",
-        "proprio_toron3": "B29",
-        "existant_toron3": "C29",
-        "deri_toron3": "D29",
-        "type_toron3": "J29",
-        "nbe_de_cable_toron3": "L29",
-        "diametre_toron3": "K29",
-        "rupture_toron3": "M29",
-        "deg_sol_toron3": "N29",
-        "ancre_toron3": "O29",
-
-        "hauteur_toron4": "A30",
-        "proprio_toron4": "B30",
-        "existant_toron4": "C30",
-        "deri_toron4": "D30",
-        "type_toron4": "J30",
-        "nbe_de_cable_toron4": "L30",
-        "diametre_toron4": "K30",
-        "rupture_toron4": "M30",
-        "deg_sol_toron4": "N30",
-        "ancre_toron4": "O30",
-
-        "hauteur_toron5": "A31",
-        "proprio_toron5": "B31",
-        "existant_toron5": "C31",
-        "deri_toron5": "D31",
-        "type_toron5": "J31",
-        "nbe_de_cable_toron5": "L31",
-        "diametre_toron5": "K31",
-        "rupture_toron5": "M31",
-        "deg_sol_toron5": "N31",
-        "ancre_toron5": "O31",
-
-        "hauteur_toron6": "A32",
-        "proprio_toron6": "B32",
-        "existant_toron6": "C32",
-        "deri_toron6": "D32",
-        "type_toron6": "J32",
-        "nbe_de_cable_toron6": "L32",
-        "diametre_toron6": "K32",
-        "rupture_toron6": "M32",
-        "deg_sol_toron6": "N32",
-        "ancre_toron6": "O32",
-
-        "type_de_sol_ancre1": "K36",
-        "capacite_ancre1": "K37",
-        "angle_ancre1":"K38",
-        "hauban1_ancre1": "K39",
-        "hauban2_ancre1": "K40",
-        "hauban3_ancre1": "K41",
-        "hauban4_ancre1": "K42",
-        "tige_ancre1":"K43",
-        "cosse_ancre1": "K44",
-        "ecart_ancre1": "K45",
-        "type_ancre1": "K46",
-        "devi_ancre1": "K47",
-        "espace_dispo_ancre1": "K48",
-        "etat_ancre1": "K49",
-
-
-
-        "type_de_sol_ancre2": "M36",
-        "capacite_ancre2": "M37",
-        "angle_ancre2":"M38",
-        "hauban1_ancre2": "M39",
-        "hauban2_ancre2": "M40",
-        "hauban3_ancre2": "M41",
-        "hauban4_ancre2": "M42",
-        "tige_ancre2":"M43",
-        "cosse_ancre2": "M44",
-        "ecart_ancre2": "M45",
-        "type_ancre2": "M46",
-        "devi_ancre2": "M47",
-        "espace_dispo_ancre2": "M48",
-        "etat_ancre2": "M49",
-
-
-        "type_de_sol_ancre3": "N36",
-        "capacite_ancre3": "N37",
-        "angle_ancre3": "N38",
-        "hauban1_ancre3": "N39",
-        "hauban2_ancre3": "N40",
-        "hauban3_ancre3": "N41",
-        "hauban4_ancre3": "N42",
-        "tige_ancre3": "N43",
-        "cosse_ancre3": "N44",
-        "ecart_ancre3": "N45",
-        "type_ancre3": "N46",
-        "devi_ancre3": "N47",
-        "espace_dispo_ancre3": "N48",
-        "etat_ancre3": "N49",
-
-
-        "type_de_sol_ancre4": "O36",
-        "capacite_ancre4": "O37",
-        "angle_ancre4": "O38",
-        "hauban1_ancre4": "O39",
-        "hauban2_ancre4": "O40",
-        "hauban3_ancre4": "O41",
-        "hauban4_ancre4": "O42",
-        "tige_ancre4": "O43",
-        "cosse_ancre4": "O44",
-        "ecart_ancre4": "O45",
-        "type_ancre4": "O46",
-        "devi_ancre4": "O47",
-        "espace_dispo_ancre4": "O48",
-        "etat_ancre4": "O49",
-
-        "ligne_haute_tension": "K51",
-        "element_sensible": "O51",
-        "note": "A56",
-        "date": "K62",
-
-        }
-elif typeDoc == "rsa":
-    cells = {
-        "poteau": "B1",
-        "projet": "F1",
-        "révision": "I1",
-        "travaux": "B2",
-        "diametre": "D2",
-        "classification_travaux":'F2',
-        "anomalie_1": "B3",
-        "anomalie_2": "B4",
-        "anomalie_3": "B5",
-        "probleme_1": "E3",
-        "probleme_2": "E4",
-        "probleme_3": "E5",
-        "nom_poteau": "B6",
-        "adresse": "D6",
-        "plan": "G6",
-        "code_barre": "I6",
-        "pro_poteau": "B7",
-        "usage_commun:": "D7",
-        "parc": "F7",
-        "lclc": "I7",
-        "longueur": "B8",
-        "classe": "D8",
-        "annee": "F8",
-        "nbe_transfo": "H8",
-        "type_transfo": "I8",
-        "annee_inspection": "B9",
-        "modele_bell": "D9",
-        "modele_HQ": "F9",
-        "equip": "H9",
-        "fosse": "B9",
-        "hauteur_lampadaire": "D10",
-        "cabinet": "F10",
-        "hauteur_transfo": "H10",
-        "hauteur_top": "A14",
-        "portee_pre:": "B14",
-        "portee_sui:": "C14",
-        "portee_dero": "D14",
-        "toron_ins": "E14",
-        "milieu": "G13",
-        "hauteur_mt1": "A16",
-        "conducteur_mt1": "B16",
-        "phase_mt1": "C16",
-        "deri_mt1": "D16",
-        "hauteur_mt2": "A17",
-        "conducteur_mt2": "B17",
-        "phase_mt2": "C17",
-        "deri_mt2": "D17",
-        "hauteur_mt3:": "A18",
-        "conducteur_mt3": "B18",
-        "phase_mt3": "C18",
-        "deri_mt3": "D18",
-        "hauteur_mt4": "A19",
-        "conducteur_mt4": "B19",
-        "phase_mt4": "C19",
-        "deri_mt4": "D19",
-        "hauteur_mt5": "A20",
-        "conducteur_mt5:": "B20",
-        "phase_mt5": "C20",
-        "deri_mt5": "D20",
-        "hauteur_bt1": "A27",
-        "conducteur_bt1": "B27",
-        "visee_bt1": "C27",
-        "deri_bt1": "D27",
-        "hauteur_bt2": "A26",
-        "conducteur_bt2": "B26",
-        "visee_bt2": "C26",
-        "deri_bt2": "D26",
-        "hauteur_bt3": "A25",
-        "conducteur_mbt3": "B25",
-        "visee_bt3": "C25",
-        "deri_bt3": "D25",
-        "hauteur_bt4": "A24",
-        "conducteur_bt4": "B24",
-        "visee_bt4": "C24",
-        "deri_bt4": "D24",
-        "hauteur_bt5": "A23",
-        "conducteur_bt5": "B23",
-        "visee_bt5": "C23",
-        "deri_bt5": "D23",
-        "hauteur_bt6": "A22",
-        "conducteur_bt6:": "B22",
-        "visee_bt6": "C22",
-        "deri_bt6": "D22",
-
-        "hauteur_toron1": "A29",
-        "proprio_toron1": "B29",
-        "type_toron1": "C29",
-        "nbe_de_cable_toron1": "D29",
-        "diametre_toron1": "E29",
-        "rupture_toron1": "F29",
-        "deg_sol_toron1": "G29",
-        "croisement_toron1": "H29",
-        "ancre_toron1": "I29",
-        "hauteur_toron2": "A30",
-
-        "proprio_toron2": "B30",
-        "type_toron2": "C30",
-        "nbe_de_cable_toron2": "D30",
-        "diametre_toron2": "E30",
-        "rupture_toron2": "F30",
-        "deg_sol_toron2": "G30",
-        "croisement_toron2": "H30",
-        "ancre_toron2": "I30",
-
-        "hauteur_toron3": "A31",
-        "proprio_toron3": "B31",
-        "type_toron3": "C31",
-        "nbe_de_cable_toron3": "D31",
-        "diametre_toron3": "E31",
-        "rupture_toron3": "F31",
-        "deg_sol_toron3": "G31",
-        "croisement_toron3": "H31",
-        "ancre_toron3": "I31",
-
-        "hauteur_toron4": "A32",
-        "proprio_toron4": "B32",
-        "type_toron4": "C32",
-        "nbe_de_cable_toron4": "D32",
-        "diametre_toron4": "E32",
-        "rupture_toron4": "F32",
-        "deg_sol_toron4": "G32",
-        "croisement_toron4": "H32",
-        "ancre_toron4": "I32",
-
-        "hauteur_toron5": "A33",
-        "proprio_toron5": "B33",
-        "type_toron5": "C33",
-        "nbe_de_cable_toron5": "D33",
-        "diametre_toron5": "E33",
-        "rupture_toron5": "F33",
-        "deg_sol_toron5": "G33",
-        "croisement_toron5": "H33",
-        "ancre_toron5": "I33",
-
-        "hauteur_toron6": "A34",
-        "proprio_toron6": "B34",
-        "type_toron6": "C34",
-        "nbe_de_cable_toron6": "D34",
-        "diametre_toron6": "E34",
-        "rupture_toron6": "F34",
-        "deg_sol_toron6": "G34",
-        "croisement_toron6": "H34",
-        "ancre_toron6": "I34" ,
-
-        "type_de_sol_ancre1": "F17",
-        "tige_ancre1": "F18",
-        "cosse_ancre1": "F19",
-        "type_ancre1": "F20",
-        "ecart_ancre1": "F21",
-        "hauban1_ancre1": "F22",
-        "hauban2_ancre1": "F23",
-        "hauban3_ancre1": "F24",
-        "hauban4_ancre1": "F25",
-        "etat_ancre1": "f26",
-        "espace_dispo_ancre1": "F27",
-        "type_de_sol_ancre2": "G17",
-        "tige_ancre2": "G18",
-        "cosse_ancre2": "G19",
-        "type_ancre2": "G20",
-        "ecart_ancre2": "G21",
-        "hauban1_ancre2": "G22",
-        "hauban2_ancre2": "G23",
-        "hauban3_ancre2": "G24",
-        "hauban4_ancre2": "G25",
-        "etat_ancre2": "G26",
-        "espace_dispo_ancre2": "G27",
-        "type_de_sol_ancre3": "H17",
-        "tige_ancre3": "H18",
-        "cosse_ancre3": "H19",
-        "type_ancre3": "H20",
-        "ecart_ancre3": "H21",
-        "hauban1_ancre3": "H22",
-        "hauban2_ancre3": "H23",
-        "hauban3_ancre3": "H24",
-        "hauban4_ancre3": "H25",
-        "etat_ancre3": "H26",
-        "espace_dispo_ancre3": "H27",
-        "type_de_sol_ancre4": "I17",
-        "tige_ancre4": "I18",
-        "cosse_ancre4": "I19",
-        "type_ancre4": "I20",
-        "ecart_ancre4": "I21",
-        "hauban1_ancre4": "I22",
-        "hauban2_ancre4": "I23",
-        "hauban3_ancre4": "I24",
-        "hauban4_ancre4": "I25",
-        "etat_ancre4": "I26",
-        "espace_dispo_ancre4": "I27" ,
-        "ligne_haute_tension": "A36",
-        "dis_appro": "C36",
-        "element_sensible": "D36",
-        "coord": "G36",
-        "note": "A38",
-        "date": "F49",
-
-    }
-
-else:
-    print("Erreur: veuiller fournir parametre 1 = (uds ou rsa)")
-    sys.exit()
-
-type_poteaux = {
-
-    74:(35, 5),
-    79:{'JP': (35, 5), 'SYP': (40, 5), 'LPP': (35, 5)},
-    80:(35, 4),
-    81:(35, 5),
-    82:(45, 5),
-    83:{'LPP': (40, 5), 'WRC': (35, 5)},
-    84:(40, 5),
-    86:{'RP': (40, 5), 'JP': (35, 4)},
-    87:(45, 5),
-    88:{'RP': (35, 4), 'JP': (45, 5), 'WRC': (40, 5)},
-    89:(45, 4),
-    90:{'RP': (45, 5), 'LPP': (40, 4), 'WRC': (35, 4)},
-    91:(40, 4),
-    92:(45, 5),
-    93:{'RP': (40, 4), 'SYP': (35, 2)},
-    94:(45, 4),
-    95:{'JP': (45, 4), 'WRC': (40, 4)},
-    97:(45, 4),
-    98: {'SYP': (40, 2), 'LPP': (35, 2)},
-    99:(35, 2),
-    100:(45, 4),
-    101:(35, 2),
-    103:{'SYP': (45, 2), 'WRC': (35, 2)},
-    104:(40, 2),
-    105:(40, 2),
-    107:(40, 2),
-    109:(45, 2),
-    110:{'JP': (45, 2), 'WRC': (40, 2)},
-    112:(45, 2),
-    115:(45, 2),
-
-    }
-
-parc = {
-
-    "304":("saint-remi","saint-michel","sherrington"),
-    "339":("sainte-clotilde","saint-chrysostome","hemmingford","havelock"),
-    "303":("franklin","ormstown","saint-antoine","hinchinbrooke","godmanchester","huntingdon","saint-anicet","dundee","elgin"),
-    "306":("lacolle","napierville","saint-bernard-de-lacolle"),
-    "363":("saint-barbe","saint-stanislas-de-kostka","saint-etienne-de-beauharnois","saint-louis-de-gonzague"),
-
-    }
-
-valeurs = {} # on crée le dictionnaire valeur qui va nous serir a linker le dictionnaire cell
-def create_excel(valeurs):   #fonction créant l'excel on envoit la blibliotheque qu'on a créer en lisant le fichier txt
-
-    nom_du_poteau = valeurs['poteau'].strip() + '.xlsx' #permet de donner le nom Ă  l'excel par le nom du poteau
-
-    if typeDoc == "rsa":
-        shutil.copyfile('C:\\Users\\Antoine\\PycharmProjects\\UDS\\RSA.xlsx',
-                            f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')  #copie le template et donne un nom au fichier correspondant au nom du poteuu
-        wb = load_workbook(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}') #load la copie pour écrire dedans
-        ws = wb['Grille']  # Sélectionner la feuille active (ou une feuille spécifique)
-
-    elif typeDoc == "uds":
-        shutil.copyfile('C:\\Users\\Antoine\\PycharmProjects\\UDS\\UDS.xlsx',
-                            f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')  # copie le template et donne un nom au fichier
-        wb = load_workbook(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')
-        ws = wb['Grille']  # Sélectionner la feuille active (ou une feuille spécifique)
-
-    for key in valeurs:
-
-        try:
-            champs=cells[key] #champs contient la valeur de la cellule
-            val=valeurs[key] # crĂ©e deux valeurs Ă  partir du mĂȘme key(variable) qui est la variable ce qui lie les deux blibliotheques cells et valeurs, donc la valeur a maintenant une cellule ttribuĂ©
-            ws[champs] = val   # Écriture
-        except:
-            continue
-
-    wb.save(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}') # Sauvegarder les modifications dans le mĂȘme fichier
-
-
-with open(docTxt, 'r') as file:  #on lie le document txt pour créer une blibliotheque qui va lier la valeur a la variable et on va créer l'excel
-
-    for line in file:
-
-        if "---" in line:  #a la fin d'une fiche qui finit par --- je créer un excel
-            create_excel(valeurs) #on commence à écrire l'excel
-            valeurs.clear() # clear les values dans le dictionaire valeurs
-            continue
-
-        if line.strip() == "": # si il n'y a rien sur la ligne skip  permet de laisser des espaces dans le fichier lock
-            continue
-
-        if ':' not in line:    # si il y a écrit nimporte quoi on ignore la ligne
-            continue
-
-        line=line.split(":", 1) # explode en deux la variable et la valeur dans un tableau
-        variable = line[0]  #met le premier split dans la valeur variable qui va ĂȘtre notre variable
-        value=line[1]       #met le deuxieme split dans la valeur variable qui va ĂȘtre notre variable
-
-
-        if 'hauteur' in variable:   #donne un chiffre aléatoire en string a la fin de la valur pour les hauteurs vu que j'obtient un valeur apres la virgule avec mes mesures
-
-             if value.strip() == "":
-                continue
-
-             if value.strip() == 'tri':
-
-                valeurs['hauteur_mt1'] = str(float(valeurs['hauteur_top']) + 0.3)
-                valeurs['hauteur_mt2'] = str(float(valeurs['hauteur_top']) - 0.15)
-                continue
-
-             c = float(value)
-             a = 1
-             b = (c**2 - a**2)**0.5 + float(hauteur_bosch)
-             b = round(b,2)
-             value = str(b)
-
-
-
-        if 'nom_poteau' in variable:  #copie le valeur poteau dans le nom du poteau pour avoir par example uniquement le PHD49 en gros enleve rl'addresse
-             value = valeurs["poteau"].split(" ", 1)[0] #split le nom du poteau pour n'avoir que la premiere partie apres l'espace comme phd49
-
-        if 'adresse' in variable:  #copie le valeur de l'addresse dans le nom du poteau pour avoir par example uniquement le PHD49 en gros enleve rl'addresse
-
-            # =================================================================
-            # Utilise re.sub() pour retirer le texte non numérique au début,
-            # puis supprimer toute indication de type "+2" ou "-3" accolée
-            # au numéro principal, en conservant le reste de l'adresse.
-            #
-            # Expression utilisée : r'^\D*(\d+)(?:[+-]\d+)?(.*)'
-            # - ^         → dĂ©but de la chaĂźne
-            # - \D*       → zĂ©ro ou plusieurs caractĂšres qui NE sont PAS des chiffres
-            #               (supprime par exemple "PHD", "PHC", etc.)
-            # - (\d+)     → capture le numĂ©ro principal (un ou plusieurs chiffres)
-            # - (?: ... ) → parenthĂšses non capturantes (pour regrouper sans crĂ©er un groupe sĂ©parĂ©)
-            # - [+-]\d+   → un signe "+" ou "-" suivi d'un ou plusieurs chiffres
-            #               (par ex. "+2" ou "-3")
-            # - ?         → rend la partie [+-]\d+ optionnelle
-            # - (.*)      → capture tout le reste de la chaĂźne (l'adresse aprĂšs le numĂ©ro)
-            #
-            # Remplacement utilisé : r'\1\2'
-            # - \1 → insĂšre le numĂ©ro principal capturĂ©
-            # - \2 → insùre le texte restant de l'adresse
-            #
-            # Exemple :
-            # "PHD248+2 chemin de l'église" devient "248 chemin de l'église"
-            # "PHC300-1 rue des lilas"     devient "300 rue des lilas"
-            # =================================================================
-             value = re.sub(r'^\D*(\d+)(?:[+-]\d+)?(.*)', r'\1\2', valeurs["poteau"]) # oon efface la partie PHD,PHC,PHO et le + ou le - pour obtenir uniquement l'addresse
-
-
-        if 'date' in variable:
-
-            if typeDoc  == 'uds':
-                value = str(nom_du_releveur + '\n') + str(date.today())    # met la date d'aujourd'hui pour la date du relevé
-
-            else:
-                 value = date.today()
-
-        if 'longueur' in variable: #on va trouver le type de longeur dépendamment de la circonférence ou pied
-
-            value = value.strip()
-
-            try:
-                value_int = int(value)  # convert to integer if possible sinon ca marche pas
-            except ValueError:
-                continue
-
-            if value_int not in type_poteaux: # si c anous donne une valeur hors du dictionnaire ou que l'on met la valeur de la longeueur directemen on skip le processus
-                 continue
-
-            type_poteaux_entre = type_poteaux[value_int] #met la valeur du dictionnaire dans une variable qui nous permettra de savoir si c'est un dictio ou un tuple pour differencie les deux type de modele dans le dictionaire
-
-            if isinstance(type_poteaux_entre,dict): # si on a un dictionnaire donc si on est obligé d'indiquer le type de bois
-
-                 bois= valeurs['bois'].strip() # on prend la valeur du bois dans le fichier texte met le dnas une nouvelle variable
-
-                 if bois == '': #si on ne connait pas le bois ca skip tout
-                     continue
-
-                 valeurs['classe'] = type_poteaux_entre[bois][1] #on va sélectionner le dictionnaire du bois correspondant et la classe du poteau
-                 value = type_poteaux_entre[bois][0] #on va sélectionner le dictionnaire du bois correspondant et la longueur du poteau
-
-            else: #else si la valuer n'est qu'un tupple
-                  valeurs['classe'] = type_poteaux_entre[1] #on va sélectionner  la classe du poteau et on le stock dans la variable classe du dictio valeur
-                  value = type_poteaux_entre[0] #on va sélectionner  la longueur du poteau et on le stock dans le value de ce cycle qui sera longueur.
-
-        if "ville" in variable:
-
-            # This line tries to find the first key in the 'parc' dictionary
-            # where the target value (e.g., a town name) exists in the tuple of values.
-
-            valeurs['parc']= next((k for k, v in parc.items() if value.strip() in v), None) #k for k va me donner laclé de la valeur de la ville
-
-
-        valeurs[variable]=value     #crée le dictionnaire valeur qui lie variable et sa valeur
-
-
-
-
-
-
-
-
-
+import sys
+from openpyxl import load_workbook
+import shutil
+import random
+import re
+from datetime import date
+# =================================================================
+             #CODE POUR CRÉER L'EXCEL DE L'UDS ET RSA AVEC UN FICHIER TXT QUI SERT A NE PAS RECOPIER LES DONNÉE POUR SAUVER DU TEMPS
+            # le but du code est de linker deux dictionaire, le dictionnaire cell qui contient la valeur les cellule des variables et
+            # dictionaire valeurs qui contient les valeurs des variables, le dictionaire valeur sera créer au fure et a mesure dans la lecture du fichier txt
+            # pour déterminer que la fiche du poteau est finie on met --- a la fin ce qui va arreter la lecture et commencer le processus de la création de l'excel
+            # deux variable vont etre créer champs et val qui seront le link entre les deux dictionaire ce qui va faire en sorte de link la valeur avec les cellule car les deux dictionaires ont les mee variable
+            # il y a quelques regles pour certaine variable les ''if'' dans la section ou on lie le fichier txt et quelques autre dictionnaire pas besoin de les comprendre pour comprendre le code
+            # on déclenche le code avec deux arguments si c'est un uds rsa et ou le fichier text se trouve par exemple rsa C:\Users\Antoine\PycharmProjects\UDS\PDF.py rsa C:\Users\Antoine\PycharmProjects\UDS\test.txt
+            # donc (ou se trouve le script)+(argument 1:rsa ou uds?) +(argument 2:ou se trouve le fichier texte), il faut faire la commande dans cmd.
+# =====================================================================
+
+if len(sys.argv) < 2:
+    print("manque de parametres: argument 1 = type de fichier,argument 2 = fichier path")  #python C:\Users\Antoine\PycharmProjects\UDS\UDS.py rsa C:\Users\Antoine\PycharmProjects\UDS\RSA_UDS.txt
+    sys.exit()
+typeDoc = sys.argv[1]
+docTxt = sys.argv[2]
+nom_du_releveur = input('Nom du releveur: ')
+hauteur_bosch = input("rentrer la hauteur de l'appareil par rapport au sol lors des mesures: ")
+
+cells = {}
+if typeDoc == "uds":
+
+    cells = {
+        "poteau": "B4",
+        "projet": "K3",
+        "révision": "O3",
+        "travaux": "B3",
+        "diametre": "H3",
+
+        "adresse": "K4",
+        "plan": "H4",
+        "code_barre": "N6",
+        "pro_poteau": "K7",
+        "annee_inspection": "H5",
+        "parc": "K5",
+        "option_HQ":"N5",
+        "longueur": "C6",
+        "classe": "D6",
+        "annee": "H6",
+        "circonference": "K6",
+        "p/r":"D7",
+        "usage_commun:": "O7",
+        "angle": "K13",
+        "lclc": "K14",
+        "nbe_transfo": "L15",
+        "type_transfo": "K15",
+        "equip": "K16",
+        "gradation": "K17",
+        "lampadaire":"K18",
+        "las":"K19",
+        "montage_HQ":"K20",
+        "portee_lache":"K21",
+        "portee_pre:": "K22",
+        "portee_sui:": "N22",
+        "malt":"N21",
+        "reseau":"N20",
+        "cabinet":"O19",
+        "luminaire":"N18",
+        "traverse":"O17",
+        "las":"N16",
+        "fosse": "O14",
+        "hauteur_transfo": "O15",
+        "hauteur_top": "A11",
+        "portee_pre:": "B14",
+        "portee_sui:": "C14",
+
+        "hauteur_mt1": "A14",
+        "conducteur_mt1": "C14",
+        "phase_mt1": "B14",
+        "deri_mt1": "D14",
+
+        "hauteur_mt2": "A15",
+        "conducteur_mt2": "C15",
+        "phase_mt2": "B15",
+        "deri_mt2": "D15",
+
+
+        "hauteur_mt3:": "A16",
+        "conducteur_mt3": "C16",
+        "phase_mt3": "B16",
+        "deri_mt3": "D16",
+
+        "hauteur_bt1": "A23",
+        "conducteur_bt1": "B23",
+        "visee_bt1": "C23",
+        "deri_bt1": "D23",
+
+
+        "hauteur_bt2": "A22",
+        "conducteur_bt2": "B22",
+        "visee_bt2": "C22",
+        "deri_bt2": "D22",
+
+        "hauteur_bt3": "A21",
+        "conducteur_mbt3": "B21",
+        "visee_bt3": "C21",
+        "deri_bt3": "D21",
+
+
+        "hauteur_bt4": "A20",
+        "conducteur_bt4": "B20",
+        "visee_bt4": "C20",
+        "deri_bt4": "D20",
+
+        "hauteur_bt5": "A19",
+        "conducteur_bt5": "B19",
+        "visee_bt5": "C19",
+        "deri_bt5": "D19",
+
+        "hauteur_bt6": "A18",
+        "conducteur_bt6:": "B18",
+        "visee_bt6": "C18",
+        "deri_bt6": "D18",
+
+        "hauteur_toron1": "A27",
+        "proprio_toron1": "B27",
+        "toron1_existant": "C27",
+        "deri":"D27",
+        "type_toron1": "J27",
+        "nbe_de_cable_toron1": "L27",
+        "diametre_toron1": "K27",
+        "rupture_toron1": "M27",
+        "deg_sol_toron1": "N27",
+        "ancre_toron1": "O27",
+
+        "hauteur_toron2": "A28",
+        "proprio_toron2": "B28",
+        "existant_toron2": "C28",
+        "deri_toron2": "D28",
+        "type_toron2": "J28",
+        "nbe_de_cable_toron2": "L28",
+        "diametre_toron2": "K28",
+        "rupture_toron2": "M28",
+        "deg_sol_toron2": "N28",
+        "ancre_toron2": "O28",
+
+        "hauteur_toron3": "A29",
+        "proprio_toron3": "B29",
+        "existant_toron3": "C29",
+        "deri_toron3": "D29",
+        "type_toron3": "J29",
+        "nbe_de_cable_toron3": "L29",
+        "diametre_toron3": "K29",
+        "rupture_toron3": "M29",
+        "deg_sol_toron3": "N29",
+        "ancre_toron3": "O29",
+
+        "hauteur_toron4": "A30",
+        "proprio_toron4": "B30",
+        "existant_toron4": "C30",
+        "deri_toron4": "D30",
+        "type_toron4": "J30",
+        "nbe_de_cable_toron4": "L30",
+        "diametre_toron4": "K30",
+        "rupture_toron4": "M30",
+        "deg_sol_toron4": "N30",
+        "ancre_toron4": "O30",
+
+        "hauteur_toron5": "A31",
+        "proprio_toron5": "B31",
+        "existant_toron5": "C31",
+        "deri_toron5": "D31",
+        "type_toron5": "J31",
+        "nbe_de_cable_toron5": "L31",
+        "diametre_toron5": "K31",
+        "rupture_toron5": "M31",
+        "deg_sol_toron5": "N31",
+        "ancre_toron5": "O31",
+
+        "hauteur_toron6": "A32",
+        "proprio_toron6": "B32",
+        "existant_toron6": "C32",
+        "deri_toron6": "D32",
+        "type_toron6": "J32",
+        "nbe_de_cable_toron6": "L32",
+        "diametre_toron6": "K32",
+        "rupture_toron6": "M32",
+        "deg_sol_toron6": "N32",
+        "ancre_toron6": "O32",
+
+        "type_de_sol_ancre1": "K36",
+        "capacite_ancre1": "K37",
+        "angle_ancre1":"K38",
+        "hauban1_ancre1": "K39",
+        "hauban2_ancre1": "K40",
+        "hauban3_ancre1": "K41",
+        "hauban4_ancre1": "K42",
+        "tige_ancre1":"K43",
+        "cosse_ancre1": "K44",
+        "ecart_ancre1": "K45",
+        "type_ancre1": "K46",
+        "devi_ancre1": "K47",
+        "espace_dispo_ancre1": "K48",
+        "etat_ancre1": "K49",
+
+
+
+        "type_de_sol_ancre2": "M36",
+        "capacite_ancre2": "M37",
+        "angle_ancre2":"M38",
+        "hauban1_ancre2": "M39",
+        "hauban2_ancre2": "M40",
+        "hauban3_ancre2": "M41",
+        "hauban4_ancre2": "M42",
+        "tige_ancre2":"M43",
+        "cosse_ancre2": "M44",
+        "ecart_ancre2": "M45",
+        "type_ancre2": "M46",
+        "devi_ancre2": "M47",
+        "espace_dispo_ancre2": "M48",
+        "etat_ancre2": "M49",
+
+
+        "type_de_sol_ancre3": "N36",
+        "capacite_ancre3": "N37",
+        "angle_ancre3": "N38",
+        "hauban1_ancre3": "N39",
+        "hauban2_ancre3": "N40",
+        "hauban3_ancre3": "N41",
+        "hauban4_ancre3": "N42",
+        "tige_ancre3": "N43",
+        "cosse_ancre3": "N44",
+        "ecart_ancre3": "N45",
+        "type_ancre3": "N46",
+        "devi_ancre3": "N47",
+        "espace_dispo_ancre3": "N48",
+        "etat_ancre3": "N49",
+
+
+        "type_de_sol_ancre4": "O36",
+        "capacite_ancre4": "O37",
+        "angle_ancre4": "O38",
+        "hauban1_ancre4": "O39",
+        "hauban2_ancre4": "O40",
+        "hauban3_ancre4": "O41",
+        "hauban4_ancre4": "O42",
+        "tige_ancre4": "O43",
+        "cosse_ancre4": "O44",
+        "ecart_ancre4": "O45",
+        "type_ancre4": "O46",
+        "devi_ancre4": "O47",
+        "espace_dispo_ancre4": "O48",
+        "etat_ancre4": "O49",
+
+        "ligne_haute_tension": "K51",
+        "element_sensible": "O51",
+        "note": "A56",
+        "date": "K62",
+
+        }
+elif typeDoc == "rsa":
+    cells = {
+        "poteau": "B1",
+        "projet": "F1",
+        "révision": "I1",
+        "travaux": "B2",
+        "diametre": "D2",
+        "classification_travaux":'F2',
+        "anomalie_1": "B3",
+        "anomalie_2": "B4",
+        "anomalie_3": "B5",
+        "probleme_1": "E3",
+        "probleme_2": "E4",
+        "probleme_3": "E5",
+        "nom_poteau": "B6",
+        "adresse": "D6",
+        "plan": "G6",
+        "code_barre": "I6",
+        "pro_poteau": "B7",
+        "usage_commun:": "D7",
+        "parc": "F7",
+        "lclc": "I7",
+        "longueur": "B8",
+        "classe": "D8",
+        "annee": "F8",
+        "nbe_transfo": "H8",
+        "type_transfo": "I8",
+        "annee_inspection": "B9",
+        "modele_bell": "D9",
+        "modele_HQ": "F9",
+        "equip": "H9",
+        "fosse": "B9",
+        "hauteur_lampadaire": "D10",
+        "cabinet": "F10",
+        "hauteur_transfo": "H10",
+        "hauteur_top": "A14",
+        "portee_pre:": "B14",
+        "portee_sui:": "C14",
+        "portee_dero": "D14",
+        "toron_ins": "E14",
+        "milieu": "G13",
+        "hauteur_mt1": "A16",
+        "conducteur_mt1": "B16",
+        "phase_mt1": "C16",
+        "deri_mt1": "D16",
+        "hauteur_mt2": "A17",
+        "conducteur_mt2": "B17",
+        "phase_mt2": "C17",
+        "deri_mt2": "D17",
+        "hauteur_mt3:": "A18",
+        "conducteur_mt3": "B18",
+        "phase_mt3": "C18",
+        "deri_mt3": "D18",
+        "hauteur_mt4": "A19",
+        "conducteur_mt4": "B19",
+        "phase_mt4": "C19",
+        "deri_mt4": "D19",
+        "hauteur_mt5": "A20",
+        "conducteur_mt5:": "B20",
+        "phase_mt5": "C20",
+        "deri_mt5": "D20",
+        "hauteur_bt1": "A27",
+        "conducteur_bt1": "B27",
+        "visee_bt1": "C27",
+        "deri_bt1": "D27",
+        "hauteur_bt2": "A26",
+        "conducteur_bt2": "B26",
+        "visee_bt2": "C26",
+        "deri_bt2": "D26",
+        "hauteur_bt3": "A25",
+        "conducteur_mbt3": "B25",
+        "visee_bt3": "C25",
+        "deri_bt3": "D25",
+        "hauteur_bt4": "A24",
+        "conducteur_bt4": "B24",
+        "visee_bt4": "C24",
+        "deri_bt4": "D24",
+        "hauteur_bt5": "A23",
+        "conducteur_bt5": "B23",
+        "visee_bt5": "C23",
+        "deri_bt5": "D23",
+        "hauteur_bt6": "A22",
+        "conducteur_bt6:": "B22",
+        "visee_bt6": "C22",
+        "deri_bt6": "D22",
+
+        "hauteur_toron1": "A29",
+        "proprio_toron1": "B29",
+        "type_toron1": "C29",
+        "nbe_de_cable_toron1": "D29",
+        "diametre_toron1": "E29",
+        "rupture_toron1": "F29",
+        "deg_sol_toron1": "G29",
+        "croisement_toron1": "H29",
+        "ancre_toron1": "I29",
+        "hauteur_toron2": "A30",
+
+        "proprio_toron2": "B30",
+        "type_toron2": "C30",
+        "nbe_de_cable_toron2": "D30",
+        "diametre_toron2": "E30",
+        "rupture_toron2": "F30",
+        "deg_sol_toron2": "G30",
+        "croisement_toron2": "H30",
+        "ancre_toron2": "I30",
+
+        "hauteur_toron3": "A31",
+        "proprio_toron3": "B31",
+        "type_toron3": "C31",
+        "nbe_de_cable_toron3": "D31",
+        "diametre_toron3": "E31",
+        "rupture_toron3": "F31",
+        "deg_sol_toron3": "G31",
+        "croisement_toron3": "H31",
+        "ancre_toron3": "I31",
+
+        "hauteur_toron4": "A32",
+        "proprio_toron4": "B32",
+        "type_toron4": "C32",
+        "nbe_de_cable_toron4": "D32",
+        "diametre_toron4": "E32",
+        "rupture_toron4": "F32",
+        "deg_sol_toron4": "G32",
+        "croisement_toron4": "H32",
+        "ancre_toron4": "I32",
+
+        "hauteur_toron5": "A33",
+        "proprio_toron5": "B33",
+        "type_toron5": "C33",
+        "nbe_de_cable_toron5": "D33",
+        "diametre_toron5": "E33",
+        "rupture_toron5": "F33",
+        "deg_sol_toron5": "G33",
+        "croisement_toron5": "H33",
+        "ancre_toron5": "I33",
+
+        "hauteur_toron6": "A34",
+        "proprio_toron6": "B34",
+        "type_toron6": "C34",
+        "nbe_de_cable_toron6": "D34",
+        "diametre_toron6": "E34",
+        "rupture_toron6": "F34",
+        "deg_sol_toron6": "G34",
+        "croisement_toron6": "H34",
+        "ancre_toron6": "I34" ,
+
+        "type_de_sol_ancre1": "F17",
+        "tige_ancre1": "F18",
+        "cosse_ancre1": "F19",
+        "type_ancre1": "F20",
+        "ecart_ancre1": "F21",
+        "hauban1_ancre1": "F22",
+        "hauban2_ancre1": "F23",
+        "hauban3_ancre1": "F24",
+        "hauban4_ancre1": "F25",
+        "etat_ancre1": "f26",
+        "espace_dispo_ancre1": "F27",
+        "type_de_sol_ancre2": "G17",
+        "tige_ancre2": "G18",
+        "cosse_ancre2": "G19",
+        "type_ancre2": "G20",
+        "ecart_ancre2": "G21",
+        "hauban1_ancre2": "G22",
+        "hauban2_ancre2": "G23",
+        "hauban3_ancre2": "G24",
+        "hauban4_ancre2": "G25",
+        "etat_ancre2": "G26",
+        "espace_dispo_ancre2": "G27",
+        "type_de_sol_ancre3": "H17",
+        "tige_ancre3": "H18",
+        "cosse_ancre3": "H19",
+        "type_ancre3": "H20",
+        "ecart_ancre3": "H21",
+        "hauban1_ancre3": "H22",
+        "hauban2_ancre3": "H23",
+        "hauban3_ancre3": "H24",
+        "hauban4_ancre3": "H25",
+        "etat_ancre3": "H26",
+        "espace_dispo_ancre3": "H27",
+        "type_de_sol_ancre4": "I17",
+        "tige_ancre4": "I18",
+        "cosse_ancre4": "I19",
+        "type_ancre4": "I20",
+        "ecart_ancre4": "I21",
+        "hauban1_ancre4": "I22",
+        "hauban2_ancre4": "I23",
+        "hauban3_ancre4": "I24",
+        "hauban4_ancre4": "I25",
+        "etat_ancre4": "I26",
+        "espace_dispo_ancre4": "I27" ,
+        "ligne_haute_tension": "A36",
+        "dis_appro": "C36",
+        "element_sensible": "D36",
+        "coord": "G36",
+        "note": "A38",
+        "date": "F49",
+
+    }
+
+else:
+    print("Erreur: veuiller fournir parametre 1 = (uds ou rsa)")
+    sys.exit()
+
+type_poteaux = {
+
+    74:(35, 5),
+    79:{'JP': (35, 5), 'SYP': (40, 5), 'LPP': (35, 5)},
+    80:(35, 4),
+    81:(35, 5),
+    82:(45, 5),
+    83:{'LPP': (40, 5), 'WRC': (35, 5)},
+    84:(40, 5),
+    86:{'RP': (40, 5), 'JP': (35, 4)},
+    87:(45, 5),
+    88:{'RP': (35, 4), 'JP': (45, 5), 'WRC': (40, 5)},
+    89:(45, 4),
+    90:{'RP': (45, 5), 'LPP': (40, 4), 'WRC': (35, 4)},
+    91:(40, 4),
+    92:(45, 5),
+    93:{'RP': (40, 4), 'SYP': (35, 2)},
+    94:(45, 4),
+    95:{'JP': (45, 4), 'WRC': (40, 4)},
+    97:(45, 4),
+    98: {'SYP': (40, 2), 'LPP': (35, 2)},
+    99:(35, 2),
+    100:(45, 4),
+    101:(35, 2),
+    103:{'SYP': (45, 2), 'WRC': (35, 2)},
+    104:(40, 2),
+    105:(40, 2),
+    107:(40, 2),
+    109:(45, 2),
+    110:{'JP': (45, 2), 'WRC': (40, 2)},
+    112:(45, 2),
+    115:(45, 2),
+
+    }
+
+parc = {
+
+    "304":("saint-remi","saint-michel","sherrington"),
+    "339":("sainte-clotilde","saint-chrysostome","hemmingford","havelock"),
+    "303":("franklin","ormstown","saint-antoine","hinchinbrooke","godmanchester","huntingdon","saint-anicet","dundee","elgin"),
+    "306":("lacolle","napierville","saint-bernard-de-lacolle"),
+    "363":("saint-barbe","saint-stanislas-de-kostka","saint-etienne-de-beauharnois","saint-louis-de-gonzague"),
+
+    }
+
+valeurs = {} # on crée le dictionnaire valeur qui va nous serir a linker le dictionnaire cell
+def create_excel(valeurs):   #fonction créant l'excel on envoit la blibliotheque qu'on a créer en lisant le fichier txt
+
+    nom_du_poteau = valeurs['poteau'].strip() + '.xlsx' #permet de donner le nom Ă  l'excel par le nom du poteau
+
+    if typeDoc == "rsa":
+        shutil.copyfile('C:\\Users\\Antoine\\PycharmProjects\\UDS\\RSA.xlsx',
+                            f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')  #copie le template et donne un nom au fichier correspondant au nom du poteuu
+        wb = load_workbook(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}') #load la copie pour écrire dedans
+        ws = wb['Grille']  # Sélectionner la feuille active (ou une feuille spécifique)
+
+    elif typeDoc == "uds":
+        shutil.copyfile('C:\\Users\\Antoine\\PycharmProjects\\UDS\\UDS.xlsx',
+                            f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')  # copie le template et donne un nom au fichier
+        wb = load_workbook(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}')
+        ws = wb['Grille']  # Sélectionner la feuille active (ou une feuille spécifique)
+
+    for key in valeurs:
+
+        try:
+            champs=cells[key] #champs contient la valeur de la cellule
+            val=valeurs[key] # crĂ©e deux valeurs Ă  partir du mĂȘme key(variable) qui est la variable ce qui lie les deux blibliotheques cells et valeurs, donc la valeur a maintenant une cellule ttribuĂ©
+            ws[champs] = val   # Écriture
+        except:
+            continue
+
+    wb.save(f'C:\\Users\\Antoine\\PycharmProjects\\UDS\\{nom_du_poteau}') # Sauvegarder les modifications dans le mĂȘme fichier
+
+
+with open(docTxt, 'r') as file:  #on lie le document txt pour créer une blibliotheque qui va lier la valeur a la variable et on va créer l'excel
+
+    for line in file:
+
+        if "---" in line:  #a la fin d'une fiche qui finit par --- je créer un excel
+            create_excel(valeurs) #on commence à écrire l'excel
+            valeurs.clear() # clear les values dans le dictionaire valeurs
+            continue
+
+        if line.strip() == "": # si il n'y a rien sur la ligne skip  permet de laisser des espaces dans le fichier lock
+            continue
+
+        if ':' not in line:    # si il y a écrit nimporte quoi on ignore la ligne
+            continue
+
+        line=line.split(":", 1) # explode en deux la variable et la valeur dans un tableau
+        variable = line[0]  #met le premier split dans la valeur variable qui va ĂȘtre notre variable
+        value=line[1]       #met le deuxieme split dans la valeur variable qui va ĂȘtre notre variable
+
+
+        if 'hauteur' in variable:   #donne un chiffre aléatoire en string a la fin de la valur pour les hauteurs vu que j'obtient un valeur apres la virgule avec mes mesures
+
+             if value.strip() == "":
+                continue
+
+             if value.strip() == 'tri':
+
+                valeurs['hauteur_mt1'] = str(float(valeurs['hauteur_top']) + 0.3)
+                valeurs['hauteur_mt2'] = str(float(valeurs['hauteur_top']) - 0.15)
+                continue
+
+             c = float(value)
+             a = 1
+             b = (c**2 - a**2)**0.5 + float(hauteur_bosch)
+             b = round(b,2)
+             value = str(b)
+
+
+
+        if 'nom_poteau' in variable:  #copie le valeur poteau dans le nom du poteau pour avoir par example uniquement le PHD49 en gros enleve rl'addresse
+             value = valeurs["poteau"].split(" ", 1)[0] #split le nom du poteau pour n'avoir que la premiere partie apres l'espace comme phd49
+
+        if 'adresse' in variable:  #copie le valeur de l'addresse dans le nom du poteau pour avoir par example uniquement le PHD49 en gros enleve rl'addresse
+
+            # =================================================================
+            # Utilise re.sub() pour retirer le texte non numérique au début,
+            # puis supprimer toute indication de type "+2" ou "-3" accolée
+            # au numéro principal, en conservant le reste de l'adresse.
+            #
+            # Expression utilisée : r'^\D*(\d+)(?:[+-]\d+)?(.*)'
+            # - ^         → dĂ©but de la chaĂźne
+            # - \D*       → zĂ©ro ou plusieurs caractĂšres qui NE sont PAS des chiffres
+            #               (supprime par exemple "PHD", "PHC", etc.)
+            # - (\d+)     → capture le numĂ©ro principal (un ou plusieurs chiffres)
+            # - (?: ... ) → parenthĂšses non capturantes (pour regrouper sans crĂ©er un groupe sĂ©parĂ©)
+            # - [+-]\d+   → un signe "+" ou "-" suivi d'un ou plusieurs chiffres
+            #               (par ex. "+2" ou "-3")
+            # - ?         → rend la partie [+-]\d+ optionnelle
+            # - (.*)      → capture tout le reste de la chaĂźne (l'adresse aprĂšs le numĂ©ro)
+            #
+            # Remplacement utilisé : r'\1\2'
+            # - \1 → insĂšre le numĂ©ro principal capturĂ©
+            # - \2 → insùre le texte restant de l'adresse
+            #
+            # Exemple :
+            # "PHD248+2 chemin de l'église" devient "248 chemin de l'église"
+            # "PHC300-1 rue des lilas"     devient "300 rue des lilas"
+            # =================================================================
+             value = re.sub(r'^\D*(\d+)(?:[+-]\d+)?(.*)', r'\1\2', valeurs["poteau"]) # oon efface la partie PHD,PHC,PHO et le + ou le - pour obtenir uniquement l'addresse
+
+
+        if 'date' in variable:
+
+            if typeDoc  == 'uds':
+                value = str(nom_du_releveur + '\n') + str(date.today())    # met la date d'aujourd'hui pour la date du relevé
+
+            else:
+                 value = date.today()
+
+        if 'longueur' in variable: #on va trouver le type de longeur dépendamment de la circonférence ou pied
+
+            value = value.strip()
+
+            try:
+                value_int = int(value)  # convert to integer if possible sinon ca marche pas
+            except ValueError:
+                continue
+
+            if value_int not in type_poteaux: # si c anous donne une valeur hors du dictionnaire ou que l'on met la valeur de la longeueur directemen on skip le processus
+                 continue
+
+            type_poteaux_entre = type_poteaux[value_int] #met la valeur du dictionnaire dans une variable qui nous permettra de savoir si c'est un dictio ou un tuple pour differencie les deux type de modele dans le dictionaire
+
+            if isinstance(type_poteaux_entre,dict): # si on a un dictionnaire donc si on est obligé d'indiquer le type de bois
+
+                 bois= valeurs['bois'].strip() # on prend la valeur du bois dans le fichier texte met le dnas une nouvelle variable
+
+                 if bois == '': #si on ne connait pas le bois ca skip tout
+                     continue
+
+                 valeurs['classe'] = type_poteaux_entre[bois][1] #on va sélectionner le dictionnaire du bois correspondant et la classe du poteau
+                 value = type_poteaux_entre[bois][0] #on va sélectionner le dictionnaire du bois correspondant et la longueur du poteau
+
+            else: #else si la valuer n'est qu'un tupple
+                  valeurs['classe'] = type_poteaux_entre[1] #on va sélectionner  la classe du poteau et on le stock dans la variable classe du dictio valeur
+                  value = type_poteaux_entre[0] #on va sélectionner  la longueur du poteau et on le stock dans le value de ce cycle qui sera longueur.
+
+        if "ville" in variable:
+
+            # This line tries to find the first key in the 'parc' dictionary
+            # where the target value (e.g., a town name) exists in the tuple of values.
+
+            valeurs['parc']= next((k for k, v in parc.items() if value.strip() in v), None) #k for k va me donner laclé de la valeur de la ville
+
+
+        valeurs[variable]=value     #crée le dictionnaire valeur qui lie variable et sa valeur
+
+
+
+
+
+
+
+
+
diff --git a/amélioration b/amélioration
index c0fe1a2..637e921 100644
--- a/amélioration
+++ b/amélioration
@@ -1,9 +1,9 @@
--Me débarasser du --- pour améliorer la fluidité
-
--Pouvoir plusieurs fichier texte si la personne prefere un fichier par poteau donc continuer java script
-
--Trouver une facon que sur la page web que l'option ''tri soit claire'
-
--Faire les portĂ©es(je ne sais aps comment ce que la logique doit ĂȘtre) 
-
--faudrait que je me fasse un lien pour télécharger le template excel/rsa et les modeles de ficheir texte
+-Me débarasser du --- pour améliorer la fluidité
+
+-Pouvoir plusieurs fichier texte si la personne prefere un fichier par poteau donc continuer java script
+
+-Trouver une facon que sur la page web que l'option ''tri soit claire'
+
+-Faire les portĂ©es(je ne sais aps comment ce que la logique doit ĂȘtre) 
+
+-faudrait que je me fasse un lien pour télécharger le template excel/rsa et les modeles de ficheir texte
diff --git a/checkpoint.py b/checkpoint.py
index e316c79..8273114 100644
--- a/checkpoint.py
+++ b/checkpoint.py
@@ -1,666 +1,666 @@
-import io, re, shutil, random
-from datetime import date
-import sys
-from openpyxl import load_workbook
-from io import BytesIO
-from openpyxl import Workbook
-from js import console
-
-
-def save_workbook_to_bytes(wb):
-    buffer = io.BytesIO()
-    wb.save(buffer)
-    return buffer.getvalue()
-
-# Pull variables set by JS
-template_uint8 = globals().get("template_uint8")                  #get les id du html par le java
-txt_content = globals().get("txt_content")
-typeDoc = globals().get("typeDoc")
-nom_du_releveur = globals().get("nom_du_releveur")
-hauteur_bosch = globals().get("hauteur_bosch")
-
-# Convert template bytes into Python bytes
-template_bytes = bytes(template_uint8)
-
-# --- Start of your original dictionaries and logic (slightly adapted) ---
-
-cells = {}
-if typeDoc == "uds":
-    cells = {
-        "poteau": "B4",
-        "projet": "K3",
-        "révision": "O3",
-        "travaux": "B3",
-        "diametre": "H3",
-        "adresse": "K4",
-        "plan": "H4",
-        "code_barre": "N6",
-        "pro_poteau": "K7",
-        "annee_inspection": "H5",
-        "parc": "K5",
-        "option_HQ":"N5",
-        "longueur": "C6",
-        "classe": "D6",
-        "annee": "H6",
-        "circonference": "K6",
-        "p/r":"D7",
-        "usage_commun:": "O7",
-        "angle": "K13",
-        "lclc": "K14",
-        "nbe_transfo": "L15",
-        "type_transfo": "K15",
-        "equip": "K16",
-        "gradation": "K17",
-        "lampadaire":"K18",
-        "las":"K19",
-        "montage_HQ":"K20",
-        "portee_lache":"K21",
-        "portee_pre:": "K22",
-        "portee_sui:": "N22",
-        "malt":"N21",
-        "reseau":"N20",
-        "cabinet":"O19",
-        "luminaire":"N18",
-        "traverse":"O17",
-        "las":"N16",
-        "fosse": "O14",
-        "hauteur_transfo": "O15",
-        "hauteur_top": "A11",
-        "portee_pre:": "B14",
-        "portee_sui:": "C14",
-        "hauteur_mt1": "A14",
-        "conducteur_mt1": "C14",
-        "phase_mt1": "B14",
-        "deri_mt1": "D14",
-        "hauteur_mt2": "A15",
-        "conducteur_mt2": "C15",
-        "phase_mt2": "B15",
-        "deri_mt2": "D15",
-        "hauteur_mt3:": "A16",
-        "conducteur_mt3": "C16",
-        "phase_mt3": "B16",
-        "deri_mt3": "D16",
-        "hauteur_bt1": "A23",
-        "conducteur_bt1": "B23",
-        "visee_bt1": "C23",
-        "deri_bt1": "D23",
-        "hauteur_bt2": "A22",
-        "conducteur_bt2": "B22",
-        "visee_bt2": "C22",
-        "deri_bt2": "D22",
-        "hauteur_bt3": "A21",
-        "conducteur_mbt3": "B21",
-        "visee_bt3": "C21",
-        "deri_bt3": "D21",
-        "hauteur_bt4": "A20",
-        "conducteur_bt4": "B20",
-        "visee_bt4": "C20",
-        "deri_bt4": "D20",
-        "hauteur_bt5": "A19",
-        "conducteur_bt5": "B19",
-        "visee_bt5": "C19",
-        "deri_bt5": "D19",
-        "hauteur_bt6": "A18",
-        "conducteur_bt6:": "B18",
-        "visee_bt6": "C18",
-        "deri_bt6": "D18",
-        "hauteur_toron1": "A27",
-        "proprio_toron1": "B27",
-        "toron1_existant": "C27",
-        "deri":"D27",
-        "type_toron1": "J27",
-        "nbe_de_cable_toron1": "L27",
-        "diametre_toron1": "K27",
-        "rupture_toron1": "M27",
-        "deg_sol_toron1": "N27",
-        "ancre_toron1": "O27",
-        "hauteur_toron2": "A28",
-        "proprio_toron2": "B28",
-        "existant_toron2": "C28",
-        "deri_toron2": "D28",
-        "type_toron2": "J28",
-        "nbe_de_cable_toron2": "L28",
-        "diametre_toron2": "K28",
-        "rupture_toron2": "M28",
-        "deg_sol_toron2": "N28",
-        "ancre_toron2": "O28",
-        "hauteur_toron3": "A29",
-        "proprio_toron3": "B29",
-        "existant_toron3": "C29",
-        "deri_toron3": "D29",
-        "type_toron3": "J29",
-        "nbe_de_cable_toron3": "L29",
-        "diametre_toron3": "K29",
-        "rupture_toron3": "M29",
-        "deg_sol_toron3": "N29",
-        "ancre_toron3": "O29",
-        "hauteur_toron4": "A30",
-        "proprio_toron4": "B30",
-        "existant_toron4": "C30",
-        "deri_toron4": "D30",
-        "type_toron4": "J30",
-        "nbe_de_cable_toron4": "L30",
-        "diametre_toron4": "K30",
-        "rupture_toron4": "M30",
-        "deg_sol_toron4": "N30",
-        "ancre_toron4": "O30",
-        "hauteur_toron5": "A31",
-        "proprio_toron5": "B31",
-        "existant_toron5": "C31",
-        "deri_toron5": "D31",
-        "type_toron5": "J31",
-        "nbe_de_cable_toron5": "L31",
-        "diametre_toron5": "K31",
-        "rupture_toron5": "M31",
-        "deg_sol_toron5": "N31",
-        "ancre_toron5": "O31",
-        "hauteur_toron6": "A32",
-        "proprio_toron6": "B32",
-        "existant_toron6": "C32",
-        "deri_toron6": "D32",
-        "type_toron6": "J32",
-        "nbe_de_cable_toron6": "L32",
-        "diametre_toron6": "K32",
-        "rupture_toron6": "M32",
-        "deg_sol_toron6": "N32",
-        "ancre_toron6": "O32",
-        "type_de_sol_ancre1": "K36",
-        "capacite_ancre1": "K37",
-        "angle_ancre1":"K38",
-        "hauban1_ancre1": "K39",
-        "hauban2_ancre1": "K40",
-        "hauban3_ancre1": "K41",
-        "hauban4_ancre1": "K42",
-        "tige_ancre1":"K43",
-        "cosse_ancre1": "K44",
-        "ecart_ancre1": "K45",
-        "type_ancre1": "K46",
-        "devi_ancre1": "K47",
-        "espace_dispo_ancre1": "K48",
-        "etat_ancre1": "K49",
-        "type_de_sol_ancre2": "M36",
-        "capacite_ancre2": "M37",
-        "angle_ancre2":"M38",
-        "hauban1_ancre2": "M39",
-        "hauban2_ancre2": "M40",
-        "hauban3_ancre2": "M41",
-        "hauban4_ancre2": "M42",
-        "tige_ancre2":"M43",
-        "cosse_ancre2": "M44",
-        "ecart_ancre2": "M45",
-        "type_ancre2": "M46",
-        "devi_ancre2": "M47",
-        "espace_dispo_ancre2": "M48",
-        "etat_ancre2": "M49",
-        "type_de_sol_ancre3": "N36",
-        "capacite_ancre3": "N37",
-        "angle_ancre3": "N38",
-        "hauban1_ancre3": "N39",
-        "hauban2_ancre3": "N40",
-        "hauban3_ancre3": "N41",
-        "hauban4_ancre3": "N42",
-        "tige_ancre3": "N43",
-        "cosse_ancre3": "N44",
-        "ecart_ancre3": "N45",
-        "type_ancre3": "N46",
-        "devi_ancre3": "N47",
-        "espace_dispo_ancre3": "N48",
-        "etat_ancre3": "N49",
-        "type_de_sol_ancre4": "O36",
-        "capacite_ancre4": "O37",
-        "angle_ancre4": "O38",
-        "hauban1_ancre4": "O39",
-        "hauban2_ancre4": "O40",
-        "hauban3_ancre4": "O41",
-        "hauban4_ancre4": "O42",
-        "tige_ancre4": "O43",
-        "cosse_ancre4": "O44",
-        "ecart_ancre4": "O45",
-        "type_ancre4": "O46",
-        "devi_ancre4": "O47",
-        "espace_dispo_ancre4": "O48",
-        "etat_ancre4": "O49",
-        "ligne_haute_tension": "K51",
-        "element_sensible": "O51",
-        "note": "A56",
-        "date": "K62",
-    }
-elif typeDoc == "rsa":
-    cells = {
-        "poteau": "B1",
-        "projet": "F1",
-        "révision": "I1",
-        "travaux": "B2",
-        "diametre": "D2",
-        "classification_travaux":'F2',
-        "anomalie_1": "B3",
-        "anomalie_2": "B4",
-        "anomalie_3": "B5",
-        "probleme_1": "E3",
-        "probleme_2": "E4",
-        "probleme_3": "E5",
-        "nom_poteau": "B6",
-        "adresse": "D6",
-        "plan": "G6",
-        "code_barre": "I6",
-        "pro_poteau": "B7",
-        "usage_commun:": "D7",
-        "parc": "F7",
-        "lclc": "I7",
-        "longueur": "B8",
-        "classe": "D8",
-        "annee": "F8",
-        "nbe_transfo": "H8",
-        "type_transfo": "I8",
-        "annee_inspection": "B9",
-        "modele_bell": "D9",
-        "modele_HQ": "F9",
-        "equip": "H9",
-        "fosse": "B9",
-        "hauteur_lampadaire": "D10",
-        "cabinet": "F10",
-        "hauteur_transfo": "H10",
-        "hauteur_top": "A14",
-        "portee_pre:": "B14",
-        "portee_sui:": "C14",
-        "portee_dero": "D14",
-        "toron_ins": "E14",
-        "milieu": "G13",
-        "hauteur_mt1": "A16",
-        "conducteur_mt1": "B16",
-        "phase_mt1": "C16",
-        "deri_mt1": "D16",
-        "hauteur_mt2": "A17",
-        "conducteur_mt2": "B17",
-        "phase_mt2": "C17",
-        "deri_mt2": "D17",
-        "hauteur_mt3": "A18",
-        "conducteur_mt3": "B18",
-        "phase_mt3": "C18",
-        "deri_mt3": "D18",
-        "hauteur_mt4": "A19",
-        "conducteur_mt4": "B19",
-        "phase_mt4": "C19",
-        "deri_mt4": "D19",
-        "hauteur_mt5": "A20",
-        "conducteur_mt5:": "B20",
-        "phase_mt5": "C20",
-        "deri_mt5": "D20",
-        "hauteur_bt1": "A27",
-        "conducteur_bt1": "B27",
-        "visee_bt1": "C27",
-        "deri_bt1": "D27",
-        "hauteur_bt2": "A26",
-        "conducteur_bt2": "B26",
-        "visee_bt2": "C26",
-        "deri_bt2": "D26",
-        "hauteur_bt3": "A25",
-        "conducteur_mbt3": "B25",
-        "visee_bt3": "C25",
-        "deri_bt3": "D25",
-        "hauteur_bt4": "A24",
-        "conducteur_bt4": "B24",
-        "visee_bt4": "C24",
-        "deri_bt4": "D24",
-        "hauteur_bt5": "A23",
-        "conducteur_bt5": "B23",
-        "visee_bt5": "C23",
-        "deri_bt5": "D23",
-        "hauteur_bt6": "A22",
-        "conducteur_bt6:": "B22",
-        "visee_bt6": "C22",
-        "deri_bt6": "D22",
-        "hauteur_toron1": "A29",
-        "proprio_toron1": "B29",
-        "type_toron1": "C29",
-        "nbe_de_cable_toron1": "D29",
-        "diametre_toron1": "E29",
-        "rupture_toron1": "F29",
-        "deg_sol_toron1": "G29",
-        "croisement_toron1": "H29",
-        "ancre_toron1": "I29",
-        "hauteur_toron2": "A30",
-        "proprio_toron2": "B30",
-        "type_toron2": "C30",
-        "nbe_de_cable_toron2": "D30",
-        "diametre_toron2": "E30",
-        "rupture_toron2": "F30",
-        "deg_sol_toron2": "G30",
-        "croisement_toron2": "H30",
-        "ancre_toron2": "I30",
-        "hauteur_toron3": "A31",
-        "proprio_toron3": "B31",
-        "type_toron3": "C31",
-        "nbe_de_cable_toron3": "D31",
-        "diametre_toron3": "E31",
-        "rupture_toron3": "F31",
-        "deg_sol_toron3": "G31",
-        "croisement_toron3": "H31",
-        "ancre_toron3": "I31",
-        "hauteur_toron4": "A32",
-        "proprio_toron4": "B32",
-        "type_toron4": "C32",
-        "nbe_de_cable_toron4": "D32",
-        "diametre_toron4": "E32",
-        "rupture_toron4": "F32",
-        "deg_sol_toron4": "G32",
-        "croisement_toron4": "H32",
-        "ancre_toron4": "I32",
-        "hauteur_toron5": "A33",
-        "proprio_toron5": "B33",
-        "type_toron5": "C33",
-        "nbe_de_cable_toron5": "D33",
-        "diametre_toron5": "E33",
-        "rupture_toron5": "F33",
-        "deg_sol_toron5": "G33",
-        "croisement_toron5": "H33",
-        "ancre_toron5": "I33",
-        "hauteur_toron6": "A34",
-        "proprio_toron6": "B34",
-        "type_toron6": "C34",
-        "nbe_de_cable_toron6": "D34",
-        "diametre_toron6": "E34",
-        "rupture_toron6": "F34",
-        "deg_sol_toron6": "G34",
-        "croisement_toron6": "H34",
-        "ancre_toron6": "I34",
-        "type_de_sol_ancre1": "F17",
-        "tige_ancre1": "F18",
-        "cosse_ancre1": "F19",
-        "type_ancre1": "F20",
-        "ecart_ancre1": "F21",
-        "hauban1_ancre1": "F22",
-        "hauban2_ancre1": "F23",
-        "hauban3_ancre1": "F24",
-        "hauban4_ancre1": "F25",
-        "etat_ancre1": "f26",
-        "espace_dispo_ancre1": "F27",
-        "type_de_sol_ancre2": "G17",
-        "tige_ancre2": "G18",
-        "cosse_ancre2": "G19",
-        "type_ancre2": "G20",
-        "ecart_ancre2": "G21",
-        "hauban1_ancre2": "G22",
-        "hauban2_ancre2": "G23",
-        "hauban3_ancre2": "G24",
-        "hauban4_ancre2": "G25",
-        "etat_ancre2": "G26",
-        "espace_dispo_ancre2": "G27",
-        "type_de_sol_ancre3": "H17",
-        "tige_ancre3": "H18",
-        "cosse_ancre3": "H19",
-        "type_ancre3": "H20",
-        "ecart_ancre3": "H21",
-        "hauban1_ancre3": "H22",
-        "hauban2_ancre3": "H23",
-        "hauban3_ancre3": "H24",
-        "hauban4_ancre3": "H25",
-        "etat_ancre3": "H26",
-        "espace_dispo_ancre3": "H27",
-        "type_de_sol_ancre4": "I17",
-        "tige_ancre4": "I18",
-        "cosse_ancre4": "I19",
-        "type_ancre4": "I20",
-        "ecart_ancre4": "I21",
-        "hauban1_ancre4": "I22",
-        "hauban2_ancre4": "I23",
-        "hauban3_ancre4": "I24",
-        "hauban4_ancre4": "I25",
-        "etat_ancre4": "I26",
-        "espace_dispo_ancre4": "I27" ,
-        "ligne_haute_tension": "A36",
-        "dis_appro": "C36",
-        "element_sensible": "D36",
-        "coord": "G36",
-        "note": "A38",
-        "date": "F49",
-        "releveur": "F47",
-    }
-else:
-    raise Exception("Erreur: typeDoc invalide (uds ou rsa requis)")
-
-# keep your type_poteaux & parc dictionaries exactly
-type_poteaux = {
-    74:(35, 5),
-    79:{'JP': (35, 5), 'SYP': (40, 5), 'LPP': (35, 5)},
-    80:(35, 4),
-    81:(35, 5),
-    82:(45, 5),
-    83:{'LPP': (40, 5), 'WRC': (35, 5)},
-    84:(40, 5),
-    86:{'RP': (40, 5), 'JP': (35, 4)},
-    87:(45, 5),
-    88:{'RP': (35, 4), 'JP': (45, 5), 'WRC': (40, 5)},
-    89:(45, 4),
-    90:{'RP': (45, 5), 'LPP': (40, 4), 'WRC': (35, 4)},
-    91:(40, 4),
-    92:(45, 5),
-    93:{'RP': (40, 4), 'SYP': (35, 2)},
-    94:(45, 4),
-    95:{'JP': (45, 4), 'WRC': (40, 4)},
-    97:(45, 4),
-    98: {'SYP': (40, 2), 'LPP': (35, 2)},
-    99:(35, 2),
-    100:(45, 4),
-    101:(35, 2),
-    103:{'SYP': (45, 2), 'WRC': (35, 2)},
-    104:(40, 2),
-    105:(40, 2),
-    107:(40, 2),
-    109:(45, 2),
-    110:{'JP': (45, 2), 'WRC': (40, 2)},
-    112:(45, 2),
-    115:(45, 2),
-}
-
-parc = {
-    "304":("saint-remi","saint-michel","sherrington"),
-    "339":("sainte-clotilde","saint-chrysostome","hemmingford","havelock"),
-    "303":("franklin","ormstown","saint-antoine","hinchinbrooke","godmanchester","huntingdon","saint-anicet","dundee","elgin"),
-    "306":("lacolle","napierville","saint-bernard-de-lacolle"),
-    "363":("saint-barbe","saint-stanislas-de-kostka","saint-etienne-de-beauharnois","saint-louis-de-gonzague"),
-}
-
-# We'll parse the txt content similar to your script
-lines = txt_content.splitlines()
-valeurs = {}
-outputs = []  # list of tuples (filename, bytes)
-
-def create_excel_from_valeurs(valeurs_dict):
-    # create a name and a workbook based on the uploaded template bytes
-    nom_du_poteau = valeurs_dict.get('poteau', 'poteau').strip() + '.xlsx'
-    # load a fresh workbook from template bytes
-    bio = io.BytesIO(template_bytes)
-    wb = load_workbook(filename=bio)
-    # choose 'Grille' sheet if exists else active
-    if 'Grille' in wb.sheetnames:
-        ws = wb['Grille']
-    else:
-        ws = wb.active
-
-    for key, value in list(valeurs_dict.items()):
-        try:
-            champs = cells[key]
-            ws[champs] = value
-        except Exception:
-            # ignore keys not present in cells
-            continue
-
-    out_bytes = save_workbook_to_bytes(wb)
-    return nom_du_poteau, out_bytes
-
-# helper to safely convert floats when needed
-def safe_float(x):
-    try:
-        return float(x)
-    except:
-        return None
-
-# The main parsing loop (close to your original)
-for line in lines:
-    if '---' in line:
-        # finalize current record
-        if 'poteau' in valeurs and valeurs.get('poteau','').strip() != '':
-            fname, b = create_excel_from_valeurs(valeurs)
-            outputs.append((fname, b))
-            console.log(f'Created output: {fname}')
-        valeurs = {}
-        continue
-
-    if line.strip() == "":
-        continue
-
-    if ':' not in line:
-        continue
-
-    variable, value = line.split(":", 1)
-    variable = variable.strip()
-    value = value.rstrip("\n")
-
-    # replicate your special handling rules
-    if 'hauteur' in variable:
-        if value.strip() == "":
-            continue
-        if value.strip() == 'tri':
-            # need hauteur_top present first
-            try:
-                valeurs["hauteur_top"] = str(valeurs["hauteur_top"].replace(",", "."))
-                value = str(float(valeurs['hauteur_top']) + 0.3)
-                #valeurs['hauteur_mt2'] = str(round(float(valeurs['hauteur_top']) - 0.15, 2))
-            except Exception:
-                # if hauteur_top missing, skip
-                console.log('marche pas')
-                pass
-            
-        # compute with hauteur_bosch (string)
-        try:
-            c = float(value)
-            a = 1
-            hb = float(hauteur_bosch)
-            b = (c**2 - a**2)**0.5 + hb
-            b = round(b, 2)
-            value = str(b).replace(".", ",")
-
-        except Exception as e:
-            # if numeric conversion fails, keep original value
-            console.log('hauteur calculation failed', e)
-            pass
-
-    if 'nom_poteau' in variable:
-        # copy name from 'poteau' (first token)
-        if 'poteau' in valeurs:
-            value = valeurs["poteau"].split(" ", 1)[0]
-
-    if 'adresse' in variable:
-
-         # =================================================================
-            # Utilise re.sub() pour retirer le texte non numérique au début,
-            # puis supprimer toute indication de type "+2" ou "-3" accolée
-            # au numéro principal, en conservant le reste de l'adresse.
-            #
-            # Expression utilisée : r'^\D*(\d+)(?:[+-]\d+)?(.*)'
-            # - ^         → dĂ©but de la chaĂźne
-            # - \D*       → zĂ©ro ou plusieurs caractĂšres qui NE sont PAS des chiffres
-            #               (supprime par exemple "PHD", "PHC", etc.)
-            # - (\d+)     → capture le numĂ©ro principal (un ou plusieurs chiffres)
-            # - (?: ... ) → parenthĂšses non capturantes (pour regrouper sans crĂ©er un groupe sĂ©parĂ©)
-            # - [+-]\d+   → un signe "+" ou "-" suivi d'un ou plusieurs chiffres
-            #               (par ex. "+2" ou "-3")
-            # - ?         → rend la partie [+-]\d+ optionnelle
-            # - (.*)      → capture tout le reste de la chaĂźne (l'adresse aprĂšs le numĂ©ro)
-            #
-            # Remplacement utilisé : r'\1\2'
-            # - \1 → insĂšre le numĂ©ro principal capturĂ©
-            # - \2 → insùre le texte restant de l'adresse
-            #
-            # Exemple :
-            # "PHD248+2 chemin de l'église" devient "248 chemin de l'église"
-            # "PHC300-1 rue des lilas"     devient "300 rue des lilas"
-            # =================================================================
-        if 'poteau' in valeurs:
-            value = re.sub(r'^\D*(\d+)(?:[+-]\d+)?(.*)', r'\1\2', valeurs["poteau"])
-
-    if 'date' in variable:
-        if typeDoc == 'uds':
-            value = str(nom_du_releveur + '\\n') + str(date.today())
-        else:
-            value = str(date.today())
-
-    if 'longueur' in variable:
-        
-        value = value.strip()
-       
-        try:
-            value_int = int(value)
-        except ValueError:           
-            continue
-
-        if value_int not in type_poteaux:
-            valeurs[variable] = value
-            continue
-
-        type_poteaux_entre = type_poteaux[value_int]
-       
-        if isinstance(type_poteaux_entre, dict):    
-            
-            bois = valeurs.get('bois', '').strip()
-            if bois == '':
-                value = next(iter(type_poteaux_entre.values()))[0]  
-                valeurs['classe'] = next(iter(type_poteaux_entre.values()))[1] 
-                valeurs[variable] = value                                             #Créer une itérateur qui permet de parcourir les éléments une par une
-                continue
-
-            valeurs['classe'] = type_poteaux_entre[bois][1]
-            value = type_poteaux_entre[bois][0]
-        else:
-            valeurs['classe'] = type_poteaux_entre[1]
-            value = type_poteaux_entre[0]
-
-    if "ville" in variable:
-        # determine parc key covering the town name
-        found = None
-        for k,v in parc.items():
-            if value.strip() in v:
-                found = k
-                break
-        valeurs['parc'] = found
-
-    if "releveur" in variable:
-
-        value = nom_du_releveur
-
-    # finally store the variable
-    valeurs[variable] = value
-
-# if file doesn't end with '---', create last record
-if valeurs and 'poteau' in valeurs and valeurs.get('poteau','').strip() != '':
-    fname, b = create_excel_from_valeurs(valeurs)
-    outputs.append((fname, b))
-
-from js import Uint8Array, Blob, URL, document
-
-for fname, bbytes in outputs:
-    u8 = Uint8Array.new(bbytes)  # explicitly convert Python bytes to JS Uint8Array
-    blob = Blob.new([u8], { "type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" })
-    url = URL.createObjectURL(blob)
-    a = document.createElement("a")
-    a.href = url
-    a.download = fname
-    a.textContent = "[Télécharger] " + fname
-    document.getElementById("downloads").appendChild(a)
-    console.log("Prepared download for " + fname)
-
-
-# also print a summary to the page console element
-from js import console as js_console
-js_console.log(f"Created {len(outputs)} file(s).")
-print(f"Created {len(outputs)} file(s).")  # visible in the log element too
-
-
-
-
-
-
-
-
-
+import io, re, shutil, random
+from datetime import date
+import sys
+from openpyxl import load_workbook
+from io import BytesIO
+from openpyxl import Workbook
+from js import console
+
+
+def save_workbook_to_bytes(wb):
+    buffer = io.BytesIO()
+    wb.save(buffer)
+    return buffer.getvalue()
+
+# Pull variables set by JS
+template_uint8 = globals().get("template_uint8")                  #get les id du html par le java
+txt_content = globals().get("txt_content")
+typeDoc = globals().get("typeDoc")
+nom_du_releveur = globals().get("nom_du_releveur")
+hauteur_bosch = globals().get("hauteur_bosch")
+
+# Convert template bytes into Python bytes
+template_bytes = bytes(template_uint8)
+
+# --- Start of your original dictionaries and logic (slightly adapted) ---
+
+cells = {}
+if typeDoc == "uds":
+    cells = {
+        "poteau": "B4",
+        "projet": "K3",
+        "révision": "O3",
+        "travaux": "B3",
+        "diametre": "H3",
+        "adresse": "K4",
+        "plan": "H4",
+        "code_barre": "N6",
+        "pro_poteau": "K7",
+        "annee_inspection": "H5",
+        "parc": "K5",
+        "option_HQ":"N5",
+        "longueur": "C6",
+        "classe": "D6",
+        "annee": "H6",
+        "circonference": "K6",
+        "p/r":"D7",
+        "usage_commun:": "O7",
+        "angle": "K13",
+        "lclc": "K14",
+        "nbe_transfo": "L15",
+        "type_transfo": "K15",
+        "equip": "K16",
+        "gradation": "K17",
+        "lampadaire":"K18",
+        "las":"K19",
+        "montage_HQ":"K20",
+        "portee_lache":"K21",
+        "portee_pre:": "K22",
+        "portee_sui:": "N22",
+        "malt":"N21",
+        "reseau":"N20",
+        "cabinet":"O19",
+        "luminaire":"N18",
+        "traverse":"O17",
+        "las":"N16",
+        "fosse": "O14",
+        "hauteur_transfo": "O15",
+        "hauteur_top": "A11",
+        "portee_pre:": "B14",
+        "portee_sui:": "C14",
+        "hauteur_mt1": "A14",
+        "conducteur_mt1": "C14",
+        "phase_mt1": "B14",
+        "deri_mt1": "D14",
+        "hauteur_mt2": "A15",
+        "conducteur_mt2": "C15",
+        "phase_mt2": "B15",
+        "deri_mt2": "D15",
+        "hauteur_mt3:": "A16",
+        "conducteur_mt3": "C16",
+        "phase_mt3": "B16",
+        "deri_mt3": "D16",
+        "hauteur_bt1": "A23",
+        "conducteur_bt1": "B23",
+        "visee_bt1": "C23",
+        "deri_bt1": "D23",
+        "hauteur_bt2": "A22",
+        "conducteur_bt2": "B22",
+        "visee_bt2": "C22",
+        "deri_bt2": "D22",
+        "hauteur_bt3": "A21",
+        "conducteur_mbt3": "B21",
+        "visee_bt3": "C21",
+        "deri_bt3": "D21",
+        "hauteur_bt4": "A20",
+        "conducteur_bt4": "B20",
+        "visee_bt4": "C20",
+        "deri_bt4": "D20",
+        "hauteur_bt5": "A19",
+        "conducteur_bt5": "B19",
+        "visee_bt5": "C19",
+        "deri_bt5": "D19",
+        "hauteur_bt6": "A18",
+        "conducteur_bt6:": "B18",
+        "visee_bt6": "C18",
+        "deri_bt6": "D18",
+        "hauteur_toron1": "A27",
+        "proprio_toron1": "B27",
+        "toron1_existant": "C27",
+        "deri":"D27",
+        "type_toron1": "J27",
+        "nbe_de_cable_toron1": "L27",
+        "diametre_toron1": "K27",
+        "rupture_toron1": "M27",
+        "deg_sol_toron1": "N27",
+        "ancre_toron1": "O27",
+        "hauteur_toron2": "A28",
+        "proprio_toron2": "B28",
+        "existant_toron2": "C28",
+        "deri_toron2": "D28",
+        "type_toron2": "J28",
+        "nbe_de_cable_toron2": "L28",
+        "diametre_toron2": "K28",
+        "rupture_toron2": "M28",
+        "deg_sol_toron2": "N28",
+        "ancre_toron2": "O28",
+        "hauteur_toron3": "A29",
+        "proprio_toron3": "B29",
+        "existant_toron3": "C29",
+        "deri_toron3": "D29",
+        "type_toron3": "J29",
+        "nbe_de_cable_toron3": "L29",
+        "diametre_toron3": "K29",
+        "rupture_toron3": "M29",
+        "deg_sol_toron3": "N29",
+        "ancre_toron3": "O29",
+        "hauteur_toron4": "A30",
+        "proprio_toron4": "B30",
+        "existant_toron4": "C30",
+        "deri_toron4": "D30",
+        "type_toron4": "J30",
+        "nbe_de_cable_toron4": "L30",
+        "diametre_toron4": "K30",
+        "rupture_toron4": "M30",
+        "deg_sol_toron4": "N30",
+        "ancre_toron4": "O30",
+        "hauteur_toron5": "A31",
+        "proprio_toron5": "B31",
+        "existant_toron5": "C31",
+        "deri_toron5": "D31",
+        "type_toron5": "J31",
+        "nbe_de_cable_toron5": "L31",
+        "diametre_toron5": "K31",
+        "rupture_toron5": "M31",
+        "deg_sol_toron5": "N31",
+        "ancre_toron5": "O31",
+        "hauteur_toron6": "A32",
+        "proprio_toron6": "B32",
+        "existant_toron6": "C32",
+        "deri_toron6": "D32",
+        "type_toron6": "J32",
+        "nbe_de_cable_toron6": "L32",
+        "diametre_toron6": "K32",
+        "rupture_toron6": "M32",
+        "deg_sol_toron6": "N32",
+        "ancre_toron6": "O32",
+        "type_de_sol_ancre1": "K36",
+        "capacite_ancre1": "K37",
+        "angle_ancre1":"K38",
+        "hauban1_ancre1": "K39",
+        "hauban2_ancre1": "K40",
+        "hauban3_ancre1": "K41",
+        "hauban4_ancre1": "K42",
+        "tige_ancre1":"K43",
+        "cosse_ancre1": "K44",
+        "ecart_ancre1": "K45",
+        "type_ancre1": "K46",
+        "devi_ancre1": "K47",
+        "espace_dispo_ancre1": "K48",
+        "etat_ancre1": "K49",
+        "type_de_sol_ancre2": "M36",
+        "capacite_ancre2": "M37",
+        "angle_ancre2":"M38",
+        "hauban1_ancre2": "M39",
+        "hauban2_ancre2": "M40",
+        "hauban3_ancre2": "M41",
+        "hauban4_ancre2": "M42",
+        "tige_ancre2":"M43",
+        "cosse_ancre2": "M44",
+        "ecart_ancre2": "M45",
+        "type_ancre2": "M46",
+        "devi_ancre2": "M47",
+        "espace_dispo_ancre2": "M48",
+        "etat_ancre2": "M49",
+        "type_de_sol_ancre3": "N36",
+        "capacite_ancre3": "N37",
+        "angle_ancre3": "N38",
+        "hauban1_ancre3": "N39",
+        "hauban2_ancre3": "N40",
+        "hauban3_ancre3": "N41",
+        "hauban4_ancre3": "N42",
+        "tige_ancre3": "N43",
+        "cosse_ancre3": "N44",
+        "ecart_ancre3": "N45",
+        "type_ancre3": "N46",
+        "devi_ancre3": "N47",
+        "espace_dispo_ancre3": "N48",
+        "etat_ancre3": "N49",
+        "type_de_sol_ancre4": "O36",
+        "capacite_ancre4": "O37",
+        "angle_ancre4": "O38",
+        "hauban1_ancre4": "O39",
+        "hauban2_ancre4": "O40",
+        "hauban3_ancre4": "O41",
+        "hauban4_ancre4": "O42",
+        "tige_ancre4": "O43",
+        "cosse_ancre4": "O44",
+        "ecart_ancre4": "O45",
+        "type_ancre4": "O46",
+        "devi_ancre4": "O47",
+        "espace_dispo_ancre4": "O48",
+        "etat_ancre4": "O49",
+        "ligne_haute_tension": "K51",
+        "element_sensible": "O51",
+        "note": "A56",
+        "date": "K62",
+    }
+elif typeDoc == "rsa":
+    cells = {
+        "poteau": "B1",
+        "projet": "F1",
+        "révision": "I1",
+        "travaux": "B2",
+        "diametre": "D2",
+        "classification_travaux":'F2',
+        "anomalie_1": "B3",
+        "anomalie_2": "B4",
+        "anomalie_3": "B5",
+        "probleme_1": "E3",
+        "probleme_2": "E4",
+        "probleme_3": "E5",
+        "nom_poteau": "B6",
+        "adresse": "D6",
+        "plan": "G6",
+        "code_barre": "I6",
+        "pro_poteau": "B7",
+        "usage_commun:": "D7",
+        "parc": "F7",
+        "lclc": "I7",
+        "longueur": "B8",
+        "classe": "D8",
+        "annee": "F8",
+        "nbe_transfo": "H8",
+        "type_transfo": "I8",
+        "annee_inspection": "B9",
+        "modele_bell": "D9",
+        "modele_HQ": "F9",
+        "equip": "H9",
+        "fosse": "B9",
+        "hauteur_lampadaire": "D10",
+        "cabinet": "F10",
+        "hauteur_transfo": "H10",
+        "hauteur_top": "A14",
+        "portee_pre:": "B14",
+        "portee_sui:": "C14",
+        "portee_dero": "D14",
+        "toron_ins": "E14",
+        "milieu": "G13",
+        "hauteur_mt1": "A16",
+        "conducteur_mt1": "B16",
+        "phase_mt1": "C16",
+        "deri_mt1": "D16",
+        "hauteur_mt2": "A17",
+        "conducteur_mt2": "B17",
+        "phase_mt2": "C17",
+        "deri_mt2": "D17",
+        "hauteur_mt3": "A18",
+        "conducteur_mt3": "B18",
+        "phase_mt3": "C18",
+        "deri_mt3": "D18",
+        "hauteur_mt4": "A19",
+        "conducteur_mt4": "B19",
+        "phase_mt4": "C19",
+        "deri_mt4": "D19",
+        "hauteur_mt5": "A20",
+        "conducteur_mt5:": "B20",
+        "phase_mt5": "C20",
+        "deri_mt5": "D20",
+        "hauteur_bt1": "A27",
+        "conducteur_bt1": "B27",
+        "visee_bt1": "C27",
+        "deri_bt1": "D27",
+        "hauteur_bt2": "A26",
+        "conducteur_bt2": "B26",
+        "visee_bt2": "C26",
+        "deri_bt2": "D26",
+        "hauteur_bt3": "A25",
+        "conducteur_mbt3": "B25",
+        "visee_bt3": "C25",
+        "deri_bt3": "D25",
+        "hauteur_bt4": "A24",
+        "conducteur_bt4": "B24",
+        "visee_bt4": "C24",
+        "deri_bt4": "D24",
+        "hauteur_bt5": "A23",
+        "conducteur_bt5": "B23",
+        "visee_bt5": "C23",
+        "deri_bt5": "D23",
+        "hauteur_bt6": "A22",
+        "conducteur_bt6:": "B22",
+        "visee_bt6": "C22",
+        "deri_bt6": "D22",
+        "hauteur_toron1": "A29",
+        "proprio_toron1": "B29",
+        "type_toron1": "C29",
+        "nbe_de_cable_toron1": "D29",
+        "diametre_toron1": "E29",
+        "rupture_toron1": "F29",
+        "deg_sol_toron1": "G29",
+        "croisement_toron1": "H29",
+        "ancre_toron1": "I29",
+        "hauteur_toron2": "A30",
+        "proprio_toron2": "B30",
+        "type_toron2": "C30",
+        "nbe_de_cable_toron2": "D30",
+        "diametre_toron2": "E30",
+        "rupture_toron2": "F30",
+        "deg_sol_toron2": "G30",
+        "croisement_toron2": "H30",
+        "ancre_toron2": "I30",
+        "hauteur_toron3": "A31",
+        "proprio_toron3": "B31",
+        "type_toron3": "C31",
+        "nbe_de_cable_toron3": "D31",
+        "diametre_toron3": "E31",
+        "rupture_toron3": "F31",
+        "deg_sol_toron3": "G31",
+        "croisement_toron3": "H31",
+        "ancre_toron3": "I31",
+        "hauteur_toron4": "A32",
+        "proprio_toron4": "B32",
+        "type_toron4": "C32",
+        "nbe_de_cable_toron4": "D32",
+        "diametre_toron4": "E32",
+        "rupture_toron4": "F32",
+        "deg_sol_toron4": "G32",
+        "croisement_toron4": "H32",
+        "ancre_toron4": "I32",
+        "hauteur_toron5": "A33",
+        "proprio_toron5": "B33",
+        "type_toron5": "C33",
+        "nbe_de_cable_toron5": "D33",
+        "diametre_toron5": "E33",
+        "rupture_toron5": "F33",
+        "deg_sol_toron5": "G33",
+        "croisement_toron5": "H33",
+        "ancre_toron5": "I33",
+        "hauteur_toron6": "A34",
+        "proprio_toron6": "B34",
+        "type_toron6": "C34",
+        "nbe_de_cable_toron6": "D34",
+        "diametre_toron6": "E34",
+        "rupture_toron6": "F34",
+        "deg_sol_toron6": "G34",
+        "croisement_toron6": "H34",
+        "ancre_toron6": "I34",
+        "type_de_sol_ancre1": "F17",
+        "tige_ancre1": "F18",
+        "cosse_ancre1": "F19",
+        "type_ancre1": "F20",
+        "ecart_ancre1": "F21",
+        "hauban1_ancre1": "F22",
+        "hauban2_ancre1": "F23",
+        "hauban3_ancre1": "F24",
+        "hauban4_ancre1": "F25",
+        "etat_ancre1": "f26",
+        "espace_dispo_ancre1": "F27",
+        "type_de_sol_ancre2": "G17",
+        "tige_ancre2": "G18",
+        "cosse_ancre2": "G19",
+        "type_ancre2": "G20",
+        "ecart_ancre2": "G21",
+        "hauban1_ancre2": "G22",
+        "hauban2_ancre2": "G23",
+        "hauban3_ancre2": "G24",
+        "hauban4_ancre2": "G25",
+        "etat_ancre2": "G26",
+        "espace_dispo_ancre2": "G27",
+        "type_de_sol_ancre3": "H17",
+        "tige_ancre3": "H18",
+        "cosse_ancre3": "H19",
+        "type_ancre3": "H20",
+        "ecart_ancre3": "H21",
+        "hauban1_ancre3": "H22",
+        "hauban2_ancre3": "H23",
+        "hauban3_ancre3": "H24",
+        "hauban4_ancre3": "H25",
+        "etat_ancre3": "H26",
+        "espace_dispo_ancre3": "H27",
+        "type_de_sol_ancre4": "I17",
+        "tige_ancre4": "I18",
+        "cosse_ancre4": "I19",
+        "type_ancre4": "I20",
+        "ecart_ancre4": "I21",
+        "hauban1_ancre4": "I22",
+        "hauban2_ancre4": "I23",
+        "hauban3_ancre4": "I24",
+        "hauban4_ancre4": "I25",
+        "etat_ancre4": "I26",
+        "espace_dispo_ancre4": "I27" ,
+        "ligne_haute_tension": "A36",
+        "dis_appro": "C36",
+        "element_sensible": "D36",
+        "coord": "G36",
+        "note": "A38",
+        "date": "F49",
+        "releveur": "F47",
+    }
+else:
+    raise Exception("Erreur: typeDoc invalide (uds ou rsa requis)")
+
+# keep your type_poteaux & parc dictionaries exactly
+type_poteaux = {
+    74:(35, 5),
+    79:{'JP': (35, 5), 'SYP': (40, 5), 'LPP': (35, 5)},
+    80:(35, 4),
+    81:(35, 5),
+    82:(45, 5),
+    83:{'LPP': (40, 5), 'WRC': (35, 5)},
+    84:(40, 5),
+    86:{'RP': (40, 5), 'JP': (35, 4)},
+    87:(45, 5),
+    88:{'RP': (35, 4), 'JP': (45, 5), 'WRC': (40, 5)},
+    89:(45, 4),
+    90:{'RP': (45, 5), 'LPP': (40, 4), 'WRC': (35, 4)},
+    91:(40, 4),
+    92:(45, 5),
+    93:{'RP': (40, 4), 'SYP': (35, 2)},
+    94:(45, 4),
+    95:{'JP': (45, 4), 'WRC': (40, 4)},
+    97:(45, 4),
+    98: {'SYP': (40, 2), 'LPP': (35, 2)},
+    99:(35, 2),
+    100:(45, 4),
+    101:(35, 2),
+    103:{'SYP': (45, 2), 'WRC': (35, 2)},
+    104:(40, 2),
+    105:(40, 2),
+    107:(40, 2),
+    109:(45, 2),
+    110:{'JP': (45, 2), 'WRC': (40, 2)},
+    112:(45, 2),
+    115:(45, 2),
+}
+
+parc = {
+    "304":("saint-remi","saint-michel","sherrington"),
+    "339":("sainte-clotilde","saint-chrysostome","hemmingford","havelock"),
+    "303":("franklin","ormstown","saint-antoine","hinchinbrooke","godmanchester","huntingdon","saint-anicet","dundee","elgin"),
+    "306":("lacolle","napierville","saint-bernard-de-lacolle"),
+    "363":("saint-barbe","saint-stanislas-de-kostka","saint-etienne-de-beauharnois","saint-louis-de-gonzague"),
+}
+
+# We'll parse the txt content similar to your script
+lines = txt_content.splitlines()
+valeurs = {}
+outputs = []  # list of tuples (filename, bytes)
+
+def create_excel_from_valeurs(valeurs_dict):
+    # create a name and a workbook based on the uploaded template bytes
+    nom_du_poteau = valeurs_dict.get('poteau', 'poteau').strip() + '.xlsx'
+    # load a fresh workbook from template bytes
+    bio = io.BytesIO(template_bytes)
+    wb = load_workbook(filename=bio)
+    # choose 'Grille' sheet if exists else active
+    if 'Grille' in wb.sheetnames:
+        ws = wb['Grille']
+    else:
+        ws = wb.active
+
+    for key, value in list(valeurs_dict.items()):
+        try:
+            champs = cells[key]
+            ws[champs] = value
+        except Exception:
+            # ignore keys not present in cells
+            continue
+
+    out_bytes = save_workbook_to_bytes(wb)
+    return nom_du_poteau, out_bytes
+
+# helper to safely convert floats when needed
+def safe_float(x):
+    try:
+        return float(x)
+    except:
+        return None
+
+# The main parsing loop (close to your original)
+for line in lines:
+    if '---' in line:
+        # finalize current record
+        if 'poteau' in valeurs and valeurs.get('poteau','').strip() != '':
+            fname, b = create_excel_from_valeurs(valeurs)
+            outputs.append((fname, b))
+            console.log(f'Created output: {fname}')
+        valeurs = {}
+        continue
+
+    if line.strip() == "":
+        continue
+
+    if ':' not in line:
+        continue
+
+    variable, value = line.split(":", 1)
+    variable = variable.strip()
+    value = value.rstrip("\n")
+
+    # replicate your special handling rules
+    if 'hauteur' in variable:
+        if value.strip() == "":
+            continue
+        if value.strip() == 'tri':
+            # need hauteur_top present first
+            try:
+                valeurs["hauteur_top"] = str(valeurs["hauteur_top"].replace(",", "."))
+                value = str(float(valeurs['hauteur_top']) + 0.3)
+                #valeurs['hauteur_mt2'] = str(round(float(valeurs['hauteur_top']) - 0.15, 2))
+            except Exception:
+                # if hauteur_top missing, skip
+                console.log('marche pas')
+                pass
+            
+        # compute with hauteur_bosch (string)
+        try:
+            c = float(value)
+            a = 1
+            hb = float(hauteur_bosch)
+            b = (c**2 - a**2)**0.5 + hb
+            b = round(b, 2)
+            value = str(b).replace(".", ",")
+
+        except Exception as e:
+            # if numeric conversion fails, keep original value
+            console.log('hauteur calculation failed', e)
+            pass
+
+    if 'nom_poteau' in variable:
+        # copy name from 'poteau' (first token)
+        if 'poteau' in valeurs:
+            value = valeurs["poteau"].split(" ", 1)[0]
+
+    if 'adresse' in variable:
+
+         # =================================================================
+            # Utilise re.sub() pour retirer le texte non numérique au début,
+            # puis supprimer toute indication de type "+2" ou "-3" accolée
+            # au numéro principal, en conservant le reste de l'adresse.
+            #
+            # Expression utilisée : r'^\D*(\d+)(?:[+-]\d+)?(.*)'
+            # - ^         → dĂ©but de la chaĂźne
+            # - \D*       → zĂ©ro ou plusieurs caractĂšres qui NE sont PAS des chiffres
+            #               (supprime par exemple "PHD", "PHC", etc.)
+            # - (\d+)     → capture le numĂ©ro principal (un ou plusieurs chiffres)
+            # - (?: ... ) → parenthĂšses non capturantes (pour regrouper sans crĂ©er un groupe sĂ©parĂ©)
+            # - [+-]\d+   → un signe "+" ou "-" suivi d'un ou plusieurs chiffres
+            #               (par ex. "+2" ou "-3")
+            # - ?         → rend la partie [+-]\d+ optionnelle
+            # - (.*)      → capture tout le reste de la chaĂźne (l'adresse aprĂšs le numĂ©ro)
+            #
+            # Remplacement utilisé : r'\1\2'
+            # - \1 → insĂšre le numĂ©ro principal capturĂ©
+            # - \2 → insùre le texte restant de l'adresse
+            #
+            # Exemple :
+            # "PHD248+2 chemin de l'église" devient "248 chemin de l'église"
+            # "PHC300-1 rue des lilas"     devient "300 rue des lilas"
+            # =================================================================
+        if 'poteau' in valeurs:
+            value = re.sub(r'^\D*(\d+)(?:[+-]\d+)?(.*)', r'\1\2', valeurs["poteau"])
+
+    if 'date' in variable:
+        if typeDoc == 'uds':
+            value = str(nom_du_releveur + '\\n') + str(date.today())
+        else:
+            value = str(date.today())
+
+    if 'longueur' in variable:
+        
+        value = value.strip()
+       
+        try:
+            value_int = int(value)
+        except ValueError:           
+            continue
+
+        if value_int not in type_poteaux:
+            valeurs[variable] = value
+            continue
+
+        type_poteaux_entre = type_poteaux[value_int]
+       
+        if isinstance(type_poteaux_entre, dict):    
+            
+            bois = valeurs.get('bois', '').strip()
+            if bois == '':
+                value = next(iter(type_poteaux_entre.values()))[0]  
+                valeurs['classe'] = next(iter(type_poteaux_entre.values()))[1] 
+                valeurs[variable] = value                                             #Créer une itérateur qui permet de parcourir les éléments une par une
+                continue
+
+            valeurs['classe'] = type_poteaux_entre[bois][1]
+            value = type_poteaux_entre[bois][0]
+        else:
+            valeurs['classe'] = type_poteaux_entre[1]
+            value = type_poteaux_entre[0]
+
+    if "ville" in variable:
+        # determine parc key covering the town name
+        found = None
+        for k,v in parc.items():
+            if value.strip() in v:
+                found = k
+                break
+        valeurs['parc'] = found
+
+    if "releveur" in variable:
+
+        value = nom_du_releveur
+
+    # finally store the variable
+    valeurs[variable] = value
+
+# if file doesn't end with '---', create last record
+if valeurs and 'poteau' in valeurs and valeurs.get('poteau','').strip() != '':
+    fname, b = create_excel_from_valeurs(valeurs)
+    outputs.append((fname, b))
+
+from js import Uint8Array, Blob, URL, document
+
+for fname, bbytes in outputs:
+    u8 = Uint8Array.new(bbytes)  # explicitly convert Python bytes to JS Uint8Array
+    blob = Blob.new([u8], { "type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" })
+    url = URL.createObjectURL(blob)
+    a = document.createElement("a")
+    a.href = url
+    a.download = fname
+    a.textContent = "[Télécharger] " + fname
+    document.getElementById("downloads").appendChild(a)
+    console.log("Prepared download for " + fname)
+
+
+# also print a summary to the page console element
+from js import console as js_console
+js_console.log(f"Created {len(outputs)} file(s).")
+print(f"Created {len(outputs)} file(s).")  # visible in the log element too
+
+
+
+
+
+
+
+
+
diff --git a/modele texte RSA.txt b/modele texte RSA.txt
index b54c7f1..4bbd813 100644
--- a/modele texte RSA.txt	
+++ b/modele texte RSA.txt	
@@ -1,87 +1,88 @@
-poteau:
-nom_poteau:
-adresse:
-projet:
-travaux: Toron Existant
-diametre: 0.113
-classification_travaux:
-parc:
-ville:
-
-anomalie_1:
-probleme_1:
-
-lclc:
-code_barre:
-classe:
-longueur:
-nbe_transfo:
-type_transfo:
-equip:
-annee:
-annee_inspection:
-
-hauteur_top:
-hauteur_mt1:
-hauteur_mt2:
-hauteur_transfo:
-hauteur_bt1:
-hauteur_bt2:
-hauteur_lampadaire:
-hauteur_toron1:
-hauteur_toron2:
-
-conducteur_mt1:
-phase_mt1:
-dero_mt1:
-
-conducteur_mt2:
-phase_mt2:
-deri_mt2:
-
-conducteur_bt1:
-visee_bt1:
-deri_bt1:
-
-conducteur_bt2:
-visee_bt2:
-deri_bt2:
-
-proprio_toron1:
-type_toron1:
-nbe_de_cĂąble_toron1:
-diametre_toron1:
-deg_sol_toron1:
-croisement_toron1:
-ancre_toron1:
-
-proprio_toron2:
-type_toron2:
-nbe_de_cĂąble_toron2:
-diametre_toron2:
-deg_sol_toron2:
-croisement_toron2:
-ancre_toron2:
-
-tige_ancre1:
-cosse_ancre1:
-type_ancre1:
-ecart_ancre1:
-hauban1_ancre1:
-hauban2_ancre1:
-hauban3_ancre1:
-etat_ancre1:
-espace_dispo_ancre1:
-
-tige_ancre2:
-cosse_ancre2:
-type_ancre2:
-ecart_ancre2:
-hauban1_ancre2:
-hauban2_ancre2:
-hauban3_ancre2:
-etat_ancre2:
-espace_dispo_ancre2:
-
-note:
+poteau:
+nom_poteau:
+adresse:
+projet:
+travaux: Toron Existant
+diametre: 0.113
+classification_travaux:
+parc:
+ville:
+
+anomalie_1:
+probleme_1:
+
+lclc:
+code_barre:
+classe:
+longueur:
+nbe_transfo:
+type_transfo:
+equip:
+annee:
+annee_inspection:
+
+hauteur_top:
+hauteur_mt1:
+hauteur_mt2:
+hauteur_mt3:
+hauteur_transfo:
+hauteur_bt1:
+hauteur_bt2:
+hauteur_lampadaire:
+hauteur_toron1:
+hauteur_toron2:
+
+conducteur_mt1:
+phase_mt1:
+dero_mt1:
+
+conducteur_mt2:
+phase_mt2:
+deri_mt2:
+
+conducteur_bt1:
+visee_bt1:
+deri_bt1:
+
+conducteur_bt2:
+visee_bt2:
+deri_bt2:
+
+proprio_toron1:
+type_toron1:
+nbe_de_cĂąble_toron1:
+diametre_toron1:
+deg_sol_toron1:
+croisement_toron1:
+ancre_toron1:
+
+proprio_toron2:
+type_toron2:
+nbe_de_cĂąble_toron2:
+diametre_toron2:
+deg_sol_toron2:
+croisement_toron2:
+ancre_toron2:
+
+tige_ancre1:
+cosse_ancre1:
+type_ancre1:
+ecart_ancre1:
+hauban1_ancre1:
+hauban2_ancre1:
+hauban3_ancre1:
+etat_ancre1:
+espace_dispo_ancre1:
+
+tige_ancre2:
+cosse_ancre2:
+type_ancre2:
+ecart_ancre2:
+hauban1_ancre2:
+hauban2_ancre2:
+hauban3_ancre2:
+etat_ancre2:
+espace_dispo_ancre2:
+
+note:
 date:
\ No newline at end of file
diff --git a/selenium.py b/selenium.py
index 8872554..c03ed30 100644
--- a/selenium.py
+++ b/selenium.py
@@ -1,40 +1,40 @@
-from selenium import webdriver
-from selenium.webdriver.chrome.service import Service
-from selenium.webdriver.common.by import By
-from selenium.webdriver.common.keys import Keys
-import time
-
-# Chemin vers ChromeDriver
-CHROMEDRIVER_PATH = "./chromedriver"  # Remplacez par le chemin correct
-
-# Options pour Chrome
-options = webdriver.ChromeOptions()
-options.add_argument("--headless")  # Mode sans interface graphique
-options.add_argument("--disable-gpu")
-options.add_argument("--window-size=1920,1080")
-
-# Initialisation du driver
-service = Service(CHROMEDRIVER_PATH)
-driver = webdriver.Chrome(service=service, options=options)
-
-try:
-    # Ouvrir la page
-    url = "https://www.consortiumdus.com/DUSS/Demande/Liste"
-    driver.get(url)
-    time.sleep(3)  # Attendre le chargement
-
-    # Vérifier si une connexion est requise
-    if "login" in driver.current_url.lower():
-        print("Page de connexion détectée. Ajoutez ici le code pour la connexion.")
-        # Exemple : remplir un formulaire de connexion
-        # username_input = driver.find_element(By.ID, "username")
-        # password_input = driver.find_element(By.ID, "password")
-        # username_input.send_keys("votre_identifiant")
-        # password_input.send_keys("votre_mot_de_passe")
-        # password_input.send_keys(Keys.RETURN)
-        # time.sleep(3)  # Attendre la redirection
-
-    print("Navigation réussie !")
-
-finally:
+from selenium import webdriver
+from selenium.webdriver.chrome.service import Service
+from selenium.webdriver.common.by import By
+from selenium.webdriver.common.keys import Keys
+import time
+
+# Chemin vers ChromeDriver
+CHROMEDRIVER_PATH = "./chromedriver"  # Remplacez par le chemin correct
+
+# Options pour Chrome
+options = webdriver.ChromeOptions()
+options.add_argument("--headless")  # Mode sans interface graphique
+options.add_argument("--disable-gpu")
+options.add_argument("--window-size=1920,1080")
+
+# Initialisation du driver
+service = Service(CHROMEDRIVER_PATH)
+driver = webdriver.Chrome(service=service, options=options)
+
+try:
+    # Ouvrir la page
+    url = "https://www.consortiumdus.com/DUSS/Demande/Liste"
+    driver.get(url)
+    time.sleep(3)  # Attendre le chargement
+
+    # Vérifier si une connexion est requise
+    if "login" in driver.current_url.lower():
+        print("Page de connexion détectée. Ajoutez ici le code pour la connexion.")
+        # Exemple : remplir un formulaire de connexion
+        # username_input = driver.find_element(By.ID, "username")
+        # password_input = driver.find_element(By.ID, "password")
+        # username_input.send_keys("votre_identifiant")
+        # password_input.send_keys("votre_mot_de_passe")
+        # password_input.send_keys(Keys.RETURN)
+        # time.sleep(3)  # Attendre la redirection
+
+    print("Navigation réussie !")
+
+finally:
     driver.quit()
\ No newline at end of file
diff --git a/test.txt b/test.txt
index c96a9b1..e33f0ef 100644
--- a/test.txt
+++ b/test.txt
@@ -1,102 +1,123 @@
-poteau:PHD4-1 rue Church
-nom_poteau:
-adresse:
-travaux:
-diametre:0.113
-
-anomalie_1:
-probleme_1:
-
-lclc:R8M4B
-code_barre:LS1DRS
-classe:
-longueur:86
-nbe_transfo:
-type_transfo:
-equip:Coupe-circuit
-annee:2001
-annee_inspection:2021
-circonference:
-bois:
-date:
-releveur:
-
-hauteur_top:9.96
-hauteur_mt1:tri
-hauteur_mt2:
-hauteur_mt3:9.27
-hauteur_transfo:
-hauteur_bt1:6.57
-hauteur_bt2:6.67
-hauteur_lampadaire:6.07
-hauteur_toron1:4.27
-hauteur_toron2:4.07
-hauteur_toron3:3.87
-hauteur_toron4:4.07
-
-conducteur_mt1:477 MCM
-phase_mt1:triphasé
-dero_mt1:
-
-conducteur_mt2:477 MCM
-phase_mt2:Triphasé
-deri_mt2:
-
-conducteur_mt3:2/0 ACSR
-phase_mt3:Triphasé
-deri_mt3:
-
-conducteur_bt1:TX 4/0
-visee_bt1:Non
-deri_bt1:
-
-conducteur_bt2:2/0 Acsr
-visee_bt2:Non
-deri_bt2:
-
-proprio_toron1:Bell
-type_toron1:10M
-nbe_de_cĂąble_toron1:3
-diametre_toron1:35mm
-deg_sol_toron1:
-croisement_toron1:
-ancre_toron1:
-
-proprio_toron2:Bell
-type_toron2:10M
-nbe_de_cĂąble_toron2:3
-diametre_toron2:30mm
-deg_sol_toron2:
-croisement_toron2:
-ancre_toron2:
-
-proprio_toron3:Bell
-type_toron3:10M
-nbe_de_cĂąble_toron3:3
-diametre_toron3:20mm
-deg_sol_toron3:2.72
-croisement_toron3:
-ancre_toron3:
-
-proprio_toron4:Bell
-type_toron4:6M
-nbe_de_cĂąble_toron4:1
-diametre_toron4:15mm
-deg_sol_toron4:3.50
-croisement_toron4:
-ancre_toron4:1
-
-note:degagement non ok toron attacj
-Her
-
-tige_ancre1: 3/4
-cosse_ancre1:4
-type_ancre1:256p
-ecart_ancre1:4.8
-hauban1_ancre1:6M
-hauban2_ancre1:3/16
-hauban3_ancre1:5/16
-hauban4_ancre1:5/16
-etat_ancre1:OK
-espace_dispo_ancre1:Non
----
\ No newline at end of file
+PHO6 rue Mcbain
+nom_poteau:
+adresse:
+travaux:
+diametre:0.113
+
+anomalie_1:
+probleme_1:
+
+lclc:
+code_barre:KN8ASK
+classe:
+longueur:2.11 feet
+nbe_transfo:
+type_transfo:
+equip:Coupe-circuit
+annee:1952
+annee_inspection:2021
+circonference:
+bois:
+
+hauteur_top:7.59
+hauteur_mt1:7.89
+hauteur_mt2:
+hauteur_mt3:
+hauteur_transfo:
+hauteur_bt1:5.77
+hauteur_bt2:6.20
+hauteur_bt3:
+hauteur_lampadaire:5.25
+hauteur_toron1:4.16
+hauteur_toron2:
+hauteur_toron3:
+hauteur_toron4:
+
+conducteur_mt1: 2/0 ACSR
+phase_mt1:monophasé
+dero_mt1:
+
+conducteur_mt2:
+phase_mt2:
+deri_mt2:
+
+conducteur_bt1:TX 4/0o
+visee_bt1:Non
+deri_bt1:
+
+conducteur_bt2:
+visee_bt2:
+deri_bt2:
+
+proprio_toron1:Bell
+type_toron1:6M
+nbe_de_cable_toron1:3
+diametre_toron1:22mm
+deg_sol_toron1:3.98
+croisement_toron1:Non
+ancre_toron1:
+
+note:x orange
+date:
+
+PHO6 rue Mcbain
+nom_poteau:
+adresse:
+travaux:
+diametre:0.113
+
+anomalie_1:
+probleme_1:
+
+lclc:
+code_barre:KN8ASK
+classe:
+longueur:2.11 feet
+nbe_transfo:
+type_transfo:
+equip:Coupe-circuit
+annee:1952
+annee_inspection:2021
+circonference:
+bois:
+
+hauteur_top:7.59
+hauteur_mt1:7.89
+hauteur_mt2:
+hauteur_mt3:
+hauteur_transfo:
+hauteur_bt1:5.77
+hauteur_bt2:6.20
+hauteur_bt3:
+hauteur_lampadaire:5.25
+hauteur_toron1:4.16
+hauteur_toron2:
+hauteur_toron3:
+hauteur_toron4:
+
+conducteur_mt1: 2/0 ACSR
+phase_mt1:monophasé
+dero_mt1:
+
+conducteur_mt2:
+phase_mt2:
+deri_mt2:
+
+conducteur_bt1:TX 4/0o
+visee_bt1:Non
+deri_bt1:
+
+conducteur_bt2:
+visee_bt2:
+deri_bt2:
+
+proprio_toron1:Bell
+type_toron1:6M
+nbe_de_cable_toron1:3
+diametre_toron1:22mm
+deg_sol_toron1:3.98
+croisement_toron1:Non
+ancre_toron1:
+
+note:x orange
+date:
diff --git a/uds.js b/uds.js
index 1b7de49..c1e8cdd 100644
--- a/uds.js
+++ b/uds.js
@@ -1,95 +1,95 @@
-
-    const statusEl = document.getElementById("status");
-    const logEl = document.getElementById("log");
-    const downloadsEl = document.getElementById("downloads");
-    const runBtn = document.getElementById("runBtn");
-
-    let pyodide = null;
-    async function initPyodide() {
-      statusEl.textContent = "Chargement de Pyodide ... (cela peut prendre 10-20s la premiĂšre fois)";
-      pyodide = await loadPyodide();
-      statusEl.textContent = "Pyodide chargé. Installation de dépendances (openpyxl)...";
-
-      await pyodide.loadPackage("micropip");
-      const micropip = pyodide.pyimport("micropip");
-      await micropip.install("openpyxl");
-      statusEl.textContent = "PrĂȘt — openpyxl installĂ©.";         //load micropip qui permet d'accĂ©der a openpyxl qui sert a Ă©crire dans les excels.
-    }
-
-    // load Pyodide script tag dynamically
-    (async () => {
-      const s = document.createElement("script");
-      s.src = "https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js";
-      s.onload = async () => { await initPyodide(); };
-      document.head.appendChild(s);
-    })();
-
-    function log(msg) {
-      logEl.textContent += msg + "\n";
-      logEl.scrollTop = logEl.scrollHeight;
-    }
-
-    function createDownloadLink(filename, bytes) {
-      // bytes is Uint8Array or ArrayBuffer-like
-      const blob = new Blob([bytes], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
-      const url = URL.createObjectURL(blob);
-      const a = document.createElement("a");
-      a.href = url;
-      a.download = filename;
-      a.textContent = `Download ${filename}`;
-      downloadsEl.appendChild(a);
-    }
-
-    runBtn.addEventListener("click", async () => {
-      downloadsEl.innerHTML = "";
-      logEl.textContent = "";
-      if (!pyodide) { alert("Pyodide n'est pas encore prĂȘt."); return; }
-
-      const templateFile = document.getElementById("template_excel").files[0];
-      const txtFile = document.getElementById("txt_input").files[0];
-      const typeDoc = document.getElementById("typedoc").value;
-      const nom_releveur = document.getElementById("nom_releveur").value || "";
-      const hauteur_bosch = document.getElementById("hauteur_bosch").value || "0";
-
-      if (!templateFile) { alert("Veuillez uploader le template Excel."); return; }
-      if (!txtFile) { alert("Veuillez uploader le fichier texte."); return; }
-
-      statusEl.textContent = "Lecture des fichiers (navigateur)...";
-      // read files on JS side
-      const [tmplBuf, txtStr] = await Promise.all([
-        templateFile.arrayBuffer(),
-        txtFile.text()
-      ]);
-
-      // pass into pyodide globals:
-      // set template bytes as a Uint8Array in globals so Python can get bytes via to_py()
-      pyodide.globals.set("template_uint8", new Uint8Array(tmplBuf));
-      pyodide.globals.set("txt_content", txtStr);
-      pyodide.globals.set("typeDoc", typeDoc);
-      pyodide.globals.set("nom_du_releveur", nom_releveur);
-      pyodide.globals.set("hauteur_bosch", hauteur_bosch);
-
-      statusEl.textContent = "Exécution du script Python (Pyodide)...";
-      log("Lancement du traitement...");
-
-      try {
-         
-        const response = await fetch('UDS - Copie.py');
-        const python_core_code = await response.text();
-        await pyodide.runPythonAsync(python_core_code);
-        statusEl.textContent = "TerminĂ© — fichiers gĂ©nĂ©rĂ©s.";
-        log("Terminé.");
-      } catch (err) {
-        console.error(err);
-        statusEl.textContent = "Erreur pendant l'exécution (voir log).";
-        log("ERREUR: " + err);
-      } finally {
-        try {
-          pyodide.globals.delete("template_uint8");
-          pyodide.globals.delete("txt_content");
-          pyodide.globals.delete("typeDoc");
-          pyodide.globals.delete("nom_du_releveur");
-          pyodide.globals.delete("hauteur_bosch");
-        } catch(e) {}
-      }
-    });
+
+    const statusEl = document.getElementById("status");
+    const logEl = document.getElementById("log");
+    const downloadsEl = document.getElementById("downloads");
+    const runBtn = document.getElementById("runBtn");
+
+    let pyodide = null;
+    async function initPyodide() {
+      statusEl.textContent = "Chargement de Pyodide ... (cela peut prendre 10-20s la premiĂšre fois)";
+      pyodide = await loadPyodide();
+      statusEl.textContent = "Pyodide chargé. Installation de dépendances (openpyxl)...";
+
+      await pyodide.loadPackage("micropip");
+      const micropip = pyodide.pyimport("micropip");
+      await micropip.install("openpyxl");
+      statusEl.textContent = "PrĂȘt — openpyxl installĂ©.";         //load micropip qui permet d'accĂ©der a openpyxl qui sert a Ă©crire dans les excels.
+    }
+
+    // load Pyodide script tag dynamically
+    (async () => {
+      const s = document.createElement("script");
+      s.src = "https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js";
+      s.onload = async () => { await initPyodide(); };
+      document.head.appendChild(s);
+    })();
+
+    function log(msg) {
+      logEl.textContent += msg + "\n";
+      logEl.scrollTop = logEl.scrollHeight;
+    }
+
+    function createDownloadLink(filename, bytes) {
+      // bytes is Uint8Array or ArrayBuffer-like
+      const blob = new Blob([bytes], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
+      const url = URL.createObjectURL(blob);
+      const a = document.createElement("a");
+      a.href = url;
+      a.download = filename;
+      a.textContent = `Download ${filename}`;
+      downloadsEl.appendChild(a);
+    }
+
+    runBtn.addEventListener("click", async () => {
+      downloadsEl.innerHTML = "";
+      logEl.textContent = "";
+      if (!pyodide) { alert("Pyodide n'est pas encore prĂȘt."); return; }
+
+      const templateFile = document.getElementById("template_excel").files[0];
+      const txtFile = document.getElementById("txt_input").files[0];
+      const typeDoc = document.getElementById("typedoc").value;
+      const nom_releveur = document.getElementById("nom_releveur").value || "";
+      const hauteur_bosch = document.getElementById("hauteur_bosch").value || "0";
+
+      if (!templateFile) { alert("Veuillez uploader le template Excel."); return; }
+      if (!txtFile) { alert("Veuillez uploader le fichier texte."); return; }
+
+      statusEl.textContent = "Lecture des fichiers (navigateur)...";
+      // read files on JS side
+      const [tmplBuf, txtStr] = await Promise.all([
+        templateFile.arrayBuffer(),
+        txtFile.text()
+      ]);
+
+      // pass into pyodide globals:
+      // set template bytes as a Uint8Array in globals so Python can get bytes via to_py()
+      pyodide.globals.set("template_uint8", new Uint8Array(tmplBuf));
+      pyodide.globals.set("txt_content", txtStr);
+      pyodide.globals.set("typeDoc", typeDoc);
+      pyodide.globals.set("nom_du_releveur", nom_releveur);
+      pyodide.globals.set("hauteur_bosch", hauteur_bosch);
+
+      statusEl.textContent = "Exécution du script Python (Pyodide)...";
+      log("Lancement du traitement...");
+
+      try {
+         
+        const response = await fetch('UDS - Copie.py');
+        const python_core_code = await response.text();
+        await pyodide.runPythonAsync(python_core_code);
+        statusEl.textContent = "TerminĂ© — fichiers gĂ©nĂ©rĂ©s.";
+        log("Terminé.");
+      } catch (err) {
+        console.error(err);
+        statusEl.textContent = "Erreur pendant l'exécution (voir log).";
+        log("ERREUR: " + err);
+      } finally {
+        try {
+          pyodide.globals.delete("template_uint8");
+          pyodide.globals.delete("txt_content");
+          pyodide.globals.delete("typeDoc");
+          pyodide.globals.delete("nom_du_releveur");
+          pyodide.globals.delete("hauteur_bosch");
+        } catch(e) {}
+      }
+    });
diff --git a/visualisation b/visualisation
index 8044a0c..9c86770 100644
--- a/visualisation
+++ b/visualisation
@@ -1,48 +1,48 @@
-Premiere étape est de pouvoir lire les lignes du fichier PDF et d epouvor copier ces lignes la dans des cellules spécifique, je me demande si je peux faire
-en sorte de rendre le programme plus flexible en étant capable de lire les cellule spécifiques avec des espace overts et pouvoir changer l'un a l'autre
-comme ca je peux analyser le ficher avec les cellules ouverts et ensuite passer Ă  l'autre cellule ouvert. aussi pour le pdf je pense qu'au lieu de faire ligne 1 Ă  ligne 2 pour le lire
-il faudrait que la lecture se fasse par le nom dans le fichier pdf par example ligne 1 sera écrit nom du poteau: PBD351 rue roy il faudrait que la lecture trigger ''au nom du poteau'' est qu ça correspond
-Ă  la cellule spĂ©cifique qui sera lut est Ă©crit donc ''nom du poteau'' correspondera toujours Ă  la mĂȘme cellule peu importe. le crĂ©ation et l'Ă©crite du fichier excel devrait ĂȘtre indĂ©pendant du fichier pdf qui appelera l
-fichier excel.
-
-Dans le fichier PDF il y aura deux forme de modÚle RSA et UDS,deux fonction different qui sera appelé en lisant la premiere ligne qui sera le titre:RSA ou UDS. je ne sais pas si le programme se rémémore les ligne
-mais sinon ils seront mit dans un tableau avant de tomber dans la fonction. dans la fonction le but se sera de ordonner les données pour l'écriture en order dans la cellule qui va créer l'excel. Le nom de l'excel
-sera donnée par la valeur du nom du poteau. Les duex fonctions seront RSA ou excel en entrant avec le tableau. Je dois aussi spécifier le nombre de fichier pdf que je dois analyser ou le nombre de page, je ne sais
-si il peut lire le nombre de page spécifiquement ou il y a moyen de créer un fichier par page avec le pdf.je dois rentrer le nombre de pdf à lire.
-
-Dans le PY de l'excel, je vais devoir créer un excel qui est une copie de l'excel(toujours copier l'excel qui est vide) (je ne sais pas si je peux copier l'excel pour l'uds sans chier les macros), ensuite le gros truc est que je ne sais pas
-si je peux repĂ©rer les cellules qui sont vides et ensuite dĂ©tecter ca et pouvoir Ă©crire et ensuite passer Ă  la prochaine cellule vide si je peux faire ca donc ça devrait ĂȘtre facile. Je dois rentrer avec le nombre de fichier que je vuex faire.
-
------------------------------------------
-
-
-✅ Objectif global
-Lire un ou plusieurs fichiers PDF, en extraire les données selon un format RSA ou UDS, détecter des mots-clés (comme "Nom du poteau"),
-organiser les données dans un tableau structuré, et remplir un fichier Excel modÚle dans les bonnes cellules. Tu veux :
-
-Lire un PDF page par page (ou fichier par fichier).
-
-Identifier automatiquement si c’est un modùle RSA ou UDS.
-
-Extraire des champs (ex : "Nom du poteau", "Adresse", etc.) avec leurs valeurs.
-
-Copier les valeurs extraites dans un modÚle Excel existant, en remplissant les cellules vides spécifiques.
-
-Générer un nouveau fichier Excel par entrée, avec le nom basé sur la valeur du champ "Nom du poteau".
-
-đŸ§© Étapes proposĂ©es
-Étape 1 : Lecture du PDF
-Utiliser PyMuPDF (alias fitz) ou pdfplumber pour lire le contenu texte ligne par ligne.
-
-Détecter le type de modÚle ("RSA" ou "UDS") sur la premiÚre ligne.
-
-Récupérer les lignes avec des mots-clés connus : par ex. "Nom du poteau: PBD351 rue Roy".
-
- Flexibilité et extensions possibles
-✅ Tu peux dĂ©tecter les cellules vides avec if ws[cellule].value is None:
-
-✅ Tu peux adapter les correspondances avec un dictionnaire par type de modùle (RSA, UDS)
-
-✅ Le code est indĂ©pendant du contenu PDF – il extrait et transforme en dictionnaire gĂ©nĂ©rique
-
-✅ Tu peux entrer le nombre de fichiers à traiter, ou le nombre de pages à lire
+Premiere étape est de pouvoir lire les lignes du fichier PDF et d epouvor copier ces lignes la dans des cellules spécifique, je me demande si je peux faire
+en sorte de rendre le programme plus flexible en étant capable de lire les cellule spécifiques avec des espace overts et pouvoir changer l'un a l'autre
+comme ca je peux analyser le ficher avec les cellules ouverts et ensuite passer Ă  l'autre cellule ouvert. aussi pour le pdf je pense qu'au lieu de faire ligne 1 Ă  ligne 2 pour le lire
+il faudrait que la lecture se fasse par le nom dans le fichier pdf par example ligne 1 sera écrit nom du poteau: PBD351 rue roy il faudrait que la lecture trigger ''au nom du poteau'' est qu ça correspond
+Ă  la cellule spĂ©cifique qui sera lut est Ă©crit donc ''nom du poteau'' correspondera toujours Ă  la mĂȘme cellule peu importe. le crĂ©ation et l'Ă©crite du fichier excel devrait ĂȘtre indĂ©pendant du fichier pdf qui appelera l
+fichier excel.
+
+Dans le fichier PDF il y aura deux forme de modÚle RSA et UDS,deux fonction different qui sera appelé en lisant la premiere ligne qui sera le titre:RSA ou UDS. je ne sais pas si le programme se rémémore les ligne
+mais sinon ils seront mit dans un tableau avant de tomber dans la fonction. dans la fonction le but se sera de ordonner les données pour l'écriture en order dans la cellule qui va créer l'excel. Le nom de l'excel
+sera donnée par la valeur du nom du poteau. Les duex fonctions seront RSA ou excel en entrant avec le tableau. Je dois aussi spécifier le nombre de fichier pdf que je dois analyser ou le nombre de page, je ne sais
+si il peut lire le nombre de page spécifiquement ou il y a moyen de créer un fichier par page avec le pdf.je dois rentrer le nombre de pdf à lire.
+
+Dans le PY de l'excel, je vais devoir créer un excel qui est une copie de l'excel(toujours copier l'excel qui est vide) (je ne sais pas si je peux copier l'excel pour l'uds sans chier les macros), ensuite le gros truc est que je ne sais pas
+si je peux repĂ©rer les cellules qui sont vides et ensuite dĂ©tecter ca et pouvoir Ă©crire et ensuite passer Ă  la prochaine cellule vide si je peux faire ca donc ça devrait ĂȘtre facile. Je dois rentrer avec le nombre de fichier que je vuex faire.
+
+-----------------------------------------
+
+
+✅ Objectif global
+Lire un ou plusieurs fichiers PDF, en extraire les données selon un format RSA ou UDS, détecter des mots-clés (comme "Nom du poteau"),
+organiser les données dans un tableau structuré, et remplir un fichier Excel modÚle dans les bonnes cellules. Tu veux :
+
+Lire un PDF page par page (ou fichier par fichier).
+
+Identifier automatiquement si c’est un modùle RSA ou UDS.
+
+Extraire des champs (ex : "Nom du poteau", "Adresse", etc.) avec leurs valeurs.
+
+Copier les valeurs extraites dans un modÚle Excel existant, en remplissant les cellules vides spécifiques.
+
+Générer un nouveau fichier Excel par entrée, avec le nom basé sur la valeur du champ "Nom du poteau".
+
+đŸ§© Étapes proposĂ©es
+Étape 1 : Lecture du PDF
+Utiliser PyMuPDF (alias fitz) ou pdfplumber pour lire le contenu texte ligne par ligne.
+
+Détecter le type de modÚle ("RSA" ou "UDS") sur la premiÚre ligne.
+
+Récupérer les lignes avec des mots-clés connus : par ex. "Nom du poteau: PBD351 rue Roy".
+
+ Flexibilité et extensions possibles
+✅ Tu peux dĂ©tecter les cellules vides avec if ws[cellule].value is None:
+
+✅ Tu peux adapter les correspondances avec un dictionnaire par type de modùle (RSA, UDS)
+
+✅ Le code est indĂ©pendant du contenu PDF – il extrait et transforme en dictionnaire gĂ©nĂ©rique
+
+✅ Tu peux entrer le nombre de fichiers à traiter, ou le nombre de pages à lire