From 5ed15ce01754b83a67a8ec37ef43642e3b37d8c5 Mon Sep 17 00:00:00 2001 From: root <13910913995@163.com> Date: Sun, 11 Jan 2026 21:50:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=BA=86main=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=BA=E5=BA=8F=E3=80=81?= =?UTF-8?q?pdf=E9=BB=91=E7=99=BDbug=E3=80=81=E6=A1=8C=E9=9D=A2=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E5=9B=BE=E6=A0=87bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/devices/camera_manager.py | 21 +++++++++- backend/main.py | 35 +++++++++++++---- frontend/src/renderer/main/main.js | 36 ++++++++++++++++-- .../src/renderer/src/report_212121965.pdf | Bin 0 -> 862920 bytes frontend/src/renderer/src/services/api.js | 2 +- .../src/renderer/src/views/PhotoAlbum.vue | 6 +-- 6 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 frontend/src/renderer/src/report_212121965.pdf diff --git a/backend/devices/camera_manager.py b/backend/devices/camera_manager.py index 220ba2c7..a3279274 100644 --- a/backend/devices/camera_manager.py +++ b/backend/devices/camera_manager.py @@ -154,6 +154,19 @@ class CameraManager(BaseDevice): return True + def set_connected(self, is_connected: bool): + """ + 设置连接状态并触发回调 + + Args: + is_connected: 连接状态 + """ + # 更新心跳时间,防止刚连接就被判定超时 + if is_connected: + self.update_heartbeat() + + super().set_connected(is_connected) + def initialize(self) -> bool: """ 初始化相机设备 @@ -222,6 +235,8 @@ class CameraManager(BaseDevice): # 使用set_connected方法来正确启动连接监控线程 self.set_connected(True) self._last_connected_state = True + # 更新心跳时间,防止连接监控线程刚启动就判定为超时 + self.update_heartbeat() self._device_info.update({ 'device_index': self.device_index, 'resolution': f"{self.width}x{self.height}", @@ -493,6 +508,8 @@ class CameraManager(BaseDevice): try: self.is_streaming = True + # 更新心跳时间,确保流开始时不会被误判超时 + self.update_heartbeat() self.streaming_thread = threading.Thread( target=self._streaming_worker, name=f"Camera-{self.device_index}-Stream", @@ -919,7 +936,7 @@ class CameraManager(BaseDevice): """ try: if not self.is_connected: - self.logger.info("相机未连接,检查连接状态") + # self.logger.info("相机未连接,检查连接状态") return False # 尝试读取一帧 @@ -928,7 +945,7 @@ class CameraManager(BaseDevice): self.logger.error("相机连接已断开,读取失败") return False - self.logger.info("相机硬件连接正常") + # self.logger.info("相机硬件连接正常") return True except Exception as e: diff --git a/backend/main.py b/backend/main.py index bc578acc..c9683f64 100644 --- a/backend/main.py +++ b/backend/main.py @@ -86,7 +86,8 @@ class AppServer: self.config_manager = None self.device_coordinator = None self.device_managers = { - 'camera': None, + 'camera1': None, + 'camera2': None, 'femtobolt': None, 'imu': None, 'pressure': None, @@ -167,7 +168,7 @@ class AppServer: self.config.read(config_path, encoding='utf-8') camera1_index = self.config.get('CAMERA1', 'device_index', fallback=None) camera2_index = self.config.get('CAMERA2', 'device_index', fallback=None) - print(f"相机1设备号: {camera1_index}, 相机2设备号: {camera2_index}") + def init_app(self): """初始化应用组件""" @@ -225,10 +226,7 @@ class AppServer: # 初始化设备协调器(统一管理所有设备) self.logger.info('正在初始化设备协调器...') - self.device_coordinator = DeviceCoordinator(self.socketio) - # 设置状态变化回调 - self.device_coordinator.set_status_change_callback(self._on_device_status_change) - # 设备初始化现在延迟到用户登录成功后进行,加快启动速度 + self.device_coordinator = DeviceCoordinator(self.socketio) # 初始化录制管理器 self.logger.info('正在初始化录制管理器...') @@ -1876,7 +1874,23 @@ class AppServer: emit('status', {'message': '设备命名空间连接成功'}, namespace='/devices') # 连接时发送当前所有设备的状态 - self.broadcast_all_device_status() + try: + if self.device_coordinator and getattr(self.device_coordinator, 'is_initialized', False): + self.broadcast_all_device_status() + else: + def _delayed_broadcast(): + start_ts = time.time() + while self.device_coordinator and not getattr(self.device_coordinator, 'is_initialized', False): + if time.time() - start_ts > 15: + return + time.sleep(0.2) + try: + self.broadcast_all_device_status() + except Exception: + pass + threading.Thread(target=_delayed_broadcast, daemon=True).start() + except Exception: + pass @self.socketio.on('disconnect', namespace='/devices') def handle_devices_disconnect(): @@ -1941,7 +1955,7 @@ class AppServer: """重启指定类型的设备 Args: - device_type (str): 设备类型 (camera, imu, pressure, femtobolt) + device_type (str): 设备类型 (camera1, camera2, femtobolt, imu, pressure, remote) """ if not self.device_coordinator: self.logger.error('设备协调器未初始化,无法重启设备') @@ -1994,6 +2008,11 @@ class AppServer: return try: + if self.device_coordinator and not getattr(self.device_coordinator, 'is_initialized', False): + self._initialize_devices() + if self.device_coordinator: + self.device_managers = self.device_coordinator.get_device_managers() + self.logger.info('开始设备数据推送...') self.is_pushing_data = True diff --git a/frontend/src/renderer/main/main.js b/frontend/src/renderer/main/main.js index dcfd2645..98f68ba7 100644 --- a/frontend/src/renderer/main/main.js +++ b/frontend/src/renderer/main/main.js @@ -15,6 +15,19 @@ ipcMain.handle('generate-report-pdf', async (event, payload) => { const win = BrowserWindow.fromWebContents(event.sender); if (!win) throw new Error('窗口未找到'); + let prevWinBg = null; + try { + if (typeof win.getBackgroundColor === 'function') { + prevWinBg = win.getBackgroundColor(); + } + if (typeof win.setBackgroundColor === 'function') { + win.setBackgroundColor('#FFFFFFFF'); + } + if (win.webContents && typeof win.webContents.setBackgroundColor === 'function') { + win.webContents.setBackgroundColor('#FFFFFFFF'); + } + } catch (e) {} + // 1. 准备打印环境:克隆节点到独立的打印容器,确保流式布局 await win.webContents.executeJavaScript(` (function(){ @@ -61,17 +74,23 @@ ipcMain.handle('generate-report-pdf', async (event, payload) => { style.id = 'print-style-override'; style.innerHTML = \` @media print { + html, body { + background: #ffffff !important; + margin: 0 !important; + padding: 0 !important; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + } body > *:not(#electron-print-container) { display: none !important; } #electron-print-container { display: block !important; + background: #ffffff !important; } } \`; document.head.appendChild(style); - - document.body.classList.add('print-mode'); return true; })() @@ -86,7 +105,7 @@ ipcMain.handle('generate-report-pdf', async (event, payload) => { displayHeaderFooter: true, // 启用页眉页脚 headerTemplate: '
', // 空页眉 footerTemplate: ` -V1v=YNFZt?5HboX8X-C(29cnh-zk_lx(btolu6MrXGz4wG%L5On~a=UNL0lb z0_|DGVi8udoC$HZt?C-lbp_i;3-BIWy0r6qj^x3}BN`x5%%hVpk0eY8anbRdb5# zdja%GgWv|`-+4mx32+5mRU!oD6PQCZ6f86pRG=C#)5s`o{Xo`mD#7shdBz9S( z%)&}W(N$ezr^f!-OS{VUXBey^qAW4p)#EptARH866oe>*AbHSFh>Ge58kbiX#U$}K zKMfwoY&-xl9Ei~DKg3rok1Y;3jd%NOUelmHtL4z*cX)QN&vtA)ZEK`w2KF9u?eMTY zv2p3D6ioMnyvl1=@nQ`W7dbr;WzGm$7}Pn3EW=d7W$eAvrCjT^XZJig4bHS`IW@DW zu#+6@g;>N>JOod-XL>VnOZkxcDLD3;-C8O!NEtq h0T$VZYP3!ci3P2w;n;xA0#4eC^P(0+A*Gd1n77BwBcUDmQ$p ef+nG@Fq?&te>^qjz)UD4%+ly+~o3b4Dt1v+O1xm?l z!<8}M{y9=z*?2!$p$xrAQ65Qoen#`-upC)B-4C(St0PA2CZ9#^-ACpFo5UokNzjma zN;E^rSIFWI-n)g^FUhfvLyQ-tzH@r&DivlX31WRarr7x47V4AV*>AC^I|?S#u93w# zjMXKjELMX-jg$Nww{k~P^`7oFlT7~93^qq;4ZSBgmG; |`( zeU_byn@8b}ry_=cA~g}59;I{ C4)WhHodjY391VM#Wjgnh%=jzDMTQ1MNCr7G z8o3S$L$b-0k3qz`EQ;rV;{4trZ%r#Lwnm5|{4CwoB0|6|)~0orbM}rnj9TP@h=!Nl zz)Oc>8x(W|iw!;@cOyfP!mp1Mx1&BO1XY4Q>Ag6)ord3h8r+TvBsq^ES$QC8u2ef` z-eLsh6c ;srw7ZGH=skl8&Hm*4f*8WcV*nwpLl+czlv`UivLOs5&P~v za9${XrFjEVk);lMXnmzaf6ek;m~<&j{V9b{jRWu zy&pVSz6VfdpDk=p*^@Jv2>pd2na)A37P*A4_J(&|E(hZVq$v+is`1G`uF#CV0o7Kp z*$?t30vvq0q}h-5zGgnRoCppD>)X@tTUS8uV+PI1k$l 4|y%;lbBh zrS~1M7FhnBn(DNWfVaV*Xzvs1bE}D97{-%58bj*}&->p4b%aQAHl`;WMj?uP9_^lr z=U&|-kxS%%^8uZK**B1~JiI7&%9xnewLTDBaKFDf$p0&G@Sihab2|ej^w+ErI#bZQ z#PqoW+c%)-1;lc^KCZq2!P9CYf#GP~4(D8LY2;sXayz|YRS6eA@d6O57HWP?*z5E8 zHRMnr@;v8P;->hYnf~m|U45DH7v fw-dw=`B!B2=T-@pFD|502xX-^I4VcM%;JOlQjrZS?01H6( z>2D;3d( z#sFzb-#xGzlvrm#@Tbj6StEwD$(KIF-ZjAs1QvPVMcu_kCHb4%E^BFzfbISmcw>Y- z`m^x~P?7^1+_R?mKzoUaQ7S5{QMWr<1)K@&ugU|F19zl_RhbjLzy@hkh6DGzk&!=_ zfBd)sq~DwEC}0oW1>TuKRUql*AIm=$Y2hI0--BZKTc9vtDWQTv2nqmi|D!=^F;yl` zSQ<&w77Ea5>@2GXW7FKB(T| Ef^{PThPT^Mc(O<8bmugoi+&0S z@dwDyN|a DiWPjeJEC5hB-<<(`E!u9jC=xbzJxKs(4}5rp~mA`7P6qn*By< z+^Ohlp&*ay#E`0~O5`045Z~8dhR %wl}^IfG37#{@3@7zZiX z-8|W}zY&bcMsIgl4`FWQe4!t>0nMJlFP6%Ocb>Gn{m`(X>h((&^rF@{E7F~$=uvm> z6Xsh>vLBt`=cn?R=i~D+lUX@% >qS@+U<&FQ*Wx22mf6Vv UW#oF8zRl?s=Rn^>*%gCB+#O1qbt=(V~i)3GHr+6 zH73QWyJ%;$>$6FPtw)>FG6h2cLEd_7>pP9FN}S=FPkwqXt}CQU*WG~L^O-} G}E6DI$tktB7 zu-C317AOVy5&2LIHeiv_WXG}!F+Lf)=eZPGeyZJP147;8ne7eQPfFqkAl}+gh1D2XS_jxhAR#$^6wROiHdc2d= z0}NXhwt=j-%6Op#N|%bK;%Z!v(?nj?;DaN|PIcwgE}z!$8;qrUS&MbS+ F9HsX}!^J8O(Yf&HvrUH!a n3#Wl?N}d)+s+mfIP|zVwIcpT9=hDU*ELRJ87@ zjO5^oQ;|GNf$LHE%;YZCy`sW{=YlvbaT3l99#YHW2d4#bE7WdO=JmG8`{x-uLS@Ui ze0ecPFCN%|ecz>Wy*9HKDXD%w`q`pfjvuZ21V_+fCR*ggcbq5WxgH%}dBSTRXj|%_ z4s`w0#oW~tM_AWWBe=XEgN;dNy$B@5e3zS5v1C2Wuy8GTT8(cNBmq+AfwCQ{#!1;j zugCjQDg$v= I_^!R%P8QqFDM)uqvuCs?J{gj(2rAui|T1uHr7 zI*>8=+-aQNdSw08qa-B4l~{!eyKZLYHC-6UQhp@@by8$SSYw$k<4iqGH-fUjGq~HJ z>CFBlus;cRi9%r@RI_u?o+qff1A{LI3R!{G!Sr<{-X^$B;LR<*bx6>Crd+dRf25p( z>`%)E7<8T3I_5%@o)L|MS6O@q$?_O)ROJdSjFl|yrz}MdmukV#GS*qs7Ad^)DL)n& zwe}~kJ@$0wHRhDV?n@R(ooQD}VbkJCGZE0x;>Op^M?Sx(d~NY7%*C;RGpEa~k5i-j z3(=VkmJIj ~M%$)ZdEy{|Y-n`N&!^EKtmzy9j3poZ%3VViop;oLst{3_cdl43&>& z+p!xGToT4!Ka6`ob3fI1P1lsY)Dt^SA*3H|J3)vNw|{>6-SIr;>gj6~oqo09)H1N) zyDpiyDU+GlHQ}iuLENQ)B8OH{l=fHDsjcQl=jmDSlNG#ZjVURTm3GWAI{kRU9t$gy zv1m=cq{u@ZHIafxW~2DBkE@q$!cD2>ax5vQ+@KaxzHpS91mwjNacwD%Y$v{lHf^&) zL3l!su-tn4z4MBa$f&Jw7as1S3h4C|V=H(!vd}@69-tL3qce&GlME?};%3s42~3!v z7!}?l1AVn|loxx4ytnI-*8E8GQe3?sJUX%AqOs_wYTEAC^nz2MbQ4P0sT6aWhMykJ z#@0e51d@7}B8Q(8<8*{yI%B{kEOcsjteDk6rYvm8pF>YN`IYCqKs1AG4RqJSf}O(0 zkF7LqN_NRMeV%^BrP5B9Bk3|vvtCC9R--Ouw>ZI&k1;B|*|~uk(K5#RuAe{@?My<7 zB3i$G)$uG4ZyGwSz52dtrNvl6OW1zO Zd&YhF3;-m4LTz1bA`JxG60e;FQB#CjulLdv*yC3lym!|oa(DABP zn{rbfMDawOtGMYj`<_B4C5-5}K6VX {Ai}zZHh**veP8PQ^FFnV6+e#nz zcKOWOA}3E`rQ9$HcKY*L$*#?#61`xYH(^?c@V>`3opA8#F}j0f$ss*2J*q;@LtP1r z7t{u6M3MnMQ~_!zRTH?#Y!59DJTP9jOGQ~kVFrAVFxRnA)60tIkcg$ZceoiYqC02W zxCAGxnpK5db)n^dcJ!I(#5h(vdY0IKtk-4HWcuv+#Rb{ofal6xwWqekV|+8YI{ayz z-Z{8AMGgA9Obm~C7}lmsp?=~d3NaVd53a@* Njk>O*Zj*<&xB?_p}hedmCcU)2<; zC%;91$8;jOs_6!#C;Y4O>goIkjgQ970~s+-BPxHL9Rap=*x$Cb(g?iz!Io$pjcDR) zt;*-g;SqX{PxcCBy@VWE(q{r7o+A}}$Ck|DJbYNAlJj>(oOFv?583ez-|fym7J2P& zgu`aS5YUNTMwy1p%zw~*u;5c`&Gj^*{u2EhttvfFj;f5^4PQ&*u6kEVREb%KU8`g? zYq7xFh7!YgZajA-;&ys=%r06Y%m;d581EGBE{2E1Do=@M4v8kgm-DCsl Sw+6ix%MCLZO?TkpKr6MX3*01{_Rg1*+=FyOGhZ?=YjTFsGz4)4+Zgs&zUx!>` z-|fvVaS9ptRDH>P*(6asZEH1^YK&X_{GKC$<>}?UhhHBxWF+KNbtvNE?edDQai2kB zwWj-mvrPnRisN!`K$cGo;xv}7CTKICQP6^^B}%58%~&$Tx*^$qYX>T{IRii623rj> z>qFU3qYlZHP6cE_(CGpKWsOmvP6qZ$sUTNH+&xFw9|A8&qwhKp%2|3BJ~*>}cE n|OoX+^G$4v6h
vpm zdxK#u(i_9?tG0Tr0%aQ8q@5v|3tD-I2BlwCLz%YJ$@Jvvlhz1M=4iF&3?`V3S$j68 zKNZh1;lGCRf?gBp0sH4qT3<)d)>Y^-DLhmMsZQ@6K2neh%t&tP-k_)4(;B+dF9OeU zVHisi2LVqHR(2{zmBhu5%`&p~e7FU&T;*)7p1DwUI2$coc~MVW-Q*LxDMl5pnTI;X zGdz_k2vNaqAz*@M?t0}4+Cypw2=!srY{RAKKrU1D?4 z%$>NY9NG*h1=Hb7?jcGA$SiN?R%+&z!(2bC=KmxcK$=Uzi9y1?x97zujd|W*59MeH z)*sXke`Q*NyPO_f)5=U#<}wDg>yX$IUllm&dMP=&J-+QbY{N_n9jt ;}NnYGmp zX)-Q51A}DeIz9ZnLdqkL=kKiN%roJ%^X%C#EECZiP;A1pLS8Ypi>3Ro!mo9DCB9To zr}@G(y>qTPprV!ZXys|mSD;qCsXF7c+Mg+$LjD0 5Se6op9EiuU|-F(Mf89d4(TBHM-~} z)(eq7y2imL3&eFyLKx0D@(*FPKImi^he-`#7{X~?4uUDYKGg#QoLV}y9Nmj_@GQ0( zO_e0H7`83}shx4DO2(Y#LGA{?8K#Q|-F3!?%hqpcFIyz>)w5Vz#nx6U)R|s2IxIBK zQ99`G;W4rK77^Q2#GdyaaN2ZyIm4up-ZffcS2#gEH!rL@Bp;I|SGSlQRBo7PTG*ix z6_w_g6GyIpl6Am(>{SrU-6710IY)q_rkZe=Nr&F#KOaVXO)!N2nhBc5xa?EoqNpol zM`Z?1d4Hdm!Hul}9T)ekvI73{=P%A;u{Cxx>cYj9*8MUA&v5QRgL5bNp;8$fqsj+! zy7auFR)#-`)2QDV+5RP!u5F(Domg?C<@4{&v2MH>WCRhd;uFVT71179*)4|)aEHrw zw!ZtMQ6>!C887BvvW0btvOx%TX~}lXU)1l{G6fF=rK^?QM`uQLp=+ig2T;Wmk81aX zcU#?c;n$H&ZlT4;B9vDakA(^Ok7hj}zAge6THA6CZ9lvqG96^Iqft~`+Hz}j!C4lxc79yN3sy{^+gR|l zsO+C21oyn&&l-*R=K758yl>_gsq3Z&Ty=#U$qY)H+T@>OQ7uQb^rZp*nfQ6afkM1d zES6IO&Cdy{;{`EkYf(EPVG5~y>9bE0h6ab22B-Olve#^`%l;JUq;{Q^3iXPiEOW7T zy;_q6>nw#n@y$Q7^?FJ%Sx6t^ZRVSOk2n`7YlGxVZgvz40A8p(SkDdU%ew|(k< iib@D=hc=3wbzyT}HEr$!B@xuKWXd-%_Bm&hnC9zF1*PGPiqM?ed{T zKqju*Lj!@kw2O9fcJr~kSUBhuOZE2IPjpsir(U|nuV15v*r|^Xas{auZwu5IQ?r_s z71uxA11~z(wg?$7r{|YthJBB@0THF+o73S07bIA(D<|#e_g>5KncArihE_-_8s};2 zI~>>ZEAkTVny+z}(UzHKkvx??>h9f)_cv-|zLT9F3wr)oE5zb;*ZWjMBA#An7=^bW z#fgnsxq8j=zDM4DOP1U_&T6Gaj$r=M(s+Kf_Rv_xFpG9i3EhGDPY}x`e+^LHmE8(T z-T92#?3S)>ts7YyQ5#*3AXb4^UZZjI%2%qmYcWgn8Rxmy{(`K6ygWC8U7IB~CJD*W z@lKchX`GfN-(Lc?>s@>_Ue0B#M$v)>wQ~2yJ qR;@@6`aYPYqG^4p zx_`X#=Ev7d&j)+ETB2U`L&s^nm)uqG3yn*u%();eqZG?=lB>CQ;4e9(_pf660*-9i zHfiMo7IzfA+gm4HZOnJ6l=ohadJJ=%o5QE#dPnf$)epVl6xsxe#1d-W5RloPiOP_L z<>#gPDz)r9kGeexGVtem>9Rn{PB7n#qias+NWo08NyCEuyeNFp)wZq1GAuvy5Wju) zu{Vk4tn*k=ein=!Pgc7P=E_H~J8?wyJ+QEz()&@sW7g#nbuMqY@vl$Q`IoMP6pH00 zdVH1^h#XUgUK>TUvsQ~}o3Ju#Kk%o~Op0-sPQ3KW^7G^$A0DgyY}l6K=HmVB{logE z%i-6eBh1xxJhIzXKF@yzUR+Nr*K{C@v`*opt@M^9x7gZD60N$fUTy@MRSC0d6BGje zHV1o!+L;)84}rqYeKyu@&7 >?jK{C$R1&D>oh&$+`)n8<-xtZ4(8==)KT z@n+4Z>LVrLb~v3eJbTJfAKM6_>F~CA0p}>e$GIX&)q(nUKPfGv%{-4i&YF9l^vH=! zkH_RXzZqEc5lkXr`hSaZdXO^X-s8158={@jqDlNBP*_b zK317c^k _G*v<^6e|-#jnXmgHgMaKz@PmOxi<%mFr8y6?i9yvxZ@z99YS&k|hoOW9P 7ZZN~Rn2 zCz5`y8QE0xTW=|Bv?d7?*$ta;LTF^8p51`-r-vDP^AbcR>McKJcSc}%(`L4)!$@-< zOeK8Yh#{sV6Hevut%6M@u1`bkCLE~XwW3v(XwPEvH1*9kAId#^`D6VPH2 $DlQc+ zUM31u>e?57xbGrG)(@%R2BVieYV#@XKS-SB`j!$n{9yaz8(7CEJdH-WF3986XVvtw zoq|PNv8F^0OXcdf#hz1mvC`6b_S(d&Z=dPS n-$ST=J>RkwdvtyNYZ_)9S^NB#8wCJ}wd6!T4*7sK zbEN}p*sMhPs{!#J2R!{FOEWKqgb!Ka7B8yNcIigJzY$Im2AchbvL*zKNq{oU54?3R zs?aVf_W;0x1GI;LHIPAs04%Jb0N_-JHcbd%=*7t=z3ubIzs`|={CE)yK)wK$ii7|; zZn2T_7bhx6gj$shf7&!i8{h>34IuzR)kt#!G(GvG{pphe|Hy5Z8qzO7w1?pU){OTx z5JU?HFqGJ21`LuDy;bI9YosYcLQrB-3j$ODpfW-RWIO np=2B~VZufQ8*6D8EOga0|EqXqyUHfg}!0078%em_rd? zDh)^3-E^BQHmf)7qIp|G_SCM~`XEUO2Sp-lU)y>Ya@m@&>_6c9gf3%oM3pbaM%ee+ z8C`OtL=DnRtqG%2i?(|D;o+S`?=PiK1gmM@G>dJKWn zuoVq3ZXEY6z8wz^d3GcxR{OA8M|wSSsY z=T7Bb`ChZQSZKMEi-|{kq99DM^)73p>QTvnGSI+5Y6r+{TLz_vS`{hnASsSEu{nJm%X+h5w z3vwms2RpMC4db(~WDV#_v4Y}w?s| 4H_g bK#}-ENYoXnq2jcRQDYG$7Q0%J?#sl`=A8yeCWU#cG)a< 8158#?(;(G |!I1U+aS-tHLk7l(@^;~-%kp-?seW9BQZdtnp~%49=(y8*!6qRi z;U*=o=lO*(^MTQP`!b?YII%n T%C<9MSAMFmg~Bg z6C??C !wKWpxV~oBWef z>gAIGWHV{CGRD$6$Brce-zI#8b`RL1s9gh@zIRN^vfDq^lLLB~F~Ol`gt2&-z8v_@ zBdbl8UpJOUxkSm0!FVa*Cf$*uvA-PbaF|rfpWyAJT5#iady|-xCSs?{Grf8!y4X>jpWA!4`X^^?M1~Y; z%W|VgG D8e7JNl$2o582(C$bN(e91 zxOQ)zV0R0R*=lNoFE-Ui4`$%0D2OzT^J?GX#E)i_4<}j3DSa9L@VSOu@#kQ9l})J` zD!DN!s~Leao}oFmXYlDZ)uIX*5sG5QTi>^;ZujFX&j=Tbt#C(SN7=}G9hlRy@KwRx zdrPq)L2zjez46Nl)ozm^Mrthk8EwkVQuiFHHI+1GVGLVpmB{fd0{6`2B?1Z3c`f6+ zNu}A+7&RBMZ)>KLu9)1U6@ul*1`NgvLn&T8qd=C+Et4iE@=*2^ch?&XVa)BZL^rhi z@c3)(dGro3+%LYDF!`)L?kBZTPw*?^T|=#!dsvUNnROJZ=gEhE$$bA_^pL_3V`oh0 zV?dm&*_KLZ{*NirRL(_nipix&H7{bQZ}pQ0c_8)Dnd0Cyh4$%wb~9lc&C)c&5^Q_9 zdj-}d*w$YF4{sV3yoTmd7<#rW<)dcFmpNl%sp7g!k)t|jSu%y^Xr&xvL*~!YTC=PE zsBE81dcJFIVS-{{|4rl@qeoQSW8W7WRIZ7J2v)B$bhgulB^IjcUh_P&D||uaIFxe4 z<9KIRE1$@4zgj6C?PD^NY}VD9``4=7lTPMF5yQn6r9mqAddeW%E _T3_XO|9JD}BU87ehqfH<4G6=V $#FtQ P{*gb34lk^YyW`6nPM5fSBAc^g0l1Vb4}ZUS*%uYPNoKx83+ zN1FVOM3ilg-b}o$47v@q`DfJPQRdx{>_`-9`T4!;n1XHC6~&vL$scHB?|8t8z0@&G z46=;BI4(M>W`@Hiei{~E(U?tjq9nhPV6XQsJda$$pgL!rDA$C=`u$>VSo0$>pOtv7 zlES83rQ~T7ZU`Rk+_tpT>lL(Lw5Dwu16VVxy+B_-L|Wn2p=IqgtbUDu$eRl@hN>o1 zFLw6Mr6$3I$qdg_6xir&Rg^~81P7}sMIT|Ol%5!FmNiOLYx1HW=+9j`hq3W3ielH; z5Z9G6RoltPYR2nk7EJ7u V7i3#_|*Ewy$LW_HoJ&L;J(A7K?$R{$9708vQHr z!wSxo7pw0)29@(C4O{%!xtHTVe-ZYx_$DzKkGc5smCVaFUgS}n`0T2cARSS;6846n zDY-boo~~Fw&V0{YMg6nU)6?x1KsEd*Pj35Tt;~q*j>Do&iFrLthnDO7 J&UnMxAj=uxljN6D)K9oL-iYIH>5Xi&e2VX9u^B!PIY zig@_xVQ=$~( @nS}_{u{}KvQX;z{)VpPiN%HHC#>gsczIHRv`lBVMMuFd zM5&Tk2~0a&sq;+qNe?XsiaQ Wi=G6*f?4?3&wYCO)U;Rw+yty3 %$?!JCA;xV4WPYuz6OLLWtI9`w01z48iH z;_CgrkR@eC=;$U;Gf{5 j@lR%<9&&}kZiq3rK2vhxnn^b0i`jC9ah!DGS@aN z>bv(B_U`--lLZlzrhtqvq#6)Gf5s1or9*-EJM2$JctCU?!e;wds2PLGZ }!rKNaq6}+DFGl@kY5^f=Cweaw2ub2V3<^NhA`&8~4Y2fpkT;|mAn+H#69^-u z@?SV&2L^yI0*{ uNAM~F4N3q&;@oh3RXXx zattQ4!TsP1p_{SjO&vp}N&bFo0Gc$|x*bfU?Sc>Gt2p^GuEJ+7gGhE?N*+Pq?ymZJ zrfT%~)mC@&u&V``U+TIDfTL1WJj&OtB}We>uDQBI=3Z-g!gJIF=8Z|8npX> _TOMC8LIH~l>ZWh|rk2B8VBf3bl z8Yvz;WO^ceUT~Co>63; L T1V6z{K2O+|>lxECrTkFa zeP!PCJ3;FAdweFoyw@t5=Zl}`YjA>coObWhrDappw=IiTendJ%O7%kv?{m`$s=f4e zanCl46YCmVAtqXStLDbz5x*yHvi-_zd71rl%@BKV@qkW7jb kOXlbdd5oD{Dr-8!hnAYU%qlAn&D2UOiG4$=b3J_$fK)aOlGr-Brq$Atg0hY&6y% z-DmEm4PM;EihEVn3)mITlte6S7!t$t$F}SJ;`1Pj?GT|z4*fd4q&KxvE}FX3_pT+D z&Z`VyvMFxCdu4dkY|KJtB#o{xv~oU13Ij$I@F*{9!INx#!1n+=W JXc-Hk8 ^RjezH1g>V-kI&eTT4}!Kc&g_> er;|um4dqK` zUBzWI+P1`3y{e593A tpklZ-)Cni}X)~ zyX3xa0@&dmDgF&8doeNzD2n}~=(nNr-L~PS^1G*zZe>XTt%m@u##>sN|5nmYAJ44d ze({4N3_-Q?*T0kbPpUhBKj-tXem873_t%P4q_(Bi(uc -AaM>fl55RU?OAB z t3gFfsv^$q9@9R|dXy2?*hgw6l6*nds@KBU44KZo Ay&3m|X& z6F`3S;ZFp)0v_jPS+hDxKT0wa6A~e@88RxC65xbnQn=L#|1H=(wyY`q8UO+TZ{iK8 z_;+dt!jlN3cf^4JAEWl~9FO0liuya=KI;E9*X6$$6-RPZVx7Wm{t7td)b&=AbnsyL z{q_6?bg$LR&e+kjq09JR4v=*2qny*8tHhB<{@-Z~@9TVzo`Q-i-+-`2^vk0ysOoCG zldi%eNUP1b>KhC)CESbTHhR>E87Zn(x|d4F@8G5})}k~E4IWfRtCO-iCzq)E;=iX4 zb{YB6J#t-c_vQvv(5kE-L8Ff)uX#eSc8=eGm#f!ir=!ldL0W9(>qTZfZTEng3H@vL zvhQB6hhW3J?{KR>3!gq%;-b}5%I!l+v5msp?MFe1+w|#WgH$ucLes>Cr^6xUs{KYj zxJ#}%xjv+Mg$;87NaMn+cX8{vsrk`b6W3x;bSL`CBA5}u@Meao4;958$m`bLfO6;S zcu3J3Ocyg0a8Y)`)D7}WVEDuazAL*rqhZgko}78l2n;_59EKi5bl+eSQqOX`Zb0!E zb&pH9sW>AlMB;v$Yb=pk>V@JNF>8-S*-N21tFW;+D+|(HB%qT^^n=h!jt~3*XHs&V zo;1UIwut(}lJ6$h%xAyEBACW#u|>F9S-!h^3iyRnIrmA}E-JD)Wz|JHwK;!{@EW0b z!=tZV@l KaYYlyV!rW%$=!Seq+; nx(}#x{DP6r&L2AP^BBrW!YA_t7hCM8kkltrBR46I+R%F&P zM0^-#JVFC^^KY|7+S9~7F3vNbYuB28PP;NVl& Hr_|6nV5NW zdf-$&C8)i5F&0l`4Lj-wdsB7|PED|?SNpt2bCbu0LdJ$^pvQ|d$|2SbI~vG%bWMj? zQQr>}b#Zw-)xjO1Aty$b_PwGD)ZX6u2aAB4U+<`_&8}EI`0&ej6 oxnvXWuv zHtbNs1$S=AO(GJ>$b!}G+00R#zK}!fJqASwyCczI3k9f4F+u{_1vOv8#%-f zzc*CQ_QHJ?WXuaarEd=b9cp_BgOt&ULJeER{?$Do_kkzre?xA>@7%ADT5=!*2T+*( zl#r(I&jovaZnJLy2CMwyZK4UsLv~?$71hdZLPDft{4;b9IPLL1;g{S0?KeO{4eo)J zK$ZtrsBs?wswx0SAarXGBF{r{!5v5v0r?>WD3H$h4>Sbufs%khDhg3(jL4`Uc0l9; zutgN4PdaqvApn1X5GVzZi1sIW1i=_GDj;o)2td(*x}k)$0OUvk7{&HE!wI6IGyu2& zxkUdCwrD6IqXI?|kco1;j @iorpNXh` zocN#IJE7K$(>nlQv`D`#YuNnc285dX{2J-E4p05*w{3wkY!vk$6TtCrot7hHJ%Yho zd&C%l=O8j=5dHu}*3v%*rErTQA?9EaFh>wz%`e0(+~P<;A4r=BBPP@!wvUhijpHxi z3CKzMW5xVmu *(hiKlS=% DS3q Xcyt62&|-S1SYMa4=im+2r>eaA8%#W-=a?8Pg>!N zHz5Rf|1}5yKE=0fZbi;N;bcJEAv!^T$ZgLSgQ|ySwC05r#{ )urFFdwEowd;dOI2a-s@?&NsD*0+V?#q{L4*Ytxbh-k+!?I1B652D*Y z?V=kJG@1jY!Gv-3S*ylZY3#jZpB+epQW#VZ+7}>8qjDy8iWXznNR6Vad>OUDrin`l zc6F#+<3A*Bu(XXk$EYnPlX9HHr)t}y;n!(SvgB#G>zd{8AVklMImN2Pa{7_=K&u;{ zm< wai$EVf?lP0!tT3G`SV~lJ4%fr!{cEf$Jdqa`U81FH-KN7< z;A7E%fD|FC6fxfzv^?`(^7<|AT1p$Dy)?YNW^b-?fw+9iiis5gcVcwLUV+)5PL+th z^tNIjxW!ldH1mnPq*mEPPGceB&&2!% aKpN{f>RwZ!t|cPZ~X+83Jft=PhgKp z$NO_=>?L^^W8n}}t~xclP8LU&%EBy%Nx#`P*SWl<{@76fw| !D>0Z!i$^Kd%AhQt zjCM6c?C;&J36ZBhfq92&N4=%k5(lU86jE{Z*`8?*ys^%D##%5D6dtgm9DgMXHCS=c zoKrWLDCV2+EqmuG>*XHNATfK#J(N#D&|ZbvBzqY}ft@)onrXcuJ!8`ZzMfI-`c}Ii zGP_DP<{69!qwTskHyZHOK`C+E@*6eHHz0q9K %xrl#USIL4y=uUw2IXCu&HJC~8?>~ 45EtCVHv&d2v< zPx)v!wFHgk+scdnPE>}$m3{zv)iOfP0nc$nrgPLM^Lu~kDb*l9AkE%LqHdJNkdOeJ zSloH5-y}v8{XTf2^h5#S&;%^{1NT~*lRwtnZOSp=+q^a8ehWlI+A#{k8+j`k<4_O~ z^R0RncN?ODiJ LJsT}QGyZ)!E1 z61kO6dINHHy8$V=49LAZ?f4 )GAA-<&JX*+O$Z>SNu2dPHtO zRl-~C;C!Y3xQHFuV**_3`TLsBH}{HjF`%LGe_nfP_y6Zw<&WI)8_*y78N`U5)r zzviEW )%kj{Rtk4RGgAuMCXhz3 p8oQZz1aN)C=~lX)1tV?JYr-ZgMC5fBX>suWDTH%>HYNJP0=a z)k6h@!smClPX|bD2`&J>qTfA)&+U$Ui$L`IhoFSdb;WNMg@I@P%kRH=yrn1%lmA_= zfJi`o*ZLPl8i3+E1kV7)=YJ>yBQp%2w*$)BKo2|++Iw0KoL$@`Nr9tbgl$CB@}%?U z@8R46CKd(17EI*rfoyY;Vy=+lIOdT`gubQ!4GRyVegjfOpmE_by}a`&5IPmr1s`x? z)VKJ{SkbSWkL@BD?rPg_{2ypjAp}Y;5@4tNQMk-OZC~%+npU~_z_BJmZE2^P`Y#ZM z71zca)LUre1x%QE($5$G|C*GTa)Fb5X!fHJCL{p6=p#bqZtb<(lUINsHsG8VB!p8A zIHv`)7mdsSCg21EiX$MlP)Y%O6akOIfrD2NM>0eLCo%vhnjmbjl|B$~tO?+eYg9yl zr2k7#q@b1DdDi}-*Xz#me%Zaz{4;Czs^X~{{n2PD>jm8aqtBgp@uctK@mpMEtq!!~ zb)gbwT~lN&c^94Hl?$L}cgpe21P7tdlqNBnjP>h5pV~bQm;ZQYsYLSKKtwwYxm>kF z)D1|CFnPMyeJCc9=KOyBi7-4># 8_y}Lb^MLW*BN{7(fI>y1Tm>x}*`129+9+RFM*9KoJxL5nX%GwVr1^&))C*?cML* z-)@eB8kpn0um5@e&hruneUoB4wtw9(#j(ZQjo ^kA?6CmWDKNy+}C%@Nvf+H 56b^H#I_z z(MeBJ)^@t%unF`S{~|6;snz( ;l?f6b@1f~6ZlO2PsPz%HwNleYqeUn $Je@wPO81? z0ssWde0=cO!apF3Qc;H*Fi2sRYAO4(mb*_U%36GUe1q)ZB;qIzLz(%Fzc6%ykmiI% zIZ?bbFIVagcE$=~NIG^^;;^hTcU2&uC2Y`i+GdMQSu<}lyLjsji5+W4d@RsZy?Xz} zWDl?`1xgB^C@)T=CuLenTpuI#e_pi)6AoB|Swh@>D`A5o7wa=`CC-0kHJB8#3l81< zROE!#iwV-s%d4d#-|qm@+;%a#%353Ame3yDlQZ`^ u&F~U7hlpveZ5OKcTwXo z>$L$yK@ 4zKK>0m)@7qF z!_oCAXrW*_pIYiS?)dlYmz%C|%y*yoenZNSKEB@qe-UZQ{f`Hc&rpv8zxG>{Biw!t zp^H|gey*(T+EER`lSdpAQ@|~(xRa9A2OluQRvK5#wX+0xU-lnr&q{ >Weqj87R21WE$JiP&aMbdK4P0TrT(%^!bQKcbXQ;IBb`)6`aQ>D|lRo z(?8+r|Gw1c%KqCYB^z>bBQ%z+X2qR!p-{&R+}C0NE}ddG?&%!N@n$)ipv2lzsORFB zj|L|kF}&sCm&v>HHr`AlygVFK7YeAKbH8dBrU^`w6+V(}EzBFEJg3vOwccUc;Ix$? zd!$A-(hWu6*KQYdzV%eU!dB_o9MVkSw3D^3*3-FanTw@)ZG`~O2*SKu-lRWF&6nMO zHQ=(ehI}$)RXH!_sDIBWusuxzVp|7pF>oSQu&Jn5ixV<>g^@#WiXme)8q+y`U_ZSc zkzPg(R0`~#qTCR#SxATMS(izbyVch@8oV48t(%C^{lvn7IX?=bfNiw7*M%VkKSAuP z=OhXcKlHblrn3iSm*Z0ea&;~)a`~PE)xIixEX=^-<;s8vJ;1`;?C6ehx??33J9szn z35q%qeg;pJpto*Ze6BSZ;EFRr&((}uE71>hS=u_GC63}zNS0L>c&F?Z#!yG2Y=zLs zIs3qulzf;W5YXX5G~_DpVQWmvoR%cAy4w3=)5dR_v2|Zw*I?|*LwDLk(h4aS_}! N*ngI(I1$s!@rc1BvN z-&w=48rodlz4ji9onHw(U9h*cfx~s< j7AIq{v-aq{P0t0~b0v9@vJs0+j>Vkna&sEXN=S5lsp0?^}8wy1lgRW2e<0vCH3y zIweiV>xN#{)pgp10n%ZlZWhdnl4ncqMCx`79S@Y#BjbA_-RH9N;d`wDX1v7bMZCU_ zl(6jO%xc=HqQuXag94>95(OSa`3j{8pryMp$DBi}8u+ovU9!MKMGpFVDmkqudmEWd zUu3*nKDKqf4qvBOG^sArt?jkGu}jY&2ItFtaRc%T>Y}G<{(GJ3KX5IY{`EodaC*={ z!;`O BTQ06^?B|1D!sQhQxt|$i&3E?hc5!ixG6gn+ENM4GkKq zLp!nml+&Rb7ctP4ez#id?bP?j a9(KTM^ j`Mf 1X?$^J>R3rDUVxQ;-d=bD>Wsm zYMehR1X@yz{3Bc%{cbS4O^`@$$I||X*Yc0n@W;wQTR*oy Uh_{qy^4{;hUY{$m9FJG5f-PiSQo?K$24gGqTKnM`}+%+mS%@Tt_)u-Lg HICtppBzH(hORo`RyQ~|NH-heAxciY}x@!Y`|%Hu#{b6+$eJ>`eX#!XG_}ybw}W I)FB@0Jq_}Q3^4oedO6*z7u)+bgbdDrwSUuwQRyR(4mqjW#P zvG6}F;^sWZRmA!5ja`N&fD#&H)w@=y943F|E0Vt&uF;LPe*9G0Q*h8`m)du2|MATv zS6iT|bv3w*QhVn`Ipf3@U#$UzZo@_;J1DeUE53*Q`6ot550hkN;(P%+V^FECB(s0Z znm~L^=UQQB>Bn1m7IF1PJ$dGn+x`k=4rLk{-PY?XX5}EfuprT-s2QjoXuK z+%8YxMgCBw?1zl4SO26&jW?^Ic&dSL{`lvFH0kg6HQQCg>h{$WxCF#WLm3(O&Ns>A z@q5OimOhgR1z(&6yThsu6T4T8U1P%;uOSFrgZ2b&)|vMGOLZ|=Cg{p1u$k!C^nTp^ zbiuL1i3g=ZkVg4?3Je$R^%+?348Oxvi5jC(5WFP$c(p~^G7pPt&i!Ksa6`08;ndwR z*$MCDP?9JSH)tWVW38;?oxV3MN~O6r$sH)4l28M_&SxlUnm&Q7bEqa?nF__yfq`@J zhqMLJx}%tzLV3=gc;B_3zNQ; h;HE$H!^((5Q zrYemfFS+&lFTkViLunhi7EkA3qg9(9`Q Ak_A8Qp7)>CR;yokVl z#1bmOEjb_3sFEgjq!MPuKp^P5N0%<_CnO}35cR1}st`S3GEDcIQi88?`Qd4hm%GK` z3u#c3j3&)+K6mgJwj2fLT4?l-lKddGyHj!o+SV!de__01_cab>wu2ApYEPK+SauJ< zX_QCJoBZ=qqBV$8SUh~~ird%2MX!EZ;hab}`m}zqRk)u~@d9hAm~}ZGIMIJe5LiSP z-^#sjkb~G44GcAPry3vsHgzL&H_`rEH!UMJxQPL`0A)Z{vGT*;MQBxs`=UKVm|qll zMeRi$ZN*1k1_>&mUvg%o?nvzSkKZ|aeVplK`QGqz>f`V4&F`aYIrtpFC$6MYEj{ml z96;>0i^jDQhhecN`eg3c#Fv^s>DPFHvgM^|MkNisJ+hih!_wqmce~!FQi@Xwd%hoa z8SU*Wf&Db1fz~~uLU0NcTjnKICoaFT_91T4tf9N6gqxy1BZ_e0jPH*-o~MxS6wrLH z{uK-{6H=}bRIVQ4i*KNg$n5vUTr@_S915`{a3t|ddgNZ1HlyR{(lJKirG-fp3yB CaQyA^? zgS(>jijO iXa{5rrpo=&~ng zJ(=>3)k{#!CWbNa-8kJ#{hsR&+e{78cza&F*VGzRWnwxe^(0wr6Q29{9pub&Fwz>Q zp>D}Z5}Q_7nx;T?JtJMda065XbFUOo=Piu%#5MDq$*b1P&YO^UAr9@jZe#o0R#ZQc zxW2XaD*342BL`AsqoPafC{I+=H1`Ic?gH%sYUi-G#vX6E*R1eB#o!`#c$_k(VxqB9 z@(}_Cog^JX7pXkN&=o?&84KM~ejG1F(8fjb!F&LhgSJ5~T$iAW 0xb@0ZT%Cf2S?g9EOk-%|i0R6u*_ziSD`i_n z;$PmC92}(;5^LYmUe*v?o)#&Z?q7J+2|pBE6Qjgt(;av3VjXvUp1JiJuRB!1IonGh z(A4 06!w1|Z*bL|^iC?0Qa{)Mqo{WChlu}|`zhuW3A*B^}` zYf9~(zS}Y%FPp+Wc41g0J3IFF-3#y|+%Ndoq9X~ittpOw8& T^FM5YCHgwL`ENR*wpZ{0 zpShPqw9fBxvLuVCE6)1kyPsHUWs6wc(V&&2&VN{S=$RWmqTh;6Xt3fP+7kTF-~)!g zQWV+m;rMTO;U9Vm8% {Nhg-04 zk0K_Tm?NcRgZ3KmqUE7NQl~|o-g^z=5?eiKHT0?s#yd}+YzQk2Y%AFdPg0Ooe>KHC zYtgJA!+0I~DLjGE0TC3vFK;8oy~%=ICcvBqT$=5F)LLTTEsx3nR;1P=!^Ck>XChhB z3qdvzm#}sRjddU9bMsqB@%yYxwGcE=VxJi<-j^KhKJX4>Wc0mgB34a-(m9c(n1s!L z6QjeaD2;1#zDQ%qT2;+)dEXPhHm43NUV)U&luDK5a~}FM0!W;gL*@3@Y-p&0iRknT z!GhdtK8@T5p^vFjK!;-EpqHBZbNebEHYIMtG#Z{zX&G@_Z@@ QYZ7FL8x} zld|`F3D$ma>GZOaT)^N9x}^TYx8%!~z0+ DEv@ck~RxMQr;NT zNTf;tBM+ I0Zq>BE*MP 72(0W>cs8Xc<3AJ*#s(5!`fguBzKC>lxi(?j3IL)Y@xA%_k!5#hJdJ z8+6_~&QSWEr?l56r0@90VsHMx_k?(Rg2(*wuan`wPl >bkr`R0v zZ?xszmm^+&`M3$W`z9!QzWAjzJ3r~hnZSkWgmv%=uBqO&daYP+N>nPo=|RntGq{H_ zQ5nesK93Y7$lm5x*Dj^s9fj|^Qp>%$-GHT+)cdVudYXC7 (3$f zE_r7iBzIl6wMiaSeS^_st>%-qv5 hZ1$ zvIOy>#sncH93`15;2r5`F8ZF|fXQ8S;&mxsVU||BFiGiH+isZbKpSDYNqf(SAe9&S zM+6}}K)t}Mlojc_j)o(6tnG+%MmXCZp|?Q|g9okI2044k%q~+9%Zy~bEhsDasMY1# zZRLLT2q`M4a BY (5T=42+PY3gT3(6AGZ(J=rj$ibnf081&3oiWYy>K~d-%>d> zhECB`kGmXkoeC=7vOf5#VFv2yn4=#FE#~Tr*Qh@CZ(ZImYf4iL&N0f+X?!t)GuQ2= zQW!(t8z|kKd6