From e23a4bc500b81b2c8842f5246af3890aa7281a55 Mon Sep 17 00:00:00 2001 From: qubiaobiao <3294694717@qq.com> Date: Thu, 22 Feb 2024 11:22:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BB=E8=A6=81=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 10 + README.md | 29 + config.json | 7 + index.html | 13 + index.js | 4 + package.json | 57 + postcss.config.js | 6 + public/favicon.ico | Bin 0 -> 73326 bytes src/main/KeyWord.js | 3 + src/main/api/NMEAHandler.js | 103 + src/main/app.ts | 208 ++ src/main/config.js | 8 + src/main/ipcRendererManager.js | 26 + src/main/load-serialport.js | 51 + src/main/preload.js | 20 + src/render/App.vue | 60 + src/render/api/util.js | 113 + src/render/assets/earth.jpg | Bin 0 -> 1312275 bytes src/render/assets/pin.png | Bin 0 -> 1409 bytes src/render/components/BaseInfoView.vue | 91 + src/render/components/EarthView.vue | 58 + src/render/components/NMEAView.vue | 20 + src/render/components/PlanisphereView.vue | 86 + src/render/components/SNRView.vue | 78 + src/render/components/SubTitleView.vue | 9 + src/render/main.css | 9 + src/render/main.ts | 15 + src/render/shims-vue.d.ts | 5 + tailwind.config.js | 11 + tsconfig.electron.json | 16 + tsconfig.json | 18 + vite.config.ts | 28 + yarn.lock | 4159 +++++++++++++++++++++ 33 files changed, 5321 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config.json create mode 100644 index.html create mode 100644 index.js create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 public/favicon.ico create mode 100644 src/main/KeyWord.js create mode 100644 src/main/api/NMEAHandler.js create mode 100644 src/main/app.ts create mode 100644 src/main/config.js create mode 100644 src/main/ipcRendererManager.js create mode 100644 src/main/load-serialport.js create mode 100644 src/main/preload.js create mode 100644 src/render/App.vue create mode 100644 src/render/api/util.js create mode 100644 src/render/assets/earth.jpg create mode 100644 src/render/assets/pin.png create mode 100644 src/render/components/BaseInfoView.vue create mode 100644 src/render/components/EarthView.vue create mode 100644 src/render/components/NMEAView.vue create mode 100644 src/render/components/PlanisphereView.vue create mode 100644 src/render/components/SNRView.vue create mode 100644 src/render/components/SubTitleView.vue create mode 100644 src/render/main.css create mode 100644 src/render/main.ts create mode 100644 src/render/shims-vue.d.ts create mode 100644 tailwind.config.js create mode 100644 tsconfig.electron.json create mode 100644 tsconfig.json create mode 100644 vite.config.ts create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8968bd5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +.vscode +.idea + +public/Cesium \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e025aed --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Vite Electron Typescript Template + +`vite 2` `vue 3` `electron 12` + +## How to use +clone the repo via git and install dependencies: +```shell +git clone --depth 1 --single-branch https://github.com/hocili/vite-electron-typescript-template.git your-project-name +cd your-project-name +yarn +``` + +## Starting Development +Start the app in the `dev` environment: +```shell +yarn dev +``` + +```shell +yarn electron:dev +``` +## Packaging for Production +To package apps for the local platform: +```shell +yarn electron:build +``` + +## TODO +1. 使用web serial api实现串口数据接收 diff --git a/config.json b/config.json new file mode 100644 index 0000000..074264a --- /dev/null +++ b/config.json @@ -0,0 +1,7 @@ +{ + "serialport": { + "path": "COM3", + "baudRate": 115200 + }, + "extend_tdt_window": false +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..a82fdaa --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + +
+ + + +Z-$fu6P@w5vupe;v!S8l{Z{>} zNPvop@k;{=Kg*}k{v55}tguLkihA;XxNzafAb0h|%#MzRXLVBimm}H9Z9Rp8ehyj` zL~fqgZ8(1V5n;l00VZ}V+}|$=4HcCb)~X3#)H*i*abQG4Lp}DxM*G>36AKP1D&tW} zR9FPAE58ye8rt!R0WK=)UuG2pT#8`2A}lN{dHt6^V8mxS)@%siy7C{A1Oy0+E5ZQ& zpCy-zM*v}AG3l$npXTquPGTp3qob&}wEUH8s_NHo+;IAPgyb*4uae5&`-7_@zx;ld zF8-Z6T%BRmDl07fSIp(V^FNLy0Jtgp7k`nzbqDwK?;RUmlzzK#*}wM(w{&m)v}(%# z0r{`D!%$bx?2q=GuE{`*#2@N^ln?ZDb@fc$f7xzAYWClfB?Rc|8Xhx?|K|6n&Fsh@ zCWBiRzn$h!^Ir-_@fo;%;(v71F);ay{a+P+{-c^(zW}ve}^^dw__+LCvOnl@NKe@Fr z^tb#U{ox77sU42p%=PsDXLkTkKtaKK;^_Jh`~eLG1? 2~RL3!-{b723$X#|cgnVj72AGn^laKlUZd87Xsh8Fq@{xjDTFKY6WiT6)2j#L8w z)b+#<2DN{akOwddgJBr*h+{&z_EV1iA&+<`tRFiPP;UK{$KnWw>_8$LpsWe{i=0mM zLn5aEXo%>T7=wNdLCCse*>EDKYmpNZNBB{O<93hv@sYj^0MU`$|0xdvU^vp3e#)&{ zAbF&(ET72j!xOnLS?hg_!#X^chmdO@=}6ezk=#PS3MkiVPvp)hB;rutSw4~5+b440 z0}^srzb| q%TVCA3bn4?-jj%stnQ3;PZYMwI<$akfM`Sed-dIoY*F33rFKn3KZ zN1XJ8kDh^i^gNiY;skTY{8Iwdgv)^1NO{okR0TA~sDqX`9ng}X3qHKM4SA;} k{Dm$tMLNmlPS=0OCLSq&(!5S0R^Fft=D{Vhfl;9(m{c7O AW9@Ijf`5E%e@4xZP zvk)((27s;|0QV!|E>tc6=@4JP3_use_d)zH#7{u{|MJxT<*EOXr_%pzKzRCSk}~~; z^c+vyp9g%DB+)+Bu%_k&sQA`}}8vSb$gw|u9ql47HTA?n@`=^=b-^{8< zL7|M`g%cO?f3pLnYsYn$1i8+g nLOTBIr5kadF_vJr4Y_6;CG76M*mHBd*s z2lmKr5QQ8BdB{ol{{FQe3b^4?q(%ktaHd9HfOsK@mxA~!5U&UE_7EQg@d*&05Am%K zKXMXK!rP7t;{ %En zvXT%Ik(?r>{?!f@2_fNebaPV02nFRIF$FB2rTe)jdSV8Eg_ef?k1~|_fbBGV 2yZ_Pa2wsfAP!=~HN-{lB+jNplhwKos1PnS;7Fmdh*H0r-n)w#{rID9LE8@U za7zmH)67{c)hvr8qj_sR(MlpVK!9C5S@S@KpRspx-`jcziA%)TPIzj3!+MBp4z9xe zlw%fZcBq|F#tD*Jl_pZpzLoVXbGIYeqEP3@XMl*Mb134J?ZBro0}&JpAQiJ# kYrg_E07V=T$v_URqSKN@?5c)8KB0 zsurR1GCg7_hqZTV;0FpmYUiv+jOTKm%zR0g%=*q Oj0G&i gHW8p%Rg6;gg_wazz#Ic)V zs!VV~c`B{<2Pw}xNyd?4ALK}|^&Yy>?qZ}F#gS4@FFT(Wouz;mibE{J!y? cTjyscl*Y8^o>jczY&ONAqpL7kAvai;C#{m`Rd6yT9_^V9toZ&qC0d)m zDAR$f PKQ7Wt4EV-rYUCjd+%-cAPH;fr=VwX=W>^gio9S^oe?v|-7 zo2B2eDGqRJAv6gy-)9KAdLs=TCn~<*AP*ndWZIefkOGFlu$9D@$*1E?QhVpv)0Wpa zWZWz^?Z|moKMAc?3}=fe4%Olyh}J9>%v$hCS3S#~gk*-E7V|);sj>&V^f+mH)WfmG zf+u8WFxQqL)O)A5YP~LnS?cn6N!@=<>VeB^yY0{DH4e5TXoMXNu&Mk41j*vL9?$1@ zU)_nqmiaPSWKae4XeICWhi4xSlxEcvFsJ|zeCI)=L%Gek8(P`tddB?n>Pveva;sev zs+cP+)g;_E-1offT;afaJldh&Re4L$&hR1KdulE7d?UzX%Lu+}RH)_A0(&L|dq$ji z`xzE88O3Pw;;3D7Xh&d`T|D-|MEcpjzPr4GH^&0;*}$dxYPvvV*3GR=C;p<^x-Sc* zNRwc7x!#-pte(9MNFv*T`Y}-vlx37Y5u^_FuDUtFcP&hsUH1X{XL~rZ=riqIyobnG z3fy A0Lm~Qnvsz&EnW #{!^P7%N!jg6Vv_rNv2`CfLiFn+F>%;{q5r2zqX+6@lfEH`gL1NYB@1p; zxO8MLj~Q8dTyQGkGcGa+pK-(6b*$C{*D)Qms6zzSiaC*(fl_bEh>b4kKQD3BeXEjM zvM^@H9S>YXo{BzNH!gE-I87@U?!0#B lDoB3I zou!c5fM5N*6)}n1z{?hC@c#aj)n_%G@_E5msXph9qSxYmy!h7Iz3a-`434wy1I3z8 ziRoW-=Y)K3jh?D^A1)4P@Pv bLo;iv-j9}W zV+z9xJGbCa{zrd0CH|M`o6TDlhu&<_L55c}5pOm6cPZVDx>buKb$WH!$#Fo|av)pd z@ya(Hq#~0Pi8&E9FEUf*;a9j8m>l`!6-ARQRlPMxy!$#a<(_MF3^y@LBUiX)CyRLz z;W;=qbVWg=h>M7@4P*z#0zdWH+4HvZD=us@WO>D;rca8Uwni4 ph%3X+F2GTVKxZ{G6wX1-viNNhu;wls!b+mL!kW|-)~f|#(?7n#p3 zw+=E d-LcAzYXO5*o1MKT)~F$sF#SK*eA)J x3 zCwcF}bgRpzvM5(1;3~ lNP_fZl|wL<*v!fQValRRxC&-k`sr?Hs|#o^5Bs=?7+ zJmG5FGjM972&KLy4Wd(T%fImD-WgO6n@@?JGag!6Mm~O|V;;G@Du^;VqvWk(13D)- zg7n69Hzr6G1vVM(li{xvb9x6Q4C0X($L68t@?H*JxOSJbx6JEP(RLV_3K+b$Dq6IT zic?c C MlYiFiz7SYzjsc=L15o{i_#nEQwy z?K(hD@x|;ZzGCQvoQ36iQQMR?teW^}vi22GdN|m$I<8q4X5JBw-1wg4?p~q#>5?|n zL#kKkeTP#rxf#?Sm8Ufx*zcc)JwT6}oL0MjFv$O4dXEru%)Og}-dD{>eBGncUz UP$U3qGWTgHd;aRhxhiH}*zMRx8Uv&Bo#V?VI?Ignbs(7^VM zR|J>Grl@9d;z6lT^aa^oH1hDobMMQIHf2ft;hRG&tFbR5n|VDbJ!`VRyj;kitA)Gj zxl~ls6OuRM9KE9{`iu+0xHqcQwR^XGQtrS<@aoMep8W~Sh1qNTg0Hh3_seuW9jO?G zNV!3x*RWD7#;k=7(Hqu@o+;mAssxExrced`!gL%UfRMU;%XgC>gXvz4^AL{Bj5-kv zVV+fb7 u+3B>upYMR-!_pzkRo(*nX0tcQ=XPw>`+n7&K&YW1@r36>&AML z`+m;CW-(750|UxlL9(oyIFaXBIP&jv$!ImRU )YUF4r zx4gf%D`2C@xpl<_d|cLHe8A_DlokPFD*~k|JTuAYd(|BR-LeuA%grb h03ckzvyoahLk8^f*`HbXt!M&HoPg0!W zEs&iu> y$p2&vF_&9oR@qgJ&`YpLw(S*WT5pVS>;sDrY` zO{;jiE8o<6CaQ Z@^9)p_(<|C2U@-U; zeT3o@%d-m$j9KgV4f-x$a&L{Te#Ad*a5=LA&Hw(rO=iSHeD75M`O>1p3>A?6eTSM_ YAk&-`!GCjmWtQ+n00*ma1SxWuO27hIZ)!D^YbT@oR5$7UtnTq$~H@nZDT^0O5 zz>D+%v3F!VyeqZE=O#Am#Z~*;op(;Nz7YvLxBG}`4HMP>``2$_d!)52ywY!X_9Kfj zOAUOhG1$P3(JXw=d3C=vErJ_+R+8wxeFM8DHS1czBM(FkpU){(#KwDiyq($dd9>EP zho7PXuqTT6aRGh&lw8H5r;4d|SA8#`vw;YoAyhF|gOcS(!?EM<%!(Q4rL2^(bMr$V zZ?)$8@9k_$n7i!Ig!ol&@|o6D0X|HkPpevJjQPgCT%;Ju=Qmw@iNkB^acWI3SKq?D z);-|G>0HlM#GyFqaA?7_8_-4?W3xy;+I6ruRVlA*S9m7itZkTL(h%F{Cj~h)4+E?- z8+R+|NO&XkPOX!OptzC|`~LV*uJm^O`vY1z%S!#TawK|=Oo#H6tOfU_@j65${ju$C zR`-S%8ye#Nc;$tiioG;g8ib~%gTXbsLdLzF;t0c^36yvs?yH)^GcK#Ju&FP0ps6g@ zDTA*K!=I-K-(NZ(3dEl~uukgsn)G}>BUakHcWKLtsp3qqq9^miYY*ZESZ8Rr2d|D_ zy-@mU&P7}H&>|`M)!7mAiUUs8ZAu9D^-ZW}T;A&z(AmeieP6lq(y%v~cCB@CDUwIP zuFl#vuD%YZwkDtH^r^jt{*L^tFIMH4TOmshhg3|(`7yX&-<77#&q;1NiY!(&iSU^- zcIvVuXIux;ujE2|F~&wbS{F{OUy29&c=Mk}lvv!79^Jl`v1ia*J3w(37!@kkeO8qa z88iR-jzICF;xOX&iYB@}?meShL-6~jBWfK&-D3IP @p?9V $Mmb#onr=Veq==8 m2cryEov{k zfGc @>^ za^TZmqC}jDFc+P26@eoh_WizfqY0@~QoKKB#;V&U<}T^`tV7)4k3{_+y2W`5J~gjj z_hNf1Vm(cPqF^*VP4oa4k+Fzs|CXsf$;_qF`l@LFDWZm#)8Js7<8)QKVbgm_a-W-p z(aUEQ56?=Bh8*nU7d&2KuR7$rKd9{UXm~4TCj&*!4wtf6?<3L9Y(e?O-pC2>G4xUH z`3uJWBjgsvBZYh^nV%owp}bleRjgdQqt&F9<+DdLXZ-w|hn{q+fK&{ZPiIe3JW>_V zc&NNz;zRX+lU4;g;txB*v-G%p5=X*O>T2C`i{~>U;{2*;ZBp7a?dVekgI?&*3~LPP z_~#QaTYWLG$Je*JObyYn-<2k{kr}?H6f3PwDu)p|vY!4S?@Ig~=kgF;73R?>wz1J{ z)s~0B3}QQ^{MW}{+t`*-O|*lzJKq%x7e1q-_s=RLR6l|2iqo4WSCKE-R^0BVUuBo}6FlwOPogxq1_G zd8X|u$24cm+5m0P8p~G4DS!Avv352aA5=+r6E$4?mbVTEtS0RtKg$o*^J7l$ok2&^ z=&;F<+|%N)wNIP;@FH4n>rScX=sxvT4#oB}2oajFHKaF!nexd7J=d~o>n7|7jtYpx zQuMUt=vr*eQx8FIQf~$?K4Z3W6lRT|UL5j#WN(HTip;~m=y;Ynm*gVS(~f3YuZjgf zbe{@AW}}oF4mq3rs+niZ!Nut%8r)sU`K5W~hZITEFC)i0swSp*jEW~)empXJ)V3p? z;&g}wF7TYbvMa$#sI4|`tw)0g15zq)1+lq@PxtFv8Ht8&Ow(+|I6qlAn?27cIotmF zoM~$>*R ;}-u1rEoTcn*snIq2JJl6pl<9X=k-xv7MlJ~)_mwK^}@g6x{XVBC4Z zdx&WEQd6!Eu0aw65I1AzNf E%WEU~09>2*k`Q8;p>iqP+H^x&Mb+3rL z`p(xuRj?CDuoG9Q`=>kR-sf23uSSqMqT;L@a+C8ecB8wMS7f(*|2Q?^*5pW)aRGx- zD1!c@4ugpc&iMY!#{P0@FMQ{{e5;OE8@PUdTubqLzaGV%*^##i^6a@zQDe3Q?Kj>j zUqQ8LHEy$+x2K4I-mE5nm2uoEGVfp!BxT&v{o Uy+$+sHumQ|eVW;euuvv<| zKf |Kn z3Tz#e8GrDSZFpDo!4>Q_O%}-Q@>VkcvX-s$JR%)S$#b!xeYfOPif#Bp_AVdJm+Coh z$uO Y3td_<~fB=ri|da9E_Hp7c>Lhyy%1VX8lp__f%l7o3&EJ*!6b6W*| zl--tK;yVA>JTLO1s%Fn=ZvHK^chpAAot=XNPMZe6{T($rqUEK{6aXcRX|;i)QDOnf zw$)*;> =>J-S96{qA|QTAnp8@HnoN(OO^uq$iv6J`=#?v%|HCUFY{$Q_h@kH)>*di? zcrk3Xjsm(Ut_%4l+Ao@`+deXGZ4DIU9a=YT_ops?*io{1zi8U#oyE~`JIAl^j ^$RDW9^1iNF=;+DRO;f!S=H;a@5C8%M3*;j+g8~9Di^>M TxLX6GKHrh7>m1 z`KZX4g+X1 |IE+-y*9Q7`(au$#tf( z0@vr+gYupTX5wZ2A-7~qX@emb%?CIQ G}H44rd#EMX|zDMXS}4Wi0a>TfK^( zArfRF-Rri$EF;GygcAAv8IJ|wNNN|3lmnk!4pG;;Dw|htL)DTNXB5RN$}-0 zJTxW2i)##YElZA=D;Y*Z|wXCp(sen7Lwbn10%XmFa zp5c~FdD=ZCpCo8`;OJO_?VD>_z!Y16?&BO)GS`Gk60hKsL?_Kk4W68q!`ZP%U5X~^ zA=8z@ExFLLqDqqhK3?lp{>1Z`p((VkV8odqt*b9FY{ey7^U?jH{WwNbwXdo8E+{0? zC{n44uvfKyL_EQxF7_5}bl{Es+j%?jX9}! )XDGXthPVR>aV-@6FO^|Bc|ad&ecV+pVX*^z|4`iP%R6p?G_L zF~Ki18=hR5&^xQvuR#)wFL|oeV@;{C*WAD}9-irlec2=&($WRgSk0sk`h2O?x$u-B z2(*=b!q?%!MwBP4SBx|%vYG)rah$x-MD)t{*BKe#y{hK=ns=U^wdRnS%sdsxqQA?Z z;{s8jkfVSUdRFX*&x|utFJwZMn)}!}a1r?ZR@qpAs|F)-E6+P6K6cWR#(gxhS#g$_ z JYQyZU|RvXEvz9+d2Zz@@_RejT*N}1xK=~@dcoEeZ!DG=1u!j!?qG5<)xTQ9{s ze&*Xj-Ke^?nA-N;kmRaF9PR2KX(e+v6YpxGF1Hy_C8vC W+s{J H}S-8c<70|!*0XYuoVg>Ks` z;iU >0+V!3`lSh3-Mul0x`Y`S|Rg3z!MIyfh|&m#B9A z!Yq-D&t!cGzRs79uiP6SCD1%hC4Hu4f72gmY+tkLl(p#7Q%#$S)-6m-F4ms5%;$Oi zL()<$mDNyE-5_S(#fIbt4yU5|=b2(lI<&4LpRNYSGAz$^ansa)e+$3ejq>tfv;`18 zKfI(o9E(Q$;h^pkVhLz3D@RjSKb1yx!HZK1sP6ludi84aKw{=H+MQGkx12OIgX~3x zd-&E#O(bKMLkEjum6ZC#VYuzfS84cU__k6sY)4Xdu_6CO7=$}KtLF2`H`4Rtp-9(j zQ*d=gw05LaK40*Vev2k0TGkgczWgnfBOpBy@AeN-lW2wBs0-(pnxf|}f{FrB)8bZQ zwx&C(Tg9>1#5h*_Tv>*i3)_NU2a3NaLPCokzWUucdh#O?c1pO5Ub2)F>IHVZX?ZKg zq;bVFw?mq>%5&b0QulC1M`^9zB2IZtbY1sbTo26vGld?h1=|kx1pn^3cj>TkrCXzI z-%K6p{&cF{G|o*@7#d@EO6Nbu;uq#^uT;0uS;F$a_b8{-huD4uM?UL1iM&!2_x%kM z2R_SHevZ?^c&C!u`69WlZ`~2t6=|GRV?Hza)W*{Zg)ii0=i4ERNv(9j;odH7NJW^W zo~wvF?EUy=UicDvaKW?bEfaj-4{Ip1HHNkKib%I>sTkh8x%I3P4`u4Sur7<`fs}&v zeCTtlPt a?3S;oBHw2 z8T+miKH~0egT7X}!E-(H5`CwhWjsl%e8tph5vFKGSb6E)*IsJ&hr|oFN;K~iJ|Dhl z7Spl#dYPQ23e>I&)(Pz~jL7CE;Tm`sf2F*OLUO?A%l3{;DAs87$IZlqR$-57xv`J$ zXC7K`a;sy!u1e}UHEOv)yB+H%h;?IUGNr*?oP2%dS>|wYQ!k_jwJ)b8*!zVNo$tJ6 z?35PYEnr92u2t42Lz;vr7mHoI*py=GDRiM^bz|Bu_sSYiewxQA1I;MdqS?z~lU_zf zyTBPLq@mQn;*w*l8iR5Q1-Lp^nT_q_#wIhz%&;LEynOi)_5t~1iP9JbXW3#a^&MxA zoN6~-is3fzXJuZFA{7&a_K_ahaYhnS!LzvD>$OoCE|<91i#e;WrH}(Bm3+;{j{c7# zjxFMRJq(xe*-6R*b7t~zH{x{0INTS-4u2$?MpZss(X?-Jy!JYoW86;Y1*^CVn!g9z zaLU3X#DaSX;If~o`OJ ~Si6*n xm?F=<5vE4Q+5=UR@y*Z>(}fOK=E7(vkCe=&l97+@;aoQ>=tlb2y)+02OHjVw zBE6K L|1nZPTM+VE6Ft(hm3^^1otpcm7;l{doqxR;MzFa 1WV>gSFRb2i($-ZXYHvPs@vzgR9`KTD<@w)7dPCI(J-do$!Hd9ce^HP zbxX_OX!I|qoI>mcxxFB?x%IyCE&RJ DH;$|;)q0-@WL|P(d zQ#~af^Q{svTAfu<*4m1izH7)ZyZedyeuy(;VV~Tf$NeEcdGwJ{$+ho1P5VTSRo0<7 zT^8uIuM8 L6(W?2b|)*FJMZvr}X zw(fMg;J%eg;0T^u++&=7Y%F7y;kf#qlBN06+GRB@&(u0RM2f{7u@A8u{Pk2Ui&|7q z@7k$P%gd=v+gc7RbX-%J!k9LilO1|*bS);sov}S*>eT2mrW6xL^Ijn}NvYSCneD*% zc>xO)#4=@6mc`zcX8UPLV4{YOEy$kJbj!zN`B{JA{`^DV2d(eUetbH>pB7&kLsG?> ztA1xR-FB2p_Ws=ix7vayBjeA|89I|N5EtCdle!;RvenO!TfH&FCo*aj7DVO?6&!38 zti*ro^{afgM( }hCdN7N~*&J*UN8Mxg1spFfBd8 z0FJ1JnK=O_s$33Edjx` T~LMolz=~H;+N}G2HHV*~0x6xadhQ1$__AiEhnnIZHKjwJb+25WX9tbCY{m{ATjU6Qg^xBHnkIJWFn)3g`q3XEP`g zz (|v1&9V|5{u6bf+ zigWyE(l6bmH_-U@WT3PgL}GL9OG_B7BOT@ <{1ryBzdrmy2PKs z-6>TFQs5Jd!4q_k2v4@1@|KF3V=m+JMnl2C9_D*sKI(tS?W<6IHMg#+(`wGvG5*`5 z&RHe|12Ti>{%G-w_|~^bhxB^4nFy^kJ$YNH1f{8k2ll0uNsn)02NFHd-C4=F4ww1N zt-1lsQd+&0Of+i6DQ5(hE#)mw3ct>~J+se}4Fx!(%XF4`ohF;9ESwxB4g#^mr7H~v zr+uEh;k5X8)tBH3pt_UUcQe A zM%piMcjV@oFghmf O`|8qU95bzlUqu#WwMGYxhRtM#9A1Ob9$D z4E6l)h)mm#f=dzg7h66N3_4jT8zjtrzb8P2g5Y^-eqOwk#< $Vu#?8qzMWQ zPsN88*%6n+6|{=Tk}JLZljX&O*J>zHM(b$ZkkfwNk#9J9iD-=3eRGj^_$XA1vo)sk z&Eb2BKGH$mAD(k6AY?F^`Z~%E10}XE*&Q56$M*U0Au-R9>bQAc{G{o%eIxAV!&xzc zaWiw5ebIW{sS0`|tI7Kytc?9C$ppzvJBbvbBBz5_(t|`fsPy|pw=2GgJOuG}2b7FV zvM i+nT35{V)^V0wc5&cc8?JU5PLi%%zScB#hwPR|Aa U?ij(>dPJb1U0jJ1=sb=n{k?@ZAd?3RweD0uL_C7d3PU?+J!Y8SFqFn-* zb!V>lt*w5eJ97^I)F<6iI @R<(kuBQv}nt7 z_8`<&;3YP(jH1?ll8yI`UPpqpw}J&mt%ol^v@i6rv+eiMOo;4tqsYmK`SMMsY21}2 z=EEY2_#z#5$VWo{)mH5jc6^v3|SYs1fu47RFQmh|c)b6{PWmdQMC>3@1y;n!3FQJ0) z(_(?FXU}Rx99ZpQ%2aub=uekr+Oi0}O+7ccCy@Q@^cYEDTPs0uq*3sPGcM{(Ua@0q z`TlvluT^kzI;kHgAv01NUp{_ZUo=BU^x6 V`?cD~H*FhBSUHA?YlRv`y9rDEMY9 zy>wC+Izjpj;WDXF;Hg7-aq(@T5u=wz=X`eW C3-FAhc8nk|Qq$|FvggHu-h9U|k1@Hy?DuaPyMske zw|lBq5U)JTt0QZf&V8pwTyr4Wh%snn9Z$J@|1w2z2&V@7ix;$O*@A=}quqq+dVMVA zU%pMhjieSmpY)Y$wO9f hCWqg=B${WW$ftxvL@Z_f zD8NGIlT&nTe9pXP 0*LU3^VIxq|gE*`^D*NtG8mvvz4A{9(vuX zTI*k!MwIw@>Z>f#wCU*&J?PaobfdcxEGyU6^X)0~y}N_)UpFr83&LORy2i~fXUdZw z;1aZ>=vEX2gasa=hku~P>?fgl)*4XhKISl%{>( S%Gpc8{|f%Q;PP&?<{$-2Ew?~PNd92XiTu|jbM!h_zs(9IgRt6u5< zI;y)@v-*u&_`thdclqmA+==Ug_J@)tBO%%WJnqJY OLKN+_tXUD KsqW3)W0thWJlcTT9JUpvsJ$wDDO?Sic#Mo4|`ok^E zO=54}tS9c%7>jHh9wr~fr(4_Fh~v897o2Pg20Xm-Pxnr5o$k+f%Xp`>RvFm$2`QFN zd`s-+%lMdQZ@oIM@b33N3t~dto#gJ{l )^3`$+^Ww4YP}bd;1pLN(?p?+tIrr`KI~#M}+?N<{ z|L~lmn(X#PJ1_1FU!B*!5SVU#NV#&CkYr?CtkSf;T~^(Ct+K3Ny|?mU=<8IvFs^s2 zaQ{$o;kikZ^5L=k70IgM4wm*tA^Z@A({4K&0Vc2g0*fd(DV(vpFI|2xT9nP(ahBjw zdPyeQjZ+A7t &5{_@$@Yzy!<5H*)PFJ4yy_F%wl+#%KC5zWa^KF^ zuMXX7*Eq`$y%pOV2>d2|pA@SsIln(WnXYyA>W``*?^K&9g8N(bkMG4VNu|h!n|9S* zb;4mXr>*bzRK7eM$<=>dKkC8Nd#9%s^ZooQ#aQAn2zA#SO7vY~Buu`h4+pJ%siBIG z){F7SLDar9c^E-h`E6-v_l4|O9-+ie8=f-J^fUU5!YJOwN}j25Hyo7wNxvT`c!RuX z?-C@7A`VJO-ILl=?P9{L_y{yv+Zrb7Yly{H8i_uOhSD~ER#lEI;b2*9iGM8l;a#}4 zOAP1aMDbfaAtha;M(@a=fip6Ku%lA@j_!i-a~f6cL)uT@UnRcX3_h)8#D>Oj9;kXg zuxbpsHKcN0zTzPG9lPXMh`GBkZ4{qCyLOyIUnApF(?tDQ@kGH9Yg(^u^pF;LI?6(u z!|=krq|h)E-z9tTBIc~2R*wT|JbA403ad*G`EZ$5Ow(Jvz9vk*q5?k5!=t#N1to0E zGA}rqz7>=!!hPu5Z5l*mOZN107nJU)R+TK>+!;v4I%OWXi}TRjIpXwk^ZV_%B94|) z2NQ(Tp3lgP?<&_~DT~zEE|O0&TD(#_T` zajcfI!S}FvUYj-|noLP8#nBP8kLAhryhoIVIH?UyWzoekZK)lJLvRvK7e1IXaOo{L zM63JYIelQGl_cR^qh6fdIR5DV7WqDg>q_KIl8;f%=YznCHu}xhD5bYo@#Cz>CVGa1a-6{*% )|SOlEtxYnGsjHT?z;`gNoq$@cdWPf_I@C~OxRKCYDOR-1tJO<)n2@9R$bE}0; zFT07YIesmz_x*b1h4|RDuReM_anI^7@4dF})cX$G$c-1Cn06)I&zfMhf0EJupbaYz za(w#iUe{z(UsPPSBjmRK@()3R?fHStc9!~-^TzVp&u4dU__Vh&fBfQ$x&}9%ynGtF zg6!uVb|bpkTJ+sA8KKRdc2}@xj|z4jc6@W+{)EAO<=|kBq=Q=ytW$g~y-Mz`O=@1~ zi@1-=rcT~)WhTD_Pm{V|*T;nGs(oSHI`(&pPO=>ewW+*mzhae7f>0m-N}J->r0cy4 zKJ0c2mOI<%xcTHo{MzSF-DSoeIpGm7DIr}t<6>0BmirP15{2*ZZmY?YKa;t)wf7dc zMqJ7ppMx?7j@vymJ-@VJoB73caUYuJ$i{XE$dbsGvh#L0n>n}dX5(x+a{0wrL4B=L zyW(me+jq5XrNl2}j@Y$ruj7ZXD?!#Fi{CC7|6Xsr!OS^lS&p+^ZES0`e`@oVyt&=J z`Tm-eww3ZVra|)fNpq(v7T{Q0O)m ++*dKs8;`%UV7cCVefQT zZI;Op(#+UQRd!@OvSw|*Px_`lY&vJ@wbWA~HPQ3pUiGydFf}!u=kToiMAkp5_KMn{ zdTl;q9*^C5?9All =Ho?%m-m67X!W)eXD5fV9$WtM zMVPB>1AmwUNziU>EjKCpkm>B+u`930?^pQzfURIXwt1Ynmx1QC%uoL;ANRRV=iT{w zbEWpN@!Z9Eh94WUm+g5IzVnK-iB6?lLS0q1U&I^p2N+T9XEGnD1kuR+BQJ7@dgR!o zRbx)SebbngSrw7B@NE)7+0AM`kEN9R`_(Tp-eq%_Ied h(g^K6F0pLwVCCdnno@ORnZG(nBTw08rmi4=yoYWQK|NBc2k#dird-y zGE2iOn6x7ohnnruN?+gn;{ECwIgv!G){KO-Q1xz?Pv ejSm}V!l_+Dmme0j`hpJGwwT|yk3*d?006T zSs|~v?+w?hvtz=IPS(C-)kv)D&9D5px@QsJ^Q8|mbV s|)_#Qv@m}=ecY4oWJtfC=hHs!;4&F~}J;u^Q zx>cE9+-Y+nK=`5Xo1ml5-|B5Ee6{My4!bRwZl42~51PvldpuR>S @KU# zB0Hq{i6QsKmRH7_O~QGrEAM$4bLxgY|I-!8+Be4Z&VRCTo}Ia2dxpW)3Xh!$>pr=Z z>~bwK2$xg8vUGEK)UC|~i_7n;1I=eH&fM4#oOx)EFn|7*ys}Ep7u25K-qk(X7cAmj zKeGwQoI88pqg7S!`Lu5QhqMFJs~y`O)@w~|Vb?j=(s4lk^^`?HHFv_ZFSaeeV6;~D z&56XY$OM12Emj}mSG|~N9FfB8K99>SrIVTE;#Pwm_oEAwiOVn6PN=m$XytZkN@IiV z$CIX4uM5@H?^MjWU?t?YX10*2+R*@Ok 9#t%yB9qJADf=!_A~CBF3#8D$~3!(Y@AShgCn8J{6+lxS_8{t*VZ3PY|b=$ zyLEnjb$3GI>E&&vQ5T*+57_bH$OP&NRjg4U;o!Ow70Erd9Cr(}Z(M3yVZqiMD$lbZ zMStmqBkV?JdS5e_cu$G6-gsflEq?=vt5?e2J?LAh9oXR7X#e=->@&A^*kwAmjlCM^ zcL#f7yI|8st{X?EyGq1)rM}jTd1S)ok&@fA;_!LHi;pM7oISB}e?ZqZzurzCOaEs} zChcpRD`&rp*S5UzagjpQm7P{s^Jd4rx@3FfoVB2MMX52@xge4GRW^}(_vK@cHLRd4 zvfB1(o!Lts4(FT=woFT77Oy*SN_6e}xt&L@&q+(-k`<4-DJhoF^28!Vkhp0Hq32_r zk5R)Vq3}vUJ3^_j1?`YPoNV zSrp%N&`Uet?+i!$JFPAH9}LnQ+>)oaZg@ee-ljmvzAU@y H5s>m{baUC2zsNa@gX5;=h?`9a+5_HUUI> zu-zP-Ow*H3#$Gas@4FPcctuKk zF12m^{np(&?|5&6s86if{j}CoLVLHwk{03p0oPN^40=0HiwVwfJ9A$g!!eit=I)k; zOQ}Y8buQtG@2gNV1z)!3;p3XOeOT4gWOQEsp(zWetS^DDqA%LjttoJ_p_9sNX_F}z zrr_ Ke$1ZY z6a28}cv6Q&{F9Hyz8otR#wC|8=DAsX)1s$5BO{5|a3^ojE&J7b?#{e;ZCU4|#Sco` zcKM~8IJaqRyv=rA@zUbM=O^Lg!yX)!eV~_=EB(=Q|1DQRJSAl6)V_wS@J;(H;-;kG zR|HM|6m(xV)aA6&+QQSqo5u%8d*AHNF>88J#g-cxnz3~Ao_I`&tY6&mbyGh+D7F%n zdVK$7BPHFeDNaVEE+s6E)zRbArj;`$% _wGkp2c6u2r}z zp)tTFRD@g~rM8m&{`~!$UYF`{;z|=gr?Te@&e^1_HRJNVYZq;tO;+Y#-COUyJ=AFa zf^jkj=Z!znwaZe*&BCx@#T(H_+Z6NSbaS?Vr?HGZyS+%R!`sZl5TOV&Va+3z{`&6J zJrk=JH&Ht!{KY-HJL{M<<|prG3oLKjWv8;oDfH7RaU;tEfh=wwpK3WaIL1`h#QMiv zSRQXMzRka(ooxJJ?F%Z!?9vUQzJ=Ak&9Qr4_o>uheyiW+6y%nKiHHs|!Y#7$3Z1Ec zrBL=%uKJdbd}s87+&kP>#i-yUqSrsuo0!?Umby&s(#NAR?jqRuKA$+5OQDm>afa_} z=iD(|Y H+1(wz;UI^T >frN&9^J z=17Sy^nWsrJ+IaIgQCNSGq-j|G-Slxkuk(MCpl}k`eJWlo}X(PduVIsL7e*2ee=iq z1~&D5HcLM>`__yQmw=uUncd~{IvQUcmu)+;0;_?|H_d0tdv^RmT+E~#T8;+MK( zmyma2iJv=5Vhnnf1N~gBR;+DjifzBp)3YfvqH>#;Xdv&wZ5viHzmeRrNSS0)+`bO t#WDOTItXkT2&>1FAAkkpN~(ftytJ}=tKSloK}|_YdAvi z)ta9AzO#bf`TF8Q?^=&FW0P%68(2=PQBYzH?;)ieBb~d-x0cWPDb;#o5Ss*#;PSTy zPAPd&4(r+QUGI7>QMTUQqM!Y2r{(ec&wZ7hvOU$M9h*bs)~cthRXJYW(syF@DJvDS zh^%T}xy|}KYPvm-1D4dW4)0vjeInnvZYt9TFZb-=4;_Vs&ZF7d8lkI89yx4lFDMPR z2@Vo&-&by1G4IhV&VV&%6{_D6h@0M?SeMh*;gEdts&xGJxGY(h>1UM8+vfVNZJ)x? ztbSQR@-4fPN%DTt)W|pK%VvB$l%~=k(yN#<2X}CPy}ozO`kCfzhbId~Ze7vQa-uu* z>DUb)-(-w=dG<>CX-)1}_VdZ!&P^o`t|hMcB&fkzlFl{Z;=;9Dih7cZdV*f}_TE({ zypMgB=+DFSV60cSNo2i}jh4E=6sIgoby48Xw{t#M+?89a;w64edw!vsL(O9X&iZ`4 zyvuUcSG}&?d*3+RbDMP4;+#2Igv(ba?zTt%o?Baj-dC8n9$IQ&yVLY)eK3ovt@EqH z?}~ejw^gz+Gwt#5TYtGpQSWJYDe;83uGSfkD(j|Zn{#(pt~s%nlk4Iq)7R=UEyP0> zt5h)`N!a$8YE<`3%=1`nv7WF+*C-E#E%PuNT#Q6;MmZ^#J9g!~<7l*5&RdgpgR?KJ zXj#a%)JsL>-WJ62sq0qnmM48+uEX+ZZ#%L*xa280rR*BEI$a|-^O~2l-fl4;9udKw z%_T7bheUT=Sb}}m`l2FwOvjd$5y9`rNc8OA<~>jDv_kgr_MHl!?qqFP86qsXF#ek9 z?KN|{n*CK&f?a!Zx J?cQl z 8T);AImgGYLcs;RK4Ssu4=E#KjsGpiJ4s&zmSs5J8^ ?`pEKupqQ84>+V!}3?UNVSXBG4FfRAJ$U?Cj*lGN#efg_ruzBVyvlaUW z3WjK2N-PM8Nj-Z%uKl(CGY%QnE)u>YF@i0V5ISjM)-+jC;o&LV4ab`<*iv109ei`y zWTKA=X4UvTj*X9}oIAgmu;N6mh& zH^f0@+!&^t}V7N>SqP@ zsP%3NrntytH(GWd(MicQEY RTg<9 =K$ZKxz!!1j8Yb51JIpjYs%}<-4#_YL*m)Y{c?Cl=y_A}%$XWn16 zZJST12zWVb+~fO?GWlZFm9~d!e6)S_wA$*R8NvKAUt*%PNyEg)hnMZ<;#*QPw))+U zC?VD C=TlB6lsdIXo ze~z%|V^hA1jVX)X>HCHDu5Uu_s+XSHb~!U>(WTtzhxxHij-KY2dYKtB+4r2h5veGN zdBtWkHJL@+M6WpgtjE!1JI92D$)7pB%O&CETE)UWiz6%TDeNEQP5j8r1#ff~wgm}C ziv)$8^Sh 2*_O=CSpk i9@;@qgmv)1kYI8F=NMx@}hi zGc~ebyw00 mwzI+zq k5lAu7LO?Xekz_`TfINdlZw8LZxJjW^ZWn^i>GE~Q $h*uPE2{- zRj+%i&P^qwT{k+r*YUZ^=?v1Ha*0P%+>=lB8sANLsbHv4>ggAJJG1=Vb{ sU9_ z*P`#{kHr{zPVn8gmWMLGTA%$&;g lwT%`;`&NPu3U4G-rEqinfip!L}UFO`$ zd*rFUSX=z9$ gckwDh+rI zm!*?$G5d0Oj`Mx2pL5)BS7GB;omq1y7pfkZ_`vYiG80^?bu&Mem3?eVpVQjyM)xV( zbduJ3@t%I4Bxm`id#;R5fGmr~WEQuC9rG5xW>MFZ-=4E5V-v5R^V*rB +2@?VlxylCYIe~Ql9;Xd#1%}msI(8F=MXi%U9HG+(|ya{pr%`jriG_ zpFGv?yf4e!=*Y=6!7O{_Ve$H`&Iluoc{^8D;4Vyir8U`CW@Xw-h}Y=vn*K&xXkUoM z }xWm!%(iyp)4#_F cOj%75;2r){^_?0UCBW(!N^JUv;<7wVz8 z9?SX~X9<@s+-t-k!7Ii+*=WUqY0(c^d^F@&ZQ3uJsJ!k@6-T=5W>@2Y1$@kH*O%Qc ze-ODjc*5>8K?#)mP3MGTGiHqCQOd>C?328Amu=Fu<*hsYS64YP!+aR$+w8m|CbsO6 z&pF}uQe(VKQ?d5KGk2Od7D;iHU% r0PaWd;a6A6hfgr`qJa*o(OnditEHErDjEadK z{}gAt?y^Tpcf)~_f9!6q(CR2@K17Y
VRGRRz vem0DMO3DIjDON-ug@AF%(JiGSdM725ckEGA J*kz~ePn$G~J1(4mLO<{En?o!3cwRh= z$Rpo*l*&KWv`c(!cSgfQj^pASvots|Cgab%mw)6I&1JE??_|*U)QK1-qmw)8Z5~tk z*A?Y1f3vBjs%wp2v4u{G+5*AzNj3|-&vDq5pI6|k4W0FLo{`wSD`C!uj5$A8w>|14 z^p>(+HjVmh%`tWg#a4Ot%NeHeJFL?l^J68=_whT=v$< 6kxib&%qpd^Mh;sIc-qe_DauMFhxakfbnrXP6CV+8xuVk5Fu%T)bUAQN z;@iweOIhL;_@_iaWH*{Rd+&{Tivvh&_D}2HzGXkDHE-p$HlMo%1$NXI2CsA5E*-n= zcfinnc0i2vr_M(^#%-`s<(N7CfimWTz !M3zpU^y! v1Psd9i!zUlB%{l0>JXhXd0_)4GTiE{5XmvLQ7a_AaM zl-6eQ^ TmF%C{=$t9MGs7@6S#3Y%v)yni)*#E7n?nZnCm(m znEG2KeuppSnRcJIS^F}`TXuX+4%OLDVE>JZW!2Z)o~suI9XZb?(Nl=U#Pe}L2(#Xz z#Ai`fccpX`U(O8_2|rB9V4KC_FL#WY7;=K;6NmIU;R4;X l~ze_ zYfRoBP}1JCFYxv) zTV*DevdOR9PFX&zu-^3aqDXF)=b{{wt!9Wstx&qKMkvf;&BDF*u``bDX2FP#<-m;h z&ENR(RobRwOC@egEO39cd1>}EPxZYJ5_L%gmD$j1lkkgV))08aESPILhcJ7?K3TY* z370Qi=v-Rb-|YV6cmGcfu^1EWA*B-OF0wh&U3f)=o6PXA^1r*v|4ey!Jcc>iU1(L9 z9ZPAL-Nc?y+euwvj%>sTH&L1Y43Iwo2%O2n6z3r$8sR2v8tpDRKlXqsLm=U=3yQ(Z zPYbhW&4II7s0>$cxD(egDjp9}jQ>ylF-5rv7=<~ozJ`A6g!53_2#!+|A9%`2(_4Ys zlyGG3lsIo$el+Hz+=aJ=+D>j_XgduL;Z9Q%o*XkD5(=7L#(y=9@l=`$=jsrLwq;^( zxHHeKC@<{NC@(RaC^zgrX!Fr%cj3cP?pU8_4{?Vu2ev%MZ{R%Hz6fXTGa*11{;O>r z39iIla#AplNsMhl_u-Bl1u v;qISgNr*l3! zq{oWJ=Z`9h@s!eu@(^_!Dc{`1m0~M5)X~mb8tHfXyI`m3lOo+j_Q&{08OFF`rx9UH zjHYh-_rEKR#VZMgJM$e6b7apVIC21ACa?+c0S7I7`!C8%Vrh)0=m_WYP?;1}EA16k zD@H{RV%)K2Q0H5qC+}cQcogL(xHbeY|4lmjZHRvD7g(nz10QxB)+FFd`}wmlyUC3a zz^{I !r#Q?I~s(=E(6L@nnN= z08bz3E(C`f4W)x2u +yjEAa7H=+G-9Yefxl$#_Dt(DXPSkSnL1|AglAS)wWg_cEo zs|XH ozrq~YGthfRSn2m@|3z?`dLQl4pntoeedQ6Z0{Ccmk%Oq*7#}$-eZ4{S zKH6JKFbrtYNaGIe=YS@}54N37D;?Q#5FMk}X<|a1jKx+YqW05pAV{JBEnF{ek^4=W zj`%5prvMibFV8~nXL@<4zaxR?M*W569KnIDh!F zlM+IvC2mPI)89ECl|LHb2- A0ClKyo?;kpx1}Ljn>Ie&wtLg1WsUSbOQ%sEf0DhZoZeI3FdwxVO2##O% z0l>f!5^2xN7wm-L{Bp5zMmX{8V}zH63z!3F&i!orQT{l*j405F5TH>tK)36W{33dn z6r991^sk=>sJy{A1_p4^CoEJ^D ;+fOvw=O$zYW3B?mHEkaa za)l339^xY$0tvLwQ%byFRsnM#`ijQaxC!j~*1GoXn!o&l_~R&V3H4Y{F|ByK{5Qw5 zqFRL}jDZryG4SP{)F&iJZWa|KKb4lQ@Rv~_&sPJwX>CpY;XVNEqhov|^k5I_1-zmY zTECHe@e71Q@8W$Vgd^Sftzo^`12V|@Pk=5A&GDO`pg&QcT3ArW$jXy#VGU^g((Znm zIP@8CAwX&s7AC)wkf^u|I%Inph02+TkI*)*WkcosW(faiaUoRdn3zU5s2Fg7)_y7J zijxBT WhwPS? zuk_S3suKT`?HykB=CVG{<;87g>x-$hJ*0s_<5WrMio*#0FKznH82GCFzn&Lxl&d-8 z$9wVNZTMHuF!qg$+AWL<+AS?$KA^HROvsaE bZUSwbY-1t{5 z`st6&EBbh56t>-)SKPMLBBUP&h?c3SQ1r#bNbxY9|HXV5-FQHIFjZB`SL^dnH|Cc< zpfb%WYG0vS(Dt5&gMo2?iqgQ5xus<*oJ54lc`z1w|IirdlaQ O|3#sN~-c0(0bZ_@ps}uNRZT|s9N=veC8*> z|1DYP7PaYU7POXY 3R*u;FKCOOThgwNrw-i{<8Z{W%33688TkqqSks>L zuNA*WC(&L*MxM0cUx58vKQ+#4=Fu%|i&M*Q?L!xg2eLt7+rEWG?O4Ps4y}yJq-8|n zQcxz(hjsic(1^E!0;Dz=6NCH7AB_*JNX0AQJCI!DKl3-IxNW*-L0d7L$xR)&y0r@0 zUd<|Mvs+ZwCipcT;1F9_FVMa~R-w`a_Dm;XEq@L)y;k6RbA+GV1AB_ye`C!Xj%;ey zrEz_Er)V-zv<4a$wOOkdw6!qcfC|rDIt6VxGm2W>78G_$TW4jBxCcV*LHk8TwHi$+ zS@KrcD+D5ZfUK LD{Eg>^90!i3XDg=DWjb?TRZcM|YCj8f zpqmi~wEO(l9<9Q*LcPM)OS6kx7t94Z2{huH`#Ll>3>Gy`Ra2{#lUJ@VmX)p8DJ4~L zNKTP#|2 (bVf#s# zAExt*J4E|=>EX2EtJW}~eb-lS|I!O2TdXE(?XDqeY-gO`3kq74v ~v*0$4YqVUFy^6}FnpDejarhdqWxF31%BL+u?2%~i?TORJL=GATry %Z`SFt=ytw=IRWkn~eH7&1Qk@dG&N)h}!dvdH~=yzaNq zNiAMKk&>hkNlBDys7}*{?cf)k3fdbQ6}MYz=C@J)4GuI4T3d_?S{Ho_hQIy3mZ)u8 zl_=RmNs`U2dyE^Rs{k55)~Kj`oo3;$<6wGWTk4|H#;Je1o!_dzl895JB+8Jg5+wR4 zDT+~5PiONn=B44Fu-)oc<^tj$a7C?K|0}XD#&*%~(Y&utQ3|0XN>Bj@-POq|=WCxC z580cbxiA}K1p_qk2kXKYx~N^ymb--1{zF>}IxK%HtxnOl02 3aM7!`NSgf_jT?G;9#bwlU`&^@$|K;QkXc8#{)s^r;xlw`RV{p|-FBuTc`q^S5- zz8Z=Hn%uaoOA+SugAw^e2ArVzGOwuhFUfaC+w%T=R9N#VDeA7!{_a5>BuchbC#xQA zAmTWNmo~qom0!QO{glSA{Q_hE>lL 9#MNb0OfRA6=kLH3zCnZ@a zu$G7u8V(!C&?f`Gw}nO%(B7G$?*T7Ovr0SuXLd5fVf&S5 P0>QhaxPb$$b3hwk10LFNAW!_8?fBKYQUBJYs<}h|e`Xv5 zU+yJatCE#&);}~*9&U$$Xvo5fcI=$u){Tn`TZZruzY5Ra_^$TJY{4OG0mEECc%bn~ zi86(hR5cHjmyu`w8}R<_I#GM7h?;9CNm8v}`n{hP41JdTOi7Z w9F%T9u@DzrU|XYWtUWKp(pR581GOy0r}Bo&Og6zoXuoG(#=e7nBa|^DpiG z`n^mQ`sR1k{a+{pt%ubqYEIC|hBA0=7&ZrPLnTmC{n!gFKBqN%VqBK&9` zR3%9_)~4zFb$!;4+Vd;FQ;2%1Rf#g6zB>kz6r(6ai?8^CU#aiE_6@QhtxDChLNcNe zae&r|6iu`L8r;7Vo?;?yA|*xT0Px0LU*RB0J{8TA-&x;(v8=`?^EeTWgZ2;Z52_NS zIw`5@>;H@J{t1}sAJ4*qygX@;9wx~>N3w%IQP+R9%-S?VIZBdD8puq$C`1k0|KIrE z(crx{O-&B=g4gRa=7@|Y|DVi5rTPKujsB2nCzaZW2PqZ&m8cG+Abh1gWBPwD!S3yU z#x>H?MqDQ??QH46!_C32mL7IU$8?qVfq!ftq&+BQYAWp+Gmt_-JxpmOJs8nFm@&Q^ z_Fyo(Fb91%;6P?NhU&WkOHIQ}p!zyaprvVz7;4(C3DnX~47Ows6kRe15C(&Vnwk-I z@KkEkK-%cr|J*qfQuw`7wLk5d23`*E+y~Xr(lNeJ9sFTR`cq#6TH52w?h6o8duB3q z($WnWYz}&ca!~d@NU fW^e)VHJ`lfIt)X_^57 zgGx rYE2^!G#wQwHsQWB+H=Mp`w{5DY>r05UA?8~B|%nBr*psJ;Vf8ovLzWFT!E zNNF7>3)n#z+5i_lPK2)%Jp9W)G_NB(uxjA{;Tz$??G)=S_>~OoUsmzUpCi}^p0ZrX zhXmPNk5o{kr;sGrqQC0*- VM%;z3zHxc}32K{-+|Am+o33zc{@bk#}0@tKwWWOHeF1jt+ zP1pf^fp*4tVpoHo(suCeq0sZeH_sAW#E00I{V(xOuPfXGD;jD)WzbIte8juK7soLM zkDZ2mMdLYqNe=ChWB{>0nJ5Gk#PHYE1iyrWAe~j8R z5 3mWpO{CwOj{r0 zBZ?g jx$ z3H`pLc9Uws-*C=Id4KgCqR-&R#NY!rv4ddGZ8E$()Gy#aIz&exFHaT$`?!x_SGf}y zm9OXwqPwAXEN|)b6s6(Lyt_jzeou@Rv@XTCi|E0cSw2{Y-K2VgGtZ#^7H#dK@dP}_ z!ku`Ip|y(MHc5q239xG}1v}wP4UPJ*_+sd*iQtcSV<`UlkD_%0#U4ol+Jxpd(kp=9 zy&U-S&8N|Z5oj*T8|5?&M{wphKw}ueF%Yw3XOzpdov_wqg3s!^NGBdI)bDf{!(4 l*K#&0{~KcZZOhR8%?@sey1k0$WG?IiH6p41TT$a# 0Kb)Q5kM((=4c*{Jl#2ZCfF=#` cDX++@4*7ei59ft_B$D=y{;8NU>fbqw={#^eNnh*M;D~@)Z1SW1>8S4H(xW zc@3Du!sHxA8)&e9t%tq{mX;$gRa2`G_@2KtYEP60zX9+ZnaGb5=wC9L3ykf2;v_T) z{H71k=#1UuvT$c^@1LQ=h+ZK2iTunN%cb4JCKCE!4Zz&Q*ambjC{WP`b30d5v?35} znAa*Ol&i>Uk+?K8hT8R^@rBk! P^^ZS7h%ajA-3LV^{wqih4sCx0|~q0f>>qR+nqGvha~uV$WA*t!W<(6S2ohRDlP z$AdllGKiUxjn;+H!1lvD;9DjsQ@M$;-rspY8~hdYz#iG4sC6ys2gFN&U#h5>1nCg? zXOf{EqxRJpsV(61@kU9h{Lje(U>+EPZz9-Fm4JVin{gfz_zd_WDO6}d-(T!+N54 {y_anGL~yStGx#5!odnA1|=gdJ6Mm z>+DZ$g7p4CWys6tjz@DuN~&rZqK!Z|Gr%{V+~1!5`2w`HQChCbXrwxS=Q}DjWK8YT zm2yZ9fde09-Taor& yeBzHT4b*6Wzo^sxd{H@IIw{et#F3JMi+GBTva z;!-3x#LvQ-cnIRZ{Bijg;)kk<2CEy0I-&?K$iGYn?8Crjw3pt7{ C c5WiT!a{=9G6z!Pt5HO}kg* z`v7+C(3X$d1+7uKMIHO~3tB8^l(g&3E9;P)TiG|nmiAA#q2`gMOm(vSQ_#!m(d)t$ zv}wY)c|EibzSt^%^*+C~8`{*QmEV?!?0)Ix{4Y{+mdRvFvit)|l6>r-e-exd@L4tl z9Dn! zdx;iWCi@sxCe!H-4QQK8$!=UXgy)B5g&d6^cod16k&To~C zY{#pUWs| hNV}-;xp1=n$%mnsx^n8CStx8e11b=`w zdK+l{k)(LC=8@iDjC354IM%SReTH^HOFYobPUwR+@O@kUw_s+hw=u(DDkV`akq$p? zEP 5pJn;$5AlBSjqG zIYuhyZ@#O~&{hFB3y1Xq@{yoj{eA+{dEis~mAw0J!cDIm$vi13%660l$qqWq!_%rn z>GJxAI?D8K{%a|sr&UREBibdSu~n6*c%E@S|JUG0@YE4?6~TTecR23B-kbuyn4^*- z|IK!x{bg0M`Z8DtYUpjC+5aZV-zpy9^Zq7$qp6z;JVaHpvJ3F1G#me_1gQq_`}pH~ z+tI)_+C0cVu{ud90NT(F`-Jem;l6sKE$A=itBuuW1K#>zRf?wRp9TXA!+>?iU`iW- zqlGjLGc4s8c<$^^OQ={X%2yr)R!bR>V!^s;FG|7a3erk;5VODv>&K2^DuHzG1Yf4K zF_4bQ0g)r5zEt1-6q}v~&rf}sGD;zZe_;RApH4ujF9t(TY46hpeor4rOJ;&y6y$5< z=ugwe1LW|WhDoEPk1%X_^jroPO3Me*(t#B0$!PBzX9B?Ru2Hl3gv+#1>DYc(3qUt+1Uj-(u W0|s6F&nSu~E+aU+o7FObAZE>H5SG;*F1{o?p#_#$UKAzhxxoV}E3u80#u2 z0k}2)UA7X8FeAPa<~LBlum55^#pb}dJ80U|{y>+=F?U(zSF$K7vc2%an#Fhs8HPIY zihs+dkzUSdQkt!X8{aI5pB_kX;@mY-|3!I-Ee``b1A2L~idA!E6)V4r)dA#-3FZqr zBZmZYsu1F$TO*k1-~CF8Xa *t91{Wm@6FY$OG&PZ1t{ZN=s zsP7oRkF}FzBe?SFA{vV7M)nq9GqVxSXbONi`X21D5)r)U8w6vdGuIA)9nLO5HdO4v zbUQD=ofGK)dLaf|gbdgsFxC+V;{f{A71k4PWOoB`sCiKAX4D6WUP4^=Fq-WK)EDI{ zpo_*lx@b0A4(w;4t_Fam80=yKB0a=sqkco mV;gwnlAtooM|z5o<&}`bH5FX zj7;S$(6cmy{;nHfj6}MwAL;6{(Ah;0Lm%4PI8Y{vxqXM=%)6R)Iq}$r*-fgX*9URz zuOQtD9iEX=uuC)#wVzxL-!+Civ7bca3*}Q%YMcr>J7T|nk< =?Y+v656KnEhh@rS2;2XiVf%F;d7sx_jw*c{#FGK8L z2T93F6Npc*DWy~;uBceWhioI1l`E$h8~07HfVln0o~GZX=HJVEJRoKP#B~rswgmv= zF~MmSD7N8u>=HmX2=N>N-*w3L4X$^9>*rv{mkM@353nMn2+&mrLs=J8RBFGnWBfVn zLCnFBkTDBT{JD}2F?p~}0iB);viJBtjNgO5|2JeGGFls}AHi%?+93{cUk; KYak~TtrCBm4iAB8PPH=0A} z+mY(|H}4Dz+V#~7+sZ)C(4-CV&5(Z4nr3f;!Dwseu}Mpl4bVJ?x$qRt547$u_A9!F z-|`Uc{5Non^le|6( Ml1VVlDeV&g9dIn8 zZe~C~)&sCoH1k_CKu>m3x2S!sKEzQ49W8cFA(b7`s-MNnX!BPjtIAg=DcrA3o=&5w zxZ+M(uorsr6^x9!REX;dW3>Td^Aze7v`5b=Y#-#?MqBS_^P#v=5KHI*=-?02Wr9Y< zU1~6=f2cD>xCPo2Y+m+j=a7sBMzr2Td<$pLpVWa&d>x8)fau_?f;J7Xb9nYWJc53! z73S3+mseHN^v_b|pnoo-Bq IlKp~iDz7S8buL{8g~k@xece#YZ|k7Vl`rG)GsIWjiEurdI{s~*swCApgMRx- zQbnLYwm`C9R4$sMx&`eXFefVMFaqvA;9%YUxAl(pdnB_3eMT5vjt;Wi8cLF)7t&dx zGH{@KpHb2=8)!^2iY*FpRu9tS^^dlWf13}<#X;6z_XS224@5Siil{!FZWDn6T`9y4 zUOTI(Q|8~+_p{$4`U3LrD~!6u{(ET>(8vI=Ws)WSWt}3jB>~-9J_8Q>b%qHNy)>O- zisJtIq&fdn`4%Id(Y%E?Z#Fbt!cg68zkU;FIa;q7zxiL^*C%PPQ<7!>VeIFAd_tT) znAiVnct)zP7S?6Z?Y(B~=c*)`^u{OCzj+qZNag&gcSv4QovN}3)|AQt7&{^M? OPE(g)GWPbT zX&_~S{=v}G^wNRfL9NmP?<+iU)O1>krKL}%qxb_DjQ@1ZbhOAagQYrRM42ZvVsMb| zW9r1<(eIdP(^1+7ybvmXcna^vp!b6*iZ+0r(|nP-3iMW@11U37TOmCbmX-z#r27X_ zUs%S_@96_+ns5Je$xJ-$eTis)+BlI)dv2tuqd+eO4M*S6QxtvyJ@*YusT2C&QxDQo zBy1LiYbIQDJ(KUC^bKB)@JHvZ7=J=?XgG8CJoq^sK<6Ja{`R}>Lo6_32o9WP1bfzt zAWxlx{FuT)R*23;0~y}YeqX_foe_?l=D({>#&V*agakpR`3}hjk*{8)yYLE-b V8`(5`SXPt_4D thRX4qy zFgJenNEaSkbVeb1$0!#>&nRXB=m{1hpDpzKtAD6HAUov#+NV)e2Axrk%0<3pDjJpA zFv^GU$4D;%I*dI8N3JEqWs{?Uho&oaU^@iy7IFyo9JXlO(Z54Jk4Wc+o E80mp{3^h><{;>2sKT4zBxTQcoU53UPjHgGjcAPYsE%^G0z (UlDvICI+p?O{BMpUjC0#SXr62fNWWJdnGT_aR}sg z-#8PG)C0I_fvXbyWb(kr? 3^d7BWDap)Abp8$EK2=Zwa2YD*A>mtBW4EX3CE=#39!x%}B1pUrv>l!g1 zj01@2Yy$GVDvg5n7t`}w*BO!exX{@(va%#;kn3)Rc^cN=H{^DP{^ H`4caj zvsQECv!W)091IV#31m;*j^vCWJF(F#YLY=dLdY){&LtCr`WAv-(+AGAzJnDe-;$O6 z+UNZzs-|VFO`on^k*FhQP)eN&ve?^SWKFHzAU`Yt--j@e?>Ojz%{S^FJ@DDZ;rn5t z)6Ac(lQBPSAC;`=M~>2%jLHYOOg!?#qswV%X}>>J6UgHV0H*Zm`E7nCS)=olXRK?a zdrB^jr8-HDKuJ+pi}uC_q)urVkHoKFpv$!Y7SI9gL-cE;@_zOmqRn70?SkZL6r!>L zdPe;|fQPT-et-j#{%?-8k7UeX7g-8&i 33 z6D3*zC$~_4AU_x!oMSsHuj9Atj~L-avHn0_Fc|-}-_Ba99Q-Ga*QKb87;A>{`+s{6 z PB+IB>DX`y#-^YKX^~0Nr_5EXdWQCP)Sr){DakvSTs#enW$h!NmAO2c>fVI zjq+s!nDzP&Tz-%~eoAe6R!S{-mQF1R02^BnA~0dF80=W4{n(EnitmK2VNd@>1z8DP zObpi;xJMU~MWBmbI2OVq0@*@W30%nb7@5U(;;BeZffz)z@uSNrHVj7U8QKUU9y1p0 z4;Xl9rf>)LrC>i673nzjU+>L9)&RDulU^g+r$|>ZWn^CkF<9>2w?X>~R@b4>{QMKd zp4klhta`AaI)?13f+2=Ws6Dq7+KYy}@z41A5{G_)Y{$Y~rmcl?Inf^4!lGaIiuQzH zC#D z26QE?bX0ujb_s(tw7e7WQhL&cC7PYzx6Q8j(rRI zb|_?DKgEE(6WX7FZPlAdCpJmcx8crQMo9jHz84iHdx(lutfli&VNUED0e5Y%mkdR6 z5G0QXbK&Df_(R{K8WLRirXYAxe8DI;AsmvafURPDm>s83xD$sG?0bvQz8mdhMMNrX z&>k1|bcPtPBZP6p0e!p(?V)LVWjEm&5Z@;X_S$&_XAYBa4?a=YBf|cFA_>LafxR~$ z!bd#d8meXrb>YB*Tp#|;L}UMp1=q8Y4V7FM{uIQC~N-70AC=$ z^d{1oZ7zZ_%#PI+#$N%*+BWs)8uC9AvJpgWL~qvvp9%36ynx?Fe0LAnACQy}C?(D?e}+`R_^=+%GBLc rmSe4k671`=-Zm&gXTo_xQ>_n6X^?y#|~EXjsr@rjy*F4DhaoxI$S_ z$3V=dk!+P 2&x;lZHTy2CyYrk9cp;mmk;v)TN?gUMmRwy#T=qb%D(bsS4WF0Wp(8gr@fm_Wx+g zN9T&%eS{a#Dri3rJYFZ%Qx5hkw{##bjn3O ~`gN!+T7|7B4)71@-M1=7zUXkSfIkKK;wDPIu1c0&b}1`> z9qqeeuX|VTH|UZnM0q&hQtBPznfmofGFK{-RkQ;NlLl>yz6IZC-s53?s7{mxU6lmQ zKe}HxDV1BDrYbd>??;md>0RL*l3P%AZ@-_N^xd-HFERZ_Q^t?-4B+Vr;HUxiyz_pP z{}+B|s!f*HhL{$oY9fA4j~sxfVtfa#eb`3K8TLk4WPSTVP-Vw(VAwGbVVZVzf`+UA z!b6HKD(&ilv@ zhmf5-ED;_8YK%7e-z%32Wgy;+E|ZOP5fMY{J+eENRWG6WNzi-^z*hlyg4LI-G2i9E z!yQ={1K$yjcoS4EvY$pWd641G5)&bVoi~*k@eHu`CqTYu$fg_dH;AVo*s#)cZb)t( z415yJj^1gi2jJ%gie(t#$UX;nk_zA%wqmj6(?R~44ZO`FW8>HfVfIrMBb?dQ&^OT@ zf-~V8h$lGZD#2Mm8t~%+IL{|Ia<4#mLcA2}PZ}TNz {qa!G1yPZ*Jz^qdHV~U`ov1L$bdE;IcWpsn7cq9`$7X$*72q!*SV4d?!A={= zW`|s0Z%XO`yhMCUhrkH0A)MO`JcFM`aHF<}7}-itkc4cO!NwNF85=CO1Mw`3-+k*o zBsXOI^n&K?a9(yMtWA!p|J18s6)I ih_F24UO_2N~c4 z&cgcB4(r<|DEF%Nr`C1aY0Wc~+-s*xsv}$4(XB}}kJJRf*2-?@yA&+M$hxPB&OHbF zQ%F&)samKfavq#x{jK&5e~ zY3p60bW~-6@-LT%>a0puT%epm_ zwi|>O41ZZbqd~WCfan|YfrI-aux7cV^@1VWH*dpSra-*=$*Dl^cc3`xVU8?Ye#ZX| z(bh;8zS&2uO}LR=JfewFUi`8Uht}X*`!Sk)z+uWtf*qR#(0)#|HwN9P2-u?ozf9Y+ z&V= t&AEZijrdb%jA5ZQ9; zd~beOE7e0lE&%&p6VQ`BB{;Ip16}4OC^tRYg-;Q!3kW{6UypEL)j4HnHv!fGC$z7D zeP2B2nOwmSVa`I$dwK^gjjcD$-zT%n+*0YjE%$ =bQZ+ z{N&gq-GU|u&}+r~znPx-lAw|F%3B_|hX!cYN>G_BEBg@dcrK{SJa8n|64*YU0W2dw z0n6Yk!18^u@s%&-Cab>~; EekAD&jQP;gV*-k_;}oY5^4e5 z%YkGKUM9#5&v&aQfyxqKnfC@bH&F{)2a8uDlH}_R>byYv=L6072I@b++6hQX2r{4T z)s%m=TYd7QJ^Ir46oVFbffslI2Qc9PxccJ&u(W>w!oZdW7|R1`ApT$v!9RfXpLzxc E0IV|93jhEB literal 0 HcmV?d00001 diff --git a/src/main/KeyWord.js b/src/main/KeyWord.js new file mode 100644 index 0000000..0fa0b9d --- /dev/null +++ b/src/main/KeyWord.js @@ -0,0 +1,3 @@ +// 加密关键字 +const keyword = 'BD' +export { keyword } \ No newline at end of file diff --git a/src/main/api/NMEAHandler.js b/src/main/api/NMEAHandler.js new file mode 100644 index 0000000..79313b3 --- /dev/null +++ b/src/main/api/NMEAHandler.js @@ -0,0 +1,103 @@ +import { parse, Helpers } from 'nmea' + +let events = {} +const on = (eventName, callback) => { + if (!(eventName in events)) { + events[eventName] = [] + } + + events[eventName].push(callback) +} + +const emit = (eventName, ...args) => { + if (!(eventName in events)) { + return + } + + const cbs = events[eventName] + + cbs.forEach(cb => { + cb.call(this, ...args) + }); +} + +const handle = (value) => { + if (value.length <= 0) return + + emit('received', value) + nmeaObj = resetNMEAObj() + + const strArr = value.split('\r\n') + for (let i = 0; i < strArr.length; i++) { + const element = strArr[i]; + doHandle(element) + } + + emit('handled', nmeaObj) +} + +const doHandle = (value) => { + if (!verify(value)) { + return + } + + const result = parse(value) + switch (result.sentence) { + case 'GGA': + nmeaObj.GGA = result + break; + case 'GLL': + nmeaObj.GLL = result + break; + case 'RMC': + nmeaObj.RMC = result + break; + case 'VTG': + nmeaObj.VTG = result + break; + case 'ZDA': + nmeaObj.ZDA = result + break; + case 'TXT': + nmeaObj.TXT = result + break; + case 'GSA': + nmeaObj.GSA.push(result) + break; + case 'GSV': + nmeaObj.GSV.push(result) + break; + } +} + +const verify = (value) => { + if (!value) { + return false + } + + const dollar_index = value.indexOf('$') + const star_index = value.indexOf('*') + if (value.indexOf('$') !== 0 || star_index <= dollar_index) { + return false + } + + const [sentence, checksum, ] = value.split('*') + return Helpers.verifyChecksum(sentence, checksum) +} + +const resetNMEAObj = () => { + return { + GGA: null, + GLL: null, + RMC: null, + VTG: null, + ZDA: null, + TXT: null, + GSA: [], + GSV: [] + } +} + +let nmeaObj = resetNMEAObj() + +export default { on, handle } diff --git a/src/main/app.ts b/src/main/app.ts new file mode 100644 index 0000000..7c8e126 --- /dev/null +++ b/src/main/app.ts @@ -0,0 +1,208 @@ +import { app, screen, globalShortcut, BrowserWindow, ipcMain, dialog } from 'electron' +import { join } from "path" +import config from './config' +import './load-serialport' +import { keyword } from './KeyWord' + +const child_process = require('child_process') +const crypto = require('crypto') + +function queryPass(passPath: string, passValue: string) { + return new Promise(function (resolve, reject) { + try { + child_process.exec(`reg query ${passPath} /v ${passValue}`, (error: Error, stdout: string, stderr: string) => { + if (error) { + reject(error) + return + } + resolve({stdout, stderr}) + }) + } catch (error) { + reject(error) + } + }) +} + +function queryKey(keyPath: string, keyValue: string) { + return new Promise(function (resolve, reject) { + try { + child_process.exec(`reg query ${keyPath} /v ${keyValue}`, (error: Error, stdout: string, stderr: string) => { + if (error) { + reject(error) + return + } + resolve({stdout, stderr}) + }) + } catch (error) { + reject(error) + } + }) +} + +function cryptMD5(GUID: string) { + let md5 = crypto.createHash('md5') + let ciphertext = md5.update(GUID).digest('hex') + return ciphertext.slice(0,8)+'-'+ciphertext.slice(8,12)+'-'+ciphertext.slice(12,16)+'-'+ciphertext.slice(16,20)+'-'+ciphertext.slice(20,32) +} + +const passPath = 'HKEY_CURRENT_USER\\SOFTWARE\\HwaSmart' +const passValue = 'BDAuthorization' +const keyPath = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography' +const keyValue = 'MachineGuid' + +async function checkLaunchEnv() { + try { + const passResult: any = await queryPass(passPath, passValue) + const keyResult: any = await queryKey(keyPath, keyValue) + if(cryptMD5(keyResult.stdout.slice(83,119) + keyword) == passResult.stdout.slice(72,108)){ + return true + }else{ + return false + } + // 成功 + // 查询到 有这个app启动项 + } catch (error) { + // 没有查询到该app启动项目 + return false + } +} + +async function main() { +// 异步代码 +const checkReault: any = await checkLaunchEnv() +console.log('env right:', checkReault) + +// 异步代码执行完毕后执行的代码 +if (checkReault) { +const URl_REGEX = /[a-zA-z]+:\/\/[^\s]*/ +const DEFAULT_OPTION = { + fullscreen: true, + frame: false, + webPreferences: { + nodeIntegration: true, + preload: join(__dirname, 'preload.js') + } +} + +const launch = () => { + const extend_tdt_window = config.get('extend_tdt_window') + const displays = screen.getAllDisplays() + + const { option, url } = getMonitorWindowArguments(displays[0]) + createWindow(option, url) + + if (extend_tdt_window) { + const { option, url } = getTDTWindowArguments(displays[displays.length - 1]) + createWindow(option, url) + } +} + +const getMonitorWindowArguments = (display: any) => { + const option = getOption(display) + const url = process.env.NODE_ENV === 'development' ? 'http://localhost:3000/' : 'dist/render/index.html' + + return { option, url } +} +const getTDTWindowArguments = (display: any) => { + const option = getOption(display) + const url = 'http://gd.map.hwasmart.com/' + + return { option, url } +} + +const getOption = (display: any) => { + const origin = getDisplayOrigin(display) + const option = Object.assign({}, DEFAULT_OPTION, origin) + return option +} + +const getDisplayOrigin = (display: any) => { + const origin = !display ? {x: 0, y: 0} : {x: display.bounds.x, y: display.bounds.y} + return origin +} + +function createWindow(option: any, url: any) { + const win = new BrowserWindow(option) + + if (URl_REGEX.test(url)) { + win.loadURL(url) + } else { + win.loadFile(url) + } + + const isWindows = process.platform === 'win32'; + let needsFocusFix = false; + let triggeringProgrammaticBlur = false; + + //弹出警报窗口后 input获取不到焦点 + win.on('blur', (event: any) => { + if(!triggeringProgrammaticBlur) { + needsFocusFix = true; + } + }) + + win.on('focus', (event: any) => { + if(isWindows && needsFocusFix) { + needsFocusFix = false; + triggeringProgrammaticBlur = true; + //弹出弹窗后重新聚焦导致windows任务栏显示,重新隐藏底部windows任务栏 + win.minimize(); //最小化函数 + win.restore(); //取消最小化函数(从最小化窗口还原函数) + setTimeout(function () { + win.blur(); //失去焦点函数 + win.focus(); //获取焦点函数 + setTimeout(function () { + triggeringProgrammaticBlur = false; + }, 100); + }, 100); + } + }) + + if(process.env.NODE_ENV === 'development') win.webContents.openDevTools() + + ipcMain.on('CLOSE', (event) => { + const res = dialog.showMessageBox({ + type: 'warning', + title: '警告', + message: '确定要关闭软件吗?', + detail: '关闭软件', + cancelId: 1, // 按esc默认点击索引按钮 + defaultId: 0, // 默认高亮的按钮下标 + buttons: ['确认', '取消'], // 按钮按索引从右往左排序 + }) + + res.then((data)=>{ + if(data.response == 0){ + win.close() + }else{ + console.log('not close software') + } + }) + }) +} + +app.whenReady().then(() => { + launch() + + // 屏蔽 F11 进入/退出全屏功能 + globalShortcut.register('F11', () => {return}) +}) + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit() + } +}) + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + launch() + } +}) +} else { + dialog.showErrorBox('系统提示', '软件启动出错,请联系售后技术支持人员') + process.exit(1) +} +} + +main() diff --git a/src/main/config.js b/src/main/config.js new file mode 100644 index 0000000..c6277b9 --- /dev/null +++ b/src/main/config.js @@ -0,0 +1,8 @@ +import Store from 'electron-store' + +const store = new Store() +const set = (key, val) => store.set(key, val) + +const get = (key) => store.get(key) + +export default {set, get} diff --git a/src/main/ipcRendererManager.js b/src/main/ipcRendererManager.js new file mode 100644 index 0000000..9fdcbe7 --- /dev/null +++ b/src/main/ipcRendererManager.js @@ -0,0 +1,26 @@ +import { ipcMain } from 'electron' + +const senders = [] +ipcMain.on("APP_MOUNTED", (event) => { + const { sender } = event + senders.push(sender) + + sender.once('destroyed', () => { + const index = senders.indexOf(sender) + if (index >= 0) senders.splice(index, 1) + }) +}) + +const sendMsg = (channel, msg) => { + if (senders.length <= 0) return + + try { + senders.forEach((sender) => { + sender.send(channel, msg) + }) + } catch (error) { + console.error(error) + } +} + +export default sendMsg diff --git a/src/main/load-serialport.js b/src/main/load-serialport.js new file mode 100644 index 0000000..e46c1a4 --- /dev/null +++ b/src/main/load-serialport.js @@ -0,0 +1,51 @@ +import SerialPort from 'serialport' +import InterByteTimeout from '@serialport/parser-inter-byte-timeout' +import config from './config' +import sendMsg from './ipcRendererManager' +import NMEAHandler from './api/NMEAHandler' + +const DEFAULT_BAUDRATE = 115200 +const getSerialPortConstructorArguments = (ports) => { + // 很多电脑自带COM1接口,过滤掉COM1口 + ports = ports.filter((port) => port.path != 'COM1') + if (ports.length == 0) return + + // console.log(ports, '=====================') + const serialport = config.get('serialport') + const path = ( serialport && serialport.path ) ? serialport.path : ports[0].path + const baudRate = ( serialport && serialport.baudRate ) ? serialport.baudRate : DEFAULT_BAUDRATE + return { path, baudRate } +} + +const openSerialport = (ports) => { + try { + const constructorArguments = getSerialPortConstructorArguments(ports) + if (!constructorArguments) { + console.error('设备未连接') + return + } + + const { path, baudRate } = constructorArguments + + // console.log(path, baudRate, '++++++++++++++==='); + const serialPort = new SerialPort(path, { baudRate }) + const parser = serialPort.pipe(new InterByteTimeout({interval: 300})) + + NMEAHandler.on('received' , (nmeaStr) => { + sendMsg('NMEA_RECEIVED', nmeaStr) + }) + + NMEAHandler.on('handled' , (nmeaObj) => { + sendMsg('NMEA_HANDLED', JSON.stringify(nmeaObj)) + }) + + parser.on('data', (data) => NMEAHandler.handle(data.toString())) + } catch (error) { + console.error(error); + } +} + +SerialPort.list().then( + ports => openSerialport(ports), + err => console.error(err) +) diff --git a/src/main/preload.js b/src/main/preload.js new file mode 100644 index 0000000..c1e0c9a --- /dev/null +++ b/src/main/preload.js @@ -0,0 +1,20 @@ +const { ipcRenderer, contextBridge } = require('electron') + +contextBridge.exposeInMainWorld('ipcRenderer', { + send: (channel, data) => { + // whitelist channels + let validChannels = ['toMain'] + if (validChannels.includes(channel)) { + ipcRenderer.send(channel, data) + } + ipcRenderer.send(channel, data) + }, + receive: (channel, func) => { + let validChannels = ['fromMain'] + if (validChannels.includes(channel)) { + // Deliberately strip event as it includes `sender` + ipcRenderer.on(channel, (event, ...args) => func(...args)) + } + ipcRenderer.on(channel, (event, ...args) => func(...args)) + } +}) \ No newline at end of file diff --git a/src/render/App.vue b/src/render/App.vue new file mode 100644 index 0000000..1c4f33a --- /dev/null +++ b/src/render/App.vue @@ -0,0 +1,60 @@ + + +++ ++ + + + + diff --git a/src/render/api/util.js b/src/render/api/util.js new file mode 100644 index 0000000..b3f3b46 --- /dev/null +++ b/src/render/api/util.js @@ -0,0 +1,113 @@ +import { Helpers } from 'nmea' + +const getPosition = (nmea) => { + if (!nmea) return + + const { RMC } = nmea + const position = { lng: Helpers.parseLongitude(RMC.lon, RMC.lonPole), lat: Helpers.parseLatitude(RMC.lat, RMC.latPole) } + + return position +} + +const getBaseInfo = (nmea) => { + if (!nmea) return + + const { RMC, GGA } = nmea + try { + const longitude = (!RMC.lon || !RMC.lonPole) ? '' : Helpers.parseLongitude(RMC.lon, RMC.lonPole) + const latitude = (!RMC.lat || !RMC.latPole) ? '' : Helpers.parseLatitude(RMC.lat, RMC.latPole) + const altitude = GGA.alt + GGA.altUnit + const date = (!RMC.date) ? '' : '20' + RMC.date.slice(4, 6) + '-' + RMC.date.slice(2, 4) + '-' + RMC.date.slice(0, 2) + let UTCTime = '', BJTime = '' + if (RMC.timestamp) { + const hour = parseInt(RMC.timestamp.slice(0, 2)) + const bjHour = (hour + 8) % 24 + UTCTime = hour.toString().padStart(2, '0') + ':' + RMC.timestamp.slice(2, 4) + ':' + RMC.timestamp.slice(4, 6) + BJTime = bjHour.toString().padStart(2, '0') + ':' + RMC.timestamp.slice(2, 4) + ':' + RMC.timestamp.slice(4, 6) + } + + const baseInfo = { longitude, latitude, altitude, date, UTCTime, BJTime } + return baseInfo + } catch (error) { + console.error(error); + } +} + +const getSNROption = (nmea) => { + if (!nmea) return + + const { GSV, GSA } = nmea + const GSVArr = GSV.filter((gsv) => gsv.talker_id === 'BD') + const GSAArr = GSA.filter((gsa) => gsa.talker_id === 'BD') + + try { + let yAxis_data = [], series_data = [] + const in_positioning_id = get_in_positioning_id(GSAArr) + + GSVArr.forEach(({ satellites }) => { + satellites.forEach(({ id, SNRdB }) => { + yAxis_data.push(id) + if (in_positioning_id.indexOf(parseInt(id)) < 0) { + series_data.push([SNRdB, id, false]) + } else { + series_data.push([SNRdB, id, true]) + } + }); + }); + + const SNROption = { + yAxis: { + data: yAxis_data + }, + series: [{ + data: series_data + }] + } + + return SNROption + } catch (error) { + console.error(error); + } +} + +const getPlanisphereOption = (nmea) => { + if (!nmea) return + + const { GSV, GSA } = nmea + const GSVArr = GSV.filter((gsv) => gsv.talker_id === 'BD') + const GSAArr = GSA.filter((gsa) => gsa.talker_id === 'BD') + + try { + let data = [] + const in_positioning_id = get_in_positioning_id(GSAArr) + + GSVArr.forEach(({ satellites }) => { + satellites.forEach(({ id, elevationDeg, azimuthTrue }) => { + if (in_positioning_id.indexOf(parseInt(id)) < 0) { + data.push([parseInt(elevationDeg), azimuthTrue, id, false]) + } else { + data.push([parseInt(elevationDeg), azimuthTrue, id, true]) + } + }); + }); + + const planisphereOption = { + series: [{ data }] + } + + return planisphereOption + } catch (error) { + console.error(error); + } +} + +const get_in_positioning_id = (GSAArr) => { + let in_positioning_id = [] + GSAArr.forEach(({ satellites }) => { + in_positioning_id.push(...satellites) + }); + + return in_positioning_id +} + +export { getPosition, getBaseInfo, getSNROption, getPlanisphereOption } \ No newline at end of file diff --git a/src/render/assets/earth.jpg b/src/render/assets/earth.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c4a5d335cf91aa61846971a92575e2b7c798ba1d GIT binary patch literal 1312275 zcmeFac|4Tg`!Ifw!65rknleP$DqBOvFk_2qG%}>!9%JA4JrN~@lFE`olu}gkuE?&% zE-58zMA@1KgXi3X>izz_zu)ik{GQkEucv$5XSvRGuCrd}T<5yZU5lNIpM;Y2{HP}& z$j}gygCK|l;zmFa5`+-KBEUf`g}KgxFbgvbr==s+++ +++ +++ +++ wboBA!L5bs{~Vk#KBvPP-cdOK)5ZM3b6to&ifg7;-FsekBbooLDKvyzLt%v zm94muy{nh2r@gD2xDG{CT*lDSn(6`rWFcimrR{2p%4&++#g$amRJN(%c0v$q0tBG| zT~ |7j!xS8!S*D-`x7QaHg%ot=72IDQhgCZer4h{}Z4sK3PZh=)? zs|1AkxVia+MbKzrG+IP}oB1qzOOb!N2%c4|czAjEd3pJTczJn+V24*|DT~1W4uQpT zNPq(}f-;c^35Z1iffPV2c7sN8Emk22pq6Y1<^w7WKS(fRSlQT79GqOM5dTa>KrG0W zM1Batia@fkvaq4pIoOcg+d!fKl68Zi5}Ve3OSFW0xH7v?Vpfs1 x5!wQ(;zNgOVUCsDZl# znoT)8Q3$R m!vwvASwJR;8PP=u{LaTA-^;R>LnRGznhN@TCG(KA)`vhDp@h5xz+ z(!Z*(*adMTnPmz<1gK}>mGrw}#I38flR~J@hVJ4~>2h>#jT!k&`{R8lLNs;8?ekWx zXXLbwbiMgHEAPXu_h1pieH-60FZv~Sgm73h-|Ec~<;|7%yCm}6Qhz+qyfCXU{e))` z+H3V>TcxS!?6jkfvD4ENwQCYE9h_f7C-q#+zEkq&FI_scr9kj9`=GiwCPrY)GuWK$ zvk3Kv)`Y5-?Yq acF-DH-qE zFEY2zXu9B5@Wpq@HH%OsVLBvtD*asb+E?b;cVfS;8X2b(Oft@EJ@~de&b@HznB~{P zj<6ps^R#yIz1)C~L$tW`Gh0fiw(};lxh=Dy@9t0Czte`;r(s&sqCa$y)*XK&_@&Q} zkM|dpe74(8Z(sk{`yhpfwug?__63~xP>oAZns*dE )m!&@$tvQ zBcgU_#I=R9?uXp(udeNM2r6saTHJl)_S^f@DzmrmJtmB8&z)6EL??g8>{4eun^k_K z>)Uow8aXo5_BuBhXYE~KdWn}OKe}U!zvt6aE~V3!?Z?WVq+fit!1E )Rq0NOv+(zP$LKConpZ2xX&jP${PM6z@UD=g z8Q)6_sxrBmru(GUx|-c_K2hdNSnoKy_lVuiFHg!s%R2`(;_pw*<8o_sNroSFp8JJ9 zC)uN|rx;1zt`mme1J?+?7#>+; BGYN9*1`6#m}klQwfafI`gVb zHyG( @w+qARn@nijcg;UPQlrF8YpWHQ) z?-<=YO)YF}R%a+=KU-LRBfC}XnE&g$Ua>NDHwT7f&w74See $lWp8A?t@_ZQq^e z73e0dm&FX`Z}Mjt&-h5|Jk)I5%YJ$CR>CT|6Ljggf%Gmq ^_^qa$B+Bg`s6wGko&W-ldbg=xqSydV{Z^2 zQ6ESzoJ )5()3s_loYF@!Gs2a9`zO z(-b=RHS0Q2R0210!QsqqYO9{aTejDmavyxkT4*_wb_D%#|2W0*are4|Z(VX~I^V6r zwr+Jx&=S) 0TQeOu1ZZnL~559vb8C!&28mA`r-Ee2+in(7DELIR~QB_}euS~Xf_(C5GFKOKq zt2fSb+w`1sofQ^*+wOmyFS+pT_5o| P^vFEVjt7D3 z>=xK&U0k h(^XftT yLSjXSbeuhT+(*63Pn7E`R?%_u|syS96zLw!D(RUGZuwUeN$XKb6W5A;NutN7tt)HsW0{kXm2^8_F W}^9kfNrSwBNDlKa6k1F^rZ_??XlCVxNfa^ b#Zh_N<8N =kU(A^ddL6)qSnjS2{Jn8Fu`&f7;P^_(}TZMJTVx zLplG}y@wPY&-A@p{On6J*~jXpdC2o?CJA5C?+r8_Zpd}sQqov`vyA%v?2}v4frm!o zheT>aw~r{z5iTF{ze-Wq@ack%2)X2z6yG3yPBeGk9Vwfb)4d2;MRR-%X*}lJfsNm_ zX-6mBb_m;nf9Kg9c&;h<@S))J!GQLKQyD!Y1?>kLXX}0TQKu`1Z@vF=?;Z!MYHVdN z#xW~BPAvOI`qg)v?Yh1mEPN3xjBsCvQL+Dl|1!M@`Im(T+rCTn*ec=EHh$#cbN!N! z9S7X{n)dis2kbgbo!yor`?_8L8THf>blK(E2YM$O#z#HZI*L+0G~a#taL(zD P1L)JZv$0%_a2s3m&}!f`K4%xo^H4Oeo*m8^V-N- R#5=`Ej z$23XrQp>z5h E|v*O~X` zZO7Mxgl em7z8kru0DQ$y!-SC`rEAL_c5=5Cu>z7)N_<1yFF zv*}F?wc*^$@xyPACeR(DZn#>`J3h_9sXecWii)idLt3#a28$M4b-&E}mPeY17q|l{ z gw7s)Fr+>m_WIs 6N`F3%GfkdpZtFl0Q%nhFyFoY4|#IrqLT8R3PIsSb;Kb)p(>PjTYo4=_9tA zAD1Yu`pTDw(*Cxm;P@P8@ng(km8gu7_?-K1_r3Gc)H!)tOn$(;KyvJyikVr?5X;a( zDT42VcE?fa*69yFcJ_p=*N<*?`PjWL@qQJ_`>8+>-n=j5e3L;-eEi9{;n_lW>oa|3 z2Jw$K5hGaR_*jDu#Kmv9dohB&MdKC3Pxyp6w%~AUMAY6jw q^X~gg_QUMaUb#C?SNDyz(p9)|DLbD^xODJD>%R1p zKt1x$zV8^mUd}R}o#T{4juTt;ZkE8U39DAC1~QCB?YoGW5XxKiTV2B_GOH8u#hu&d zF?*jTDmI1se{45sQNfg5x-B1~nK_GVr`XN#w13&YUGeVYyPrlx*Y8Tyc=l>`ua4Ra z!*%Xwjt(AZ!uq{u&-IKREOhF#;oKCNJ{w`f;JR~$^Yq${J8o>K7FCD ~-0~=%w zkeMojW%=q=JMh>sN=al?@!Ig`XSUzl&Oy&Ejq14ixN&RG&2m=J?VpR&a)Kq5QiHW~ z(ZVs#g<@Ak8)xo4=Dl+{wpRIp(|M%NX?fqt?%EQM!dkaakLiAV8*2kC@6ck-_Z7qs z=H;H=vtJq2N)uTanNVZp`W}2c+UD&Ewp%S?_S@>4#2i*_2|TKE_Vuakhv#=pUpm Q<(RqgxLglg;coO{Jq}f>}-IW)=x}uda;8K%j zP*^kaLDPZPmfS||kBROIS19WG{KM#VdhH8`VArm(uj|#{zj+ussN&Fb=#1wr`I0*V z!m}ZR7egj{KkDd5q;NmIxGK-zHm;|*!t|cU`xCmC+(k=Twv0Dc3Si>ATYatbJG&-F z?sTo6lBWtl!(4Hr4|dy}_EJMB`@1jXncjQ<<@QI+BS;_fV-dQ3r>*zp>bHTB0@L+z zI~+sKTp6(AkXX-p$u0i!Ovo2@ZH3cZy@bt+ty7`9E`07Ct1Q+ZFkY>44fF9*d%*XM z-e)7PB1?zxy9rk*@k$G)z8x4}gsOkEy)?|Fc}{Mzhu$WQye%`o?nrAcn=J`uvls}Q z36)Y346&=a>K#qgLWX7UWaZf{T6St$QnPUW$nA>u>9e~^a}FOlTaOwxph*(0O&{U? zqUN)?zU|`vql|%=r=Qg)q$8(uhjflL%UeHaR446`*IaGdaqscLp+lBYDvvL!R}_36 z4RUfi%&w`T(yS8_r&4s=;v3^#a9Q%M)gnc-D*=WV=C{w1-s_(LGT)rhTFFkjL;6}@ zzBA_Ew-;DVXS@?V_%`0?u2GkPW|8}ak`CopPgB${-EW%>9e2#|tTxxazimTRVs6AN z`li=Q-hz0VOIAEB%@-B5v-;_$?4#>zi{>tuT7F!R*Syu$d-!E+ny!=cyRbJG=Cdvm z7S5mFd2QE2bkB|pA_k%=STFjii)%b;;%w4~=Js?*@BMPgdp32)&g~t3-nh<*1y9Vt z*Wm3VcJ1k@6E3Q3E{~kg+_{{-YTw|K^aq0`^B+GStbSPfLHgVN7gCSWU`O+d4+!z| zZ4bTm%`4=^YcKa5Z;*t?9iw~h q&`dgjuR*3Y*8I3Q)Wx4zo%j$FaS2UN*LrB~{q=eIbDmIMp9J+qv) zIOw-cV0_lFdp_m$K=7X7W7= x&A&751;xL3 XUaE-s~QVy5w{hVf0s zuSYeVcvIbN{m$|_GoKnWZ2-9Z;DvQ=5VXq81851!-d=9rULXo9Dj_3JFN&3`s}mDr zw~Lppt&6uaoB)TJzO$V;@cEc|DO5igL!0Ua=Yf-#Xxe)0vvjsK(K~1YKud)!Wiaw^ zbv;3`_40NjTRB*RL~fu;^MG8z?*t?cQ6O8$3-X5CU{Vm5+fQr|W0KK!@^V?O5x12$ z)ya$M!XydOIhoixhKKep^@ci3f@LdkezjQew-%G#yr`}&o*;b sN$i<>dJ@WuKjw&(DaSvy<-62 J>Ey+P8~HgAjenwZ`Pf=}xq9eYdRf9PU{=z|&d76RR={Bx8TfFuA(HKhB{Kgg z)&yv#|E*YxwbK&Z$itd=2&TY%_^mx$-OTK5!Qg@!N_DYY={{aK!5Gv@+ttg<)!E6_ z#cnwZ_eu&}h2P*jD{y0~o&E0#t5y;~-G1W3yn-BCs>7028tCJfwA3t2K9XXlt>~{o zgb)TT%{Lxq3e2BaCg$3|$B|RaI49Eu4uY8r=<(r)Yne&Fgk{#?I}>UEDV#U~Qk;Mb z^zGn5EJLy`rTv5`GvSAUyMm*_gupX@8N#GV2XP4Iti^wQke}h?e@$Baze!{E1qV!f zg%4SXpqb!Z?l&wPVp<87`Vj+1k?`8ERC_oI!4?SE76W+I7pxT?kP~DB$%D1R6|~3| zgsdP-5VME;L0B151V0>jl|YVV#)7H*e13z$RDaqx{te+L?AI~^xp+Ils~v2%VYhPi zcCqpN2Nzp=!9_C{Yk2DaoL>O=kNF8{|D4B5)iC}!O_>d5_jICK+j<^wBEgJ?_**$_ z%rpQN1TTsi*{%CqStvUXS8un!f!JL=sCLw!Yp5OtrcP$U01X~XZ!cGUTNhgoOD|g+ z0Dw&V-Bz{$t|ep`0;lX=+6eytZa>o7!|87u3A6M64l(q!`}=0YZt3J@Vrlm`EM99{ zCnpnIKd;@M1}282mF0|M1^hQ;PJ36604*n~-AYgKEj8X?1q?a>Wn+87(wn)wa{AbM zc>N3dffexI(N|g7>9{(%di>V80!#F@^?xS7eZ0@r1@3E3FIP9PO?%q@zJ75zfrair zpxjo>h4DY&tH2Q3{}Y|bn=)`gU>^q4nJ~@_FY%!OGYpKMOf1+Uxip~>%s7k>p~(+ad4KGAf9!dG?0J9ed4KGAf9!dG?0J9ed4KGAf9!dG z?0J9ed4KGAf9!dG?0J9ed4KGA|IgU-m|C+9Ksg3Mrr-s7HDE-8w167h6)3N5A#tEU zvj<^VrR~WK0aZPO{vR;JAst{eQ-ujG>FJhq<|z2$Ib6o#C+=c SZ nN~k>m?E%fd3$L{fSN8f!P(8w@F(Ga?JZ|#xLr(aPcJ FVuaZL8;F>*6K3lHJDoXI?j;;AS?!##+JF$<`U5d4jP~`dO6Q%C{Xqv;3`c zKa-gQx>5ibo_|MQ8F?5HG+0g7)!G{_bGNRBgwi%$-R-+}Dr>3eYHRE2;q-J=wN+Gh zsA}u!?bK1#QC`Wj+r`t%(#6^q&I72(Q>iv;$|`z0w3KnXfTN_kLrH0e;*M=Px?0Mr zJC$(Tw&7G)@-EpLES>((%C)gpJK^f#YzexY>TGFetKi^fYbPQ8v+Zh3wYj0Ijje{n zHfB+3Iv%#bhyg5@00e&ovsF=ftD=gDva%Wuw^?zAnxf(o9>_#J;r|c3?ItT9%lr)$ z%xoKA3jLpuVFqD#t^w5(SWo?zr!d9VeL3Vr6=zN$HA`#Q2(2OEY3XBYBe4vm{(tJ; zC4#=dX!=`w|Fa!SXr8VoynHP^Y_;sb(66xQuj>Z?_=sqwV%GMSE_SwHZBUR<04-5~ zxoD|T3jb^`GwnByTR{hG3 T5*1AltpPY?X*fj>R)rw9HY>VaP;5L*`@ zTKIzV#cyB!f|Jeim%m&n)GCfuf?QmJs|9!kR2DwYf?6+s+`9xuz~{Z?XDJ2#;uiuR z+p= M2SC|PkwQpesE(b)E*oZ*Cz2_W$1VeY8mHku;Kzo?TOs1D!mK;Ptip?kN~0z% z)}2{du{lw47=WEALK9#9%TyXA0<791s2Zx~;Wlcj=2sfk;|@eawMB}+<5_-Jq8PH3 zW%lk-65sAo*|3&Cu17r5cXN;+5*4QmJJNS=#=z+~szyxgVX~El2u%vqgz3dvh~$6< z7m*X%W>~VsMWN3qq8b88OaSdgjc>?`x59|fB$%y;IRj#rpo?(nRpnGb4g8t$U?@D8 zJytxM6ft|2667p!$>mhI>2f`ANF&xV_c~1qgG;Y=_bN`Ws?-ry Mdn4b%d|}L^WlPu|zlf|P|L#w1>N3LGl My*%LudlZUscK zr9R2*|MuSe1z!bM;@{sDT5!4HUoKLKj{nVD!mLLLqVQNAkH;85bpTYE)n1_ dry88wNA$l>i?0crvg-=Lp)M2b0az`hncjr;n$L!@=k$M~ V?9Zh!ev7KGPp zt$K4zlYZ1KU5q7t^PMBqZ-_GG91P88E*_`W@NBV((Q(9AdJ)Q>J+2^qK9uh>V}zcr z1HNjyAm^7x;G3~Zm&*8*R5htoB1ccxr<1jxa`uNtl96@bUvT( BI$$#?4-k7uz<0tN8#Da?d~G<87P3M<<#)_@(Vio1^gT&RNfu+Ht*UhgvFC zw6rIEb3gmLhts(+{REyFH9t^+%1PN?f3Z)|{iYM-4fKO>$|`IXpz+BHE<%vA*PrjX z87MA+u_^dwum74)o5#rLx)8yq?Rb!3&m5&{k^m6yfQ+1=SU@txC-*GK?=VId@#m{F z?E ~9ii-A6u2oiPd2GCyfQnMaEV zl4>5<59iDU9$%a$Pj-EFml(#zaM@Rlmv$ZFJ1eCFV?WzLX6A~nL2oGbKN9LV6 gmI)4%wT7G0C0W8Vz>m-rHyh&ej_#m*oD@Tu?S zbo$6+=I5Os7Nh6LiHlGzEh3aUNuVz@k;gRk7a_4Ou2H66qAIq5HlGg?HTy~k#WP~= z?`D!LC(V~U&7p@=(iM{d4r7e^@u1XG$DUm>X`LJy(;>eoD4`JZ3)^sv{4xp;L9Vc^ zQvV{^AxOHe*`OEQGlQ`o<6?+O=bUTGK-D>@YX^x*{}9d6 J!fohTkJT4bjMfFav1BLm73QQf}cn%|0L)^yV%QQ$QWn9mFYZyGAP7_Hq;i;x)r zy%mnr$ePI9`P0$-1_lT9BczGmB<2lz7s*oCM%UrLQ(_)gwRwzWNRThCBsWAnvY)g_ zrOqgl46%mPsEnk;me~!r6