From c9b91966e77bf10cbbc487d05eef4c27c4dedbef Mon Sep 17 00:00:00 2001 From: Xie Changrong <1225674957@qq.com> Date: Thu, 12 May 2022 10:36:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B8=E5=BF=83=E5=8A=9F=E8=83=BD=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.idea/deploymentTargetDropDown.xml | 2 +- src/Logistics/.idea/misc.xml | 1 + src/Logistics/app/build.gradle | 6 + src/Logistics/app/libs/eventbus.jar | Bin 0 -> 45302 bytes src/Logistics/app/libs/java_websocket.jar | Bin 0 -> 88934 bytes src/Logistics/app/libs/json-simple-1.1.jar | Bin 0 -> 16046 bytes .../app/src/main/AndroidManifest.xml | 3 + src/Logistics/app/src/main/assets/em.js | 1 + src/Logistics/app/src/main/assets/js.html | 121 ++++ .../app/src/main/assets/roslib.min.js | 1 + .../mysqlconnection/DBOpenHelper.java | 28 - .../logistics/tools/RCApplication.java | 42 ++ .../com/example/logistics/ui/MyFragment2.java | 93 ++- .../src/main/java/com/jilk/ros/Example.java | 139 +++++ .../java/com/jilk/ros/MessageHandler.java | 26 + .../src/main/java/com/jilk/ros/ROSClient.java | 68 +++ .../src/main/java/com/jilk/ros/Service.java | 134 ++++ .../app/src/main/java/com/jilk/ros/Topic.java | 144 +++++ .../java/com/jilk/ros/message/AudioMsg.java | 9 + .../main/java/com/jilk/ros/message/Clock.java | 25 + .../java/com/jilk/ros/message/Duration.java | 24 + .../jilk/ros/message/DurationPrimitive.java | 25 + .../main/java/com/jilk/ros/message/Empty.java | 24 + .../java/com/jilk/ros/message/Header.java | 27 + .../main/java/com/jilk/ros/message/Log.java | 32 + .../java/com/jilk/ros/message/Message.java | 202 ++++++ .../jilk/ros/message/MessageException.java | 32 + .../com/jilk/ros/message/MessageType.java | 32 + .../com/jilk/ros/message/SemanticRequest.java | 13 + .../jilk/ros/message/SemanticResponse.java | 9 + .../java/com/jilk/ros/message/StdMsg.java | 9 + .../main/java/com/jilk/ros/message/Time.java | 24 + .../com/jilk/ros/message/TimePrimitive.java | 26 + .../com/jilk/ros/rosapi/message/Empty.java | 27 + .../com/jilk/ros/rosapi/message/GetTime.java | 30 + .../ros/rosapi/message/MessageDetails.java | 28 + .../com/jilk/ros/rosapi/message/Nodes.java | 28 + .../com/jilk/ros/rosapi/message/Service.java | 34 ++ .../com/jilk/ros/rosapi/message/Services.java | 28 + .../com/jilk/ros/rosapi/message/Topic.java | 34 ++ .../com/jilk/ros/rosapi/message/Topics.java | 28 + .../com/jilk/ros/rosapi/message/Type.java | 34 ++ .../com/jilk/ros/rosapi/message/TypeDef.java | 55 ++ .../ros/rosbridge/FullMessageHandler.java | 26 + .../jilk/ros/rosbridge/ROSBridgeClient.java | 260 ++++++++ .../ros/rosbridge/implementation/Base64.java | 575 ++++++++++++++++++ .../ros/rosbridge/implementation/JSON.java | 335 ++++++++++ .../implementation/PublishEvent.java | 24 + .../ROSBridgeWebSocketClient.java | 201 ++++++ .../rosbridge/implementation/Registry.java | 49 ++ .../ros/rosbridge/indication/AsArray.java | 30 + .../rosbridge/indication/Base64Encoded.java | 30 + .../ros/rosbridge/indication/Indicate.java | 31 + .../ros/rosbridge/indication/Indicated.java | 31 + .../ros/rosbridge/indication/Indication.java | 83 +++ .../ros/rosbridge/indication/Indicator.java | 31 + .../ros/rosbridge/operation/Advertise.java | 35 ++ .../ros/rosbridge/operation/Authenticate.java | 56 ++ .../ros/rosbridge/operation/CallService.java | 41 ++ .../ros/rosbridge/operation/Fragment.java | 37 ++ .../ros/rosbridge/operation/Operation.java | 77 +++ .../com/jilk/ros/rosbridge/operation/PNG.java | 41 ++ .../jilk/ros/rosbridge/operation/Publish.java | 40 ++ .../rosbridge/operation/ServiceResponse.java | 38 ++ .../rosbridge/operation/SetStatusLevel.java | 38 ++ .../jilk/ros/rosbridge/operation/Status.java | 35 ++ .../ros/rosbridge/operation/Subscribe.java | 39 ++ .../ros/rosbridge/operation/Unadvertise.java | 33 + .../ros/rosbridge/operation/Unsubscribe.java | 33 + .../jilk/ros/rosbridge/operation/Wrapper.java | 33 + .../app/src/main/res/layout/my_fragment2.xml | 4 + 71 files changed, 3897 insertions(+), 37 deletions(-) create mode 100644 src/Logistics/app/libs/eventbus.jar create mode 100644 src/Logistics/app/libs/java_websocket.jar create mode 100644 src/Logistics/app/libs/json-simple-1.1.jar create mode 100644 src/Logistics/app/src/main/assets/em.js create mode 100644 src/Logistics/app/src/main/assets/js.html create mode 100644 src/Logistics/app/src/main/assets/roslib.min.js delete mode 100644 src/Logistics/app/src/main/java/com/example/logistics/mysqlconnection/DBOpenHelper.java create mode 100644 src/Logistics/app/src/main/java/com/example/logistics/tools/RCApplication.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/Example.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/MessageHandler.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/ROSClient.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/Service.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/Topic.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/AudioMsg.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Clock.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Duration.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/DurationPrimitive.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Empty.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Header.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Log.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Message.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/MessageException.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/MessageType.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticRequest.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticResponse.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/StdMsg.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/Time.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/message/TimePrimitive.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Empty.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/GetTime.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/MessageDetails.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Nodes.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Service.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Services.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topic.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topics.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Type.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/TypeDef.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/ROSBridgeClient.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Base64.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/JSON.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/PublishEvent.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/ROSBridgeWebSocketClient.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Registry.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/AsArray.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Base64Encoded.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicate.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicated.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indication.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicator.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Advertise.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Authenticate.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/CallService.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Fragment.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Operation.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/PNG.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/SetStatusLevel.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Status.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Subscribe.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unadvertise.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unsubscribe.java create mode 100644 src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Wrapper.java diff --git a/src/Logistics/.idea/deploymentTargetDropDown.xml b/src/Logistics/.idea/deploymentTargetDropDown.xml index 0b9ec16..458bd4f 100644 --- a/src/Logistics/.idea/deploymentTargetDropDown.xml +++ b/src/Logistics/.idea/deploymentTargetDropDown.xml @@ -12,6 +12,6 @@ - + \ No newline at end of file diff --git a/src/Logistics/.idea/misc.xml b/src/Logistics/.idea/misc.xml index 776ae1d..1c17b84 100644 --- a/src/Logistics/.idea/misc.xml +++ b/src/Logistics/.idea/misc.xml @@ -22,6 +22,7 @@ + diff --git a/src/Logistics/app/build.gradle b/src/Logistics/app/build.gradle index 99fe4bb..ef99642 100644 --- a/src/Logistics/app/build.gradle +++ b/src/Logistics/app/build.gradle @@ -28,12 +28,18 @@ android { } dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.jakewharton:butterknife:10.0.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0' + implementation files('libs/json-simple-1.1.jar') implementation 'com.journeyapps:zxing-android-embedded:3.6.0' implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation files('libs\\mysql-connector-java-5.0.7.jar') + implementation 'androidx.navigation:navigation-fragment:2.3.5' + implementation 'androidx.navigation:navigation-ui:2.3.5' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/src/Logistics/app/libs/eventbus.jar b/src/Logistics/app/libs/eventbus.jar new file mode 100644 index 0000000000000000000000000000000000000000..3e62b44d3f59cb1f92e808d378a233625c439592 GIT binary patch literal 45302 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 W90D{9xpj*I`m+q(BwyrS{q;Y2KqG_z literal 0 HcmV?d00001 diff --git a/src/Logistics/app/libs/java_websocket.jar b/src/Logistics/app/libs/java_websocket.jar new file mode 100644 index 0000000000000000000000000000000000000000..bb5caeb4e80a53b60a83868128ac5fde26d7ac64 GIT binary patch literal 88934 zcmafbV{~RwlWuI=9ox2zH@0mXopfy59oshE*zDL&I__AvXTF*5&di;;bJpJfs?Mra ztM+s1IaRxq zdTIF?X?2h&Pzr`W@?IS|(JJV2DynX|v?Axz4+#5+Q|`$Kh#2he(P+u8DwsL<(QtRs zXmUSZIlMc(I{s-32#D-|F&pBqEsidhO#f~z2#DN&kwE`92^(V%V?$4K6IVx5TXVO6 zD!}~fEB7t1SNYA!$ZKSs1{&{7^ zP8Lg)Eo_op&kRXH@yPEu2&2@!ApU&k7hK0Eapoi%yB%mFS(}=o8ePL`cv6rCv7jk z@@DoKJMp7V-HY&x64(bn9x%4`m9od@^3>J%WGM3P3DXvZZ!r8db|XOY+-r5)H+cDV z`1&<@2hIAfB>p8GR;5Qf_S5WUTxkSMS}#l(u_ICMp>Fc zLoUe1T8RO^(k7JFmNzpCS5Xn5(<(Z>>wI6lh80h_?qi{%5x>1%v)cyHMGaNBa^}U1 zZIM8`m0oYH@v5xJ4?j~IBx?DcJRc$PdY5vR{L2IuIw*eo= z7j?grj&&F3v~tDB3L}2--C{zmT)J4b=TV-u1SMvqCv&zS@50qWJTCLL9n*DP53U=*K zmMSvpLO@$pf2^Y~wZ)bc`l={ZUHk|+pVW+wN_5F}fIh==4>6p^5m{-YQt%mDF9PVL zF6twVw<0!QqqN6*UQeSDBvLBZx7w6vH8lc0)R)Z}guEe&{0f-hOoppbkXWqh5MQXc z{iy>`D?Ye-NL47IhMl*jWIEzIv#yF4&SX{nHDt^M`;io*y)!iRthOP|ON8Cz?Wr6x zGk!zr{$2IVONJhSEz>O$IjgLLTzk9mJ%vzVKD$abV*)0Hhf}qgKCg7b9380$OS<%u zMkYuCtqj$6-Hd3c%*zNswcxCxCXu@hQGh7}iz_l0H8^McjUHqx4{tTi~FA2(=w-$nJzAg}@&Xj?j&ajPE3#{SelP8;@fXY=cl4 z8@5g!JzW_|>=le>Qf^TIAKXZm0aJ-3)>6q3wjPCy??o2}p`Kl^9pZ_bF#yD^u|Ds2 zYHe+F@cnU6C~`6_F2?JS3pkI7nr4rgWhZBt#JX?Awdq4-_6 zOelLEi~Mf846!d4oY4GmIpOyo?XQaje~d))jKH=y+7)ZuRLouaLH(HRHPtV5(;m2! zv`BSR9O&wD3E;p{gGS^i4hud{D7aD~3&T?nM|2n8ng&ItVc#Ch#!@p4^I;>}V@p-_ z^LlTe>3FpTrL=mwqP3$ZHI9)GuvVb|sq1P_I5F%rsi;3(Ij|N1r3}h0-@|9U2aH^Abt6 z?-IFXu8}h)w}Zb_e8kHPee|)C%b&cO{LK)U>~JgVwkV=aDe3mCX|$X_v=ck>!lAYb zc@3OXU%xNhfvB*0U`S2Y!tS=3U>TekSK^&tUw2)P&8@x;lQT_?U@MC1Y0)5|!RcW*K{S%sKZ6`7t(Bvo6+OVJ9%ue;C&a)!X_eQEg?F* z*2rM-z%1R6Moc+>rA>mRIzNW?C7CocLj+^53(zT+`*7kd+41!rJD{4@auao}UFBkC zXYTCli$`3TyV-kt^hAD$y}A};W_E)nBgs4-U{1(n*T;_6#^KzCAq?JhHQVX^MBQ(x z3ozT+z0o@6I!27p%7F)pu(`+FW~KoOx~+|b+cH%bz#CW}oa9SY_b2jHYW0#1O0q>w z><3*6TR9THXX$ll%^I$G4uqq|6vDk0K<}oRcJif%%MX@zlNEUfo;o{NXp=Sk&gp^x zY>&YeCamt~zSS-o?FkB80NfFIHC*p^q7kjC0HSD}lLoJJq3*1E3jW7%CX+J?`fRBO zoEOHvpX%|>cB7ja~P6sTUljPN0Q-}INfmVPG<|Za#yGk zTJnr;j;dR}Sks&l2bB$o1l4vfF14@y}sK?NL7 zwJv-KqHB#l=FhX4jDh!89z_XuOU3E+*7W@G)80Px)2#Nq;pbqUQFN2dbW*4MyGZ-y zLN;gB*-lhh&LA5s5nDKgY{>J8MS6t4B0BSH8%}c|=G~&Kd?K`bxCkGK_D_n2W>nou z+j-mk zWPWlk)LLAE0>BuqX!*liuH=2oUn=MwD!mmLHJN9?4xvQ7*U)i_bJ920fE~2b3$@6(7rZ!;dgN*Wgsu5)B|TKpjm>F2TOAz9vKikV}}y zi)mF5{!Qy=oFT8_jCk%Fu1tX=2E%c~(dllq7Mbv_VFL5UInccMg_+a$A-e-Zr#jFV zZz0?9=d7y>zCcIn(#6Rwe9C^hAyQtm_Cf^uQ^I{V2Jg#S=^SRQFVw~fPQ1^D{bTRN zUCb=8#wbPE7$qDSIDYXg_TpsApL<@s?np|960l3Pf@nB1VTt)Q?#ubL@zy}xFFCiw zc!Jiwo}5(Y^ghS#2*Rhk=D5hl1A5w$td!gpp80(Xam%fjpts6}&@`szb~8vVkW7L?XR%(2|`6ZBM8p_Y)?Q6YZt;PaC1& zO1k!kQ;N;U?k?A^lL39phSl6HLC)w((w3mq!c9-X3rBt25NL_ZnYGp65`u39vEK?~ z;}=GnAeW&JWz|FHPnlC|f;Zbip8!0-?dm|W{k z#R?9sgu>Ro%Co4*6yrM9e$O*5=$cyD*T!m~t47VY`0mAMd%_L&{IgXCCAHzX-O`zn zC-t5F&w@E$pUOEcx#<1rm^JF$TmJkeV*1EI#UWMk36(BcW?fqLX6}{ct+^XbJN;8m zM`>plw67~qYuLgMY~0IqoXpumqI@wr1B=KPzr1%{{+Ab2Uv}GZ<61x7@J&zi`XkcL zeDR3FnMVO`Y>b3VTTZTxs;3o2Ld#+cK&Gl|N+>+huS$56k=- zscRr=jZOr*H!9RGJ^C>;#=kUi0_#$ZUX@7$NK`-lpE9t-Tlx}CR-(l@@)yy)8o31@ zF|*!vl>Kt(qL{!A;zSjC)&G3j(fD1_bbnnIJ_Ydk_HA_aEin9+-%rrpg9F`b^c9HT znxOBBx7_o`?{mR|>w14Y5x`(9?gh^IamCA(NB9aQs$Vn4?^x71v90k(-g!kUN{B}q}mms0Bo8_~Y{6*mn*EgiDWF%MK>efKw zVEweR@|@pq5jVRl?CY)V`;$^h^^--dEy==(2zqpzP^n4Nu#QHEiBHV*fk$HSPyDG$ z?em-NOTGNdT0ojtoZMcet4=eT5@KW$4G+PnLftoB!aBmnF-L@PBzI;a^tG_&;#R z|41BV6s67WoXlPR!5?eX6%_F`F$89b*j9k!3zM)t&#Wh?6BnQp&?-@@s!2w zjj7!IQJW)-Yd(g$oe5p4A(M10OvTG~#lMGMr5fS+Hbm)@oa#AcXkn8ltu zqdiYKzT3GcLZ7cM*dQmj)L}*3-^38G_uC`dmVc`tT<^LNIO{0`m#Nc%&M~`LaTmOj z%g0?d?FFLSswAf8UV6h@YQAl5@~2*gKhLs`v_8v)xjDF*e#Ul1tNe7Ia5VOpBxu)Xj69$Q!UI+Lt6L^yAfC`&TOZ7 z$oP=O+!l9G*C%ADfbxvGxSAS1yHqze58X><-Zd&IaCYc4N^OT=R&`8@_#s-E-GIu` zsHH)~aX_HJ)FirmeF}s5Ad39-{H6xVLW9!v&`d4Yd&Fx_*an%UUa?p!RWkLZ=Rk%$ zOP_kUzugFpbV`Rpli}|yv1@T2Ft3XNxlh|(tEoy-9-lPTfmugQMZe4_fatql4aV$* zKnO+YEHw%Z1u&ZEZ`PT@$xx>Pw>c5pCj-zd(%GeeM^Q6@2?@X;V%%1Am%CKseEw!ptw<;5%%4Yt~(98z)W8 z-+wIk4I!~lZ8l|t?S$>eTV=t%zv1+jnKvW0q^63huLJe+uT?;hvyNh1xk*8s2p9t{IxYIn1Dal2+|1 zm$YHjU(*EI#?GqlV3NW)n0&n`ROpSb9GD)VU}<=ucFZ-j!jkA6`8+kpi4f>6&SQ87?|z**5o@TWA>Th(2~b{^u$GA$H}|bUA!wKGz`QMW89xBd|adKLXKKtgf@g z5VQCZEEkSV_?@%8;h5P`VS`*1*>E3sO%SLVSVQX`zW#%2eh?42sh80v|L3b^xo}$Q zu@hE0PuxC%!!Fnd)17liNO(IKv}UF|j^YdWJHg6DCFLrl_DFatXJ93ah1d|P_-h!C zZ{(Mxx(LMZ>88+sh81fae^+KO5D>Ay&_ea!!-}T4$v=Kck*he`ng0V%VpXpl7mQH+ z4Roke;%-f6SZ<+_sF)$k(1e7s5C%d@*3fuaqQA*kVDiajr?7r8jG|exXMKN+XWiaN zgxqJfPVO?e&O6Dw@csBWd1C_EC?6&^Q5_M(pfDp(F{fVLKUT(&W2N|ZA0>-Hb5(_w z$1JX6Q`Y0zPwb(;VWz|zXX?YC`z>|~6&QBz6MUZNU)}d+_b63+JN~E2ajF-KACtQj zK(5oZVe5%oEP7q?+F8SbvCSC9|Lc;)v00m*Aq++L%6FloS|_f9i|A3|TKL-aNJY5i zD{xOj`G{U!*Aq&8`ib6BiHSixPeWg<&9~Fid4{Ip^i(YQf&c{Pm zK=kb!Ll#r1Hn`N&C=m;+L|z0Zf-hX{w9&?l*Q%EAZzT704$t4X$8^z?@_JZm+$thj zOd^s6(_XZDxMH7u#c;oF^akuVGqWhjF^dz(AH72njDa46HeD+8)8#wY-!j7#7hG02 ziXttAH0$jjs%GqZt$R8Ye5>Xf;iu_Wpb`|F^Yu;+R3ya_=-NSfQKPPsPty58-=gMt zLYOdEHp%f}U0^E>#XNKj#i+gTXNBnl#GVOAp+k;AF3eJ+SvN%)#}-#eyYSw_!M1*= zZBOKqxVRwd4eHktJ_Tj*7Z!5~sW-|c-&Ea!?;Go&&7cTK(8HLq!0hkkW5A;8)QC9; zwR^yMxbWo4$Mmzh%O&JQBjHm+e1i6zU^eGalgv+jLjLEVqmCF^lmQ0;QHKHnA^l&1 z?%(1~&0Y~*1SPK|RFsAk2Bw#+95Pi^Sy`lnDSU~Y!5UujL%6l4gn+>F(BWcomeh}V ze(2k7JgZ=rz%^%85`q6SO+fuHb-S@zG@o{Zm zo|M~7VHZsY=Q0w~_B5Q_YjJF@sh~zSN$k&wB&M`P(GDM+*gTI+?W4$_L)9H=>r6Aw4BvZlPSvIu52YN^?gDhKOsDs6n(ub11K zhQI5c6|m5H+B-QhT)()R#s}6}_uubNnNK4vcjb!3*rnaxQINVg+Y^b46-{f!LM28q`!HK2nI*D(a6NzCC9!EJ@ z&rAHImFR3}BJ&eAZH{wE{j$1)# zdRPyuZ1>L*Z}Jt>9sgQsJXEpLnUngGorX6&TLuo5Xzn4{>-`3V|D zWtD&yQ=8M`zWV$~iBaWy8ae+*8?|Zr%eS`$hXY{{6JUhF|6(wffNR|15jj8oNXRpa z>V8%H?sEVlb^*fhu>xo--HeI>96+8AUvI>h&T|65D_zHE@Pd${mQ;m-bF-eOWOGt{ zf8ggvdH*<{q7%MKoF)^#VvuH-;P24Y(~Gi>ZNE4U#jzjK_Bu<8k|>Ah18L?V=G{9* zFd#SF*izUMl*hDdb_zFyw?R4KGMCai<`%+p?h7ujgj#*w3@x>Y#U`P>8a6VC1{$T~ zTTW!C^TWnUlmy|A?v;9fnlosgmQcQ`SDo>7;uj7is`HlSjj>3?{ZZX=_>NH$yZ1*& zwK2+Rf&Q@|XZ3vP+kZZYsm(*QuYZvr5*Y-9=6^YeB4)-;ZvV_DHFZ5V#8EzfIg^dH zVG9tHb2efqz7i3pN_`~SVYXO@mg|s zSZVorSLy7}khPdC$otIyQoC1YWm@=vZU+coHAgH!@=i zZ8g{Joonep4fuOS!_2v0mGH+*n(;YnR=b5R7EsBu5n+^^D=blZ8zBm4Xz!ff%+#Zg zf-v4y$6;`fu;GH4LYjQZXY_nanDm`JwoUdZg}OZixP|9@oJi89%VstxN{?0$e53KX zas#pF27ij?sox^HR3|YIk=k9Mlj=9`icm$WPqSS5{k0y9a1g6F6|YQ3_f>Ho!uhna z>~G39KngtEz+ua=A>p!IH~Df9ucsqGa#46B_`5WIIvhGJw=nROujggxo3^j1doTcJ zcGezFL((SQgiB76tQVC}k=4D}2CBrv_qO@S+kcm z`WNW1)ipP@LB645UNK};cJRaggRT)Hm90t#!qj@@+Z%a6@+^$qdB_AS~{) z&*asZ-*#c|HHxSz?)&I%Cy!A%9R&fVUdgIjlzKM8 z0Buy|^Iy0Yr5vLkTR9Gz>cEL*vkA*G^~GjSm&(%l`I%J0uB=;33&~L_wmb!&xRaTf zQlkMtL6|074u+nWiAD6@Z!1b6zFg${j}=84JJawzJ?s^R%LCAd)CH&&erGB-W<7Sj zc-_G}n+QB)hjhPzbqxiv{IYk*4Vf3Dn#6iw!H+1DLj0q9I*vZBKb+7NK@u1zZ%WrQ%)*}sS-`0(r$iEfLqKs+H;evG2D98O(QOtSoMvPU;$fxgx?WZ5@o!!lzgNim$X3s^H|Q7jYoDA&^gZ@f|K zORx{d{Y5B%$jmeOUkeoem^%Q9*E(59TkF+3YgjZFcL_O1686e z`IB@T7wMKkVQyq%w|syAY0k7HZ&#Gw+V3pOP9Ys{&{g+fIxTVBW{~FB~p(t5k+^ds)BW*`9c{{ra0lz^dMi6#9PyP)TD`H%AxmeP*6}} zP(&V3j2=)9l2D(Ag-b(8OE*i!yYGj;m(V1`ToCi$3*A1dhZ={T@0N;9>gxsd0!?L2 zL}Y9dIXER~BqFUThF=+pC)T0KEApW+!mOHq4cXRmkcr_Xat0$ZGK^2nKaJB%%b?a9VPNSX?<-e9E>2Dq!ObU8 zDv3b=Gn#ZoyI*+tNN!X~mRrTa#lg+M5&jVwni!ZF7#avF-vleo<0Ivn zV{55(6G!$J&r^>#TR*YYMtpqNj_a)dOpjyU>)t>(s8P^!1+J#W zj=g9DF1Q6!LC>rG=B{FTbKNYo=ky>=2n&4GWMo-tK2mpxOlL~;B+g-chdU3pX2z{7o&54mdlZ-9^e~5>-sCWV z(SJ~`E;=;e;KBJ>wR<2+2$+9A#N@Rv34gWk!_{<9%H53{Fg{#Y{lg2sZXH;oJMEPX z>39GTB%YhH=5*U$>{bav)K-T@BxblZHxe#&(2gAA}A0Jq?`8W7|66}tB84+_uh z_JH@e86>m#-5iAe?GQZPHPAYL^1ZJUK3JyO;UBjaI3U-aYWH}u`~>DEV1B3mn2&-2Q(T78rBj|oW1XJVv*vd+~4kL)!WVy+Pm{gY%b(O zaQap{lo5%^FKm~E4N3?KWtw{7_o`tMj@zJ?L~F!s8Mf2<8?jm>B*vDo+933<_{&xf z>~3Gw6p0;svv)iB5nV7ZBWm0@ya)oZzS(E4#WOUCa^K9~>z-ez?@aN;luZ_WtFgO% z<*e+*j1^o~w#0&kiBz|#kyJ{}DdZRqX{?*Oym?a>`gZxiamaG|pu40KOX%&t+@}3- zgzHOZF4Tli&&!*MqjcivW~T<$(ID^H9uOdrPXrT(L1%EuC<2_{k3|$;zw~ zM;vqN$`Lev;$CHuC|z^3B#PrMd&uUEYLAbil${0NllLPUVs+o})Rn!W2gN|qmHZEX zN9hcz6LUVe!ZZ|@_Pe;hjd&<=D-P>zMYfKb5GtqO0?$Zew`f~5gjv6(8=JO(A3g0C zSo)6gg@yI-6zOkpSCllf2St-D$R*%dqbBM%_#XG6=pnRpDF$2XN{Wx8d+A8oZa}zi zD)3~#SI`QMy))uDu}u7DhFfCnLJgT{`O2BB>3$20wZ3s1C-fdyF0S>5a&yE|-Q~6S z_knmAfl`3G>=n{XR5?Sp5i3!KaSJawy0YkMBc48%YdYGeJI zicgCyDi~FOJz`c9ytZ!iq&^j*90{2nLIcUuk`V$(C+ujLeeS#v9sj_5kuN(sz0_RwL7yKSa!!W2EUGTMltp_P_E*8D6i6w?1 zNri%9U$S5fz(PhtnM(+(*4WYS0FLi*1u!R1KC3d)jO~QY^{l%^55MPVf_$>4Nkg&H zxNP}G9wt{TY$h{jL(-I}P(pkN7tcN#Uh=keC2??($1lw=pN7(7=j5rL2@!uoA1#QI zsgWW?HCxBBJLaz+nkPzFVonB9FUwsC(#pLqSDVz9O1Lq9$Blv5)f6bUtI$qV=7e0T zano|E!HO$v`ZaT6+~6T7>Z5^E2iM~uaF+D8K&nVG70K<4r^guKXVXW*?9m|KOqAC| z)>wN2=%^E1r9kE6ea{-KN~%#IwJkQ(8}o07csD5selS*Ms{Qjv-!$q^`$cw-Lwb{Y z&!lRZ14Ruh>ko)Vdqd)>NX2+*-8vqTIe6BJ+t|I@8pVKhc=Ck|20?7P>mSuu-eCDb zEyX4nfcM{oo%jZh74{dQvK#cF+@JBWZ`g)n;8`ViX#}5M? zwQ+`$TIoVovw2XBI_Z6SqERKztR6g8^XoYl!(8QoM=AYn=YdHn;qUdKDV54{sq~ndTM_m9@X0 zQ$cTP1KRQ!b?AB+1j{<-D4IGMwb#9%M6s&{cWG`I{VF3sZ?eGZoNoEMjj+Hm6Qh!4 z0!3MwZe9p#=)KkhG03GJLA^dgth-%ONEe2Fe$oqdeTyztxSTDdf#U}cP}|jJ%sbep z@X`)!+anCAj(8H8NRX-O+=RpQLhvu^cV_&A2+$ZZI-X(i5=TAb)E2ty(*APs(Y+VA0Ddfx%C6vW1}e?$LYcm!#8w(X!l$X9rqWGjrtV!FL*z zyF{2rDhX#|PI(#TIc&wcZx5Gd+@T$#JfuZXWyJ4S+K+ux0v13KMbnp2y^EH%w~JC8 zw7Xn1c5?rU;f21fB93L6!tgt447DQ)hiZh5G+u`rvW#}$?)euzCACRmh8dRlBZf%u z;*cApCD0P)rx6sA`Vc~*BNiJbOSCqd?v(P79*ZI>B!Y78$T}1Hdg-1qLD2E zM3(&n0}-x020`4=0A!&wD*P~MNMzYJf6RuAafT5W33^mHOl4BpNQ|5!BUHxX4F9k* zvdAg1JJXLQ4j!->Nu*6O@Yu>};-q3-%PLQAf-8;e(JH2kXqK%cSr<9=L~gPP2vjwa zG{|dHPL0N+Vtvkhot=Hn4-$SYlVaf)%RE2Y!lcahplJDqBptnKG5GeoNvx33 zjd2^i(CAd35K_*Ftg*_uWS6ZLYA?=jJjH=b4ROK=>7401#|x**Ly~(M;>pB;nDu0j zcO+zDS3fiE+M&X``d8)_#E-EheE3Bo3%WCHct^|9u0$kjH zo&&0Z=_<>rZ|_B_H~6xRaQuo*u5*s|^GofN6z(|+3WG(1HmWYO6sqo?u0(UxJ$2TD zuz}-B#BgaF#TZ zEHZ9J8!cghEICxG9Z$+=R?;PHr#Uoi5>Cp9nohgVO4KF(p3&UXK5$^pRJ&-2m7cuo zGaE5x$3xQC;sjR2gLyoTxi8z)E{m$!bl)kdSG7y3(KoD@ViKwSTdiL7og9YOgs5=W z#lZODB324@#rZdmPo=wsvw(j4>~kWzv3UNquZTZ-SM((CneFpWqnFC*VtZlI7+rK) z9WCio<{Zb#5w>xFva0J3QMZ($+BeMF?zCko!IdG5Gz{$28sZ*GhGM^Y5r-d56Q__8 z_nM67c)PkEpe>OgKDuBd8)T?@B6#ROPwRNIo&~n%H|d#T4@mX#d=Wygz#4kz&cx34 zeWFU{k!Eh6{j;Yv73A2==kWTb-5?p#(ziiT=Zan|t~#tshR>`#xb>$)C6zs}6ZXBZj=LUz|nnQ(f*3 z{s30`r}VHNGlrKTTp&qHQMQXm!h{`@d>$~?D z=F7UU5NbKMr0nxTzqmyoo74Etr+2eosvI15sI?!4jb{Nr$3(i@asx@fR?2mj86F{v zE@{AYNGqHm^?y8f)T{J%Np>Q%x0deFjSixy!uJ zxvy$UX= zkJcuCl(64-#C0 zrzW(z`z|ukG0}-eP$l>oY6)v&m)VlNPLOE0OB5-+<*<~*+xPgl5tA23U`!uD_CdzR zB^Xpk{v6g$d=OYz2u$pSAttwlp8X4Ly&79l7Eezded!REW*(Uj}9-S4o9tEu9Q3Bd%aoruL-4~O zg9@_}ze5qF)tKJEEW^YPI+}m6JQF_nE82s`tA2T<`-Ad>2K;>V^Uq0tX!7~UsaAc? z)UW+cWWfB`BmKoRFxmJ4*G+k`vWKYM2kSWgYVQS2Y|Sj>ry4+h`5k+^==Q1Ni6i3_ zd6(Z8Nf3;?7ChtwMVt^S`2#ec9KU^-b3N?w59Emf zWDb;{ebaMrx_e)TK9M{*KafGpF2wdxCVoi`k&)s6itMZ zi&-p}%$yW*j#N^)?cnq@YxW5q7{8abOgXqUP5K}5K>-;xmA|_4#PmqZ!cm_jm!6-AEHozuBEv89U|V2q_XFe z^oBT8l%FX14%XTq>jb(9(bhkm#Ac269m?{tUr6Qx^;5zgeK~*e{ci#@5})A}Ve!0= zJLvi9Tz{C-Dnip1Nm+WqIrhtktzFX<;%>6}bE?u=$5aC|+MUY@px~kU_NzgFz7ZLa1b=_$p{F!iOPoDJD21uF-}KZQGS^ zWP2783iDFxrbs*G#LimE8|`AKg{@kn>gO}aB;n*W@lSU5xI z52o6#K!Bq9hFyl@d$$0*G*4}V=VoC=468)SzC`>6J6>VY$uHNfsH)jO7l}+2=K-XbTLbi&~#a9EQ&D@xVSjio+tWn?&1 z73`VSvc&Nek7aAv5C-yWNK4=~>p2(lpqu^q$}g1+G0$hL!ow=dzcXW?COZ?;7b)G7 zqz%|S!;Ct`nmR{T_hH|XMjm?(h8K!vpJbhw_h4L@)$9*9ZU?rFzj|~l{(8H$*X|>e zbYYN$?W%SauLxQM$fL%fHtHl*uMiX2?$hQrf!?YU0hbXYvA$vx|xL@cA_ zxgoWK{z}l^5dmBRT#oITA+AWnow?*ge2pkK;qQ%vI;ITKbD@ne2}rAne&}!`#LfX` zih>EwQQP5oVJE{Q&_~BgiAch4sXqju6qT9%(}D&kF`{+~=iWg>58|!<eO zShC>eQ85aITi;L-AO?&y+$1)9rzG2R^%@`^B^kQhD+DMZN8^Z6bdSlHKqKLK*I|-B9$x81Cub zaP)%j?7}`{^@UvD_&$pa6%j|~9U5juqDGitNJiSRM-s%Kmf%p)GHcLFRcXZnhji42 zcyO3{c@BEW}YGiV)#MfQp0v7h!(Zc!{E%ADKXY8{h&V@nbS8P!qB z7I*1vBv6Hg|X^CY7v*o+I7ia(;jrrEo4h*|j2MSRg1Vxn*Q z>0>15GKP4_FRz*7m?<>BAt3JKs+n17QM8_7ghIl8e*cjM5dpx9rm(+nDoIAPAU@2#7l1cLBQ%= zQ>xFLBA~9?OR=>8n*yg8yBC)3k#Y7M*fmyFGE$rkYoxs~ewlS`EeMgls(c60@l9K5 z9FoH?%8}`aaiM2%?UUMyPkRa&c(aE^lqbD4J!)JTcR;e*h`k>_`0G677ZUe14s!l% zpi}_^p_2$ceaVRN>L%1Zu+5AGhiH|uf7R3!x+~Mec|@EqDQ>XQ=5bc&{0Dq|%g5X{ zRE0Sjp~Xwo<6f$Aha-3~;-2z* zg(EyeFcJsT1tqs9q*$?(CQMHBt4s~D=7bz^@BY9PnrbSIq}5pOz*n zv}1kus%6jinPABxhD2vhoH9nl6+x>oN2n%?NoEP%)T9|X0AbCuDzv6WD)ifekb%ga zCV?YNhzXW?DAIxrK9^%)Xo?(0%wTNVFapp?Il;sdf31tFnilfuSj6&a$9n)%b)s5X z$#~AMeWj~drAt~jWOBff@pRm8a}(rnFXPS;WDOXt!{s)NEU-!Dw^JsID+i=~p*ULG zM0_L{o_vY(7I2e)kFG;1&hdP^Du~mgm^D_&V3gp`>wX|WYe>7R2^I;d4el0aAW!I% zALbn+&bJ2o-~`4p=e>W*|LG^#l=dG)l&go;Q0jxrE`a(@?jyu*3LohYZwIWY2iM(m z;YY3=xZl&+v>=~zrOA8;n9_NF84b3p!a5a5mh-RXpGI&M|ZiS4A$__6PBi5P1TLyEEh7DGqn*j7Yb^ z7M+lJ8g+qppKDN!O^9Ze7h^7yl25!Yq3?3AgqJ1F@#Ex=W%M|*cW?zpM+(xB0^2n4 z_15sQWF~(Xg^@;OBDXAbx1j+uh)uH{Qy_;Zy03(E^y9=W`uek*>H95Jg!GYJq~}vDZjB*k-L=yZ?hL)XvEPULtM~9N8y2RpzsJj@j(eK z>ln-7eDlUSlnSST`7F(eug`9}x}dT6 z`lAJ)+WgUPY+%r=;u?J069Zf*v8PfDA)*OGG3#%W(cBIcf2T`)Ve~G4G6L&$%&_AW zmn$QZz_E}noACm$-{eSN`4H^k`lRe8-VR6+!WobC87y#2*VyXRPH}{V9pMQrI-L7d z8n4`^<}V&Kc4-OzWzSk1o3rXE$?GJ*m~DqMS$t&D_JGl80Bv`b=62f&o^Z$bLdL0cQdx76HK9c!Rn z@e5{Sc`xMYQf5kXTgEnhPE$i7N$Au2re11k|3J5oDLr)949np(`F z)sAbmF_+QBF{A>MhT%(A%M!@BWj~#u7K2o@|Km2wrJfKew0UIcx`r3~D*n8H*;U5) zSR{@5hqH;GJa(ut92-#B1}Y1siywsa3u!K5JxgkG*UzDC>X4cXFt;xvzCwu=+R=(Y zR-?7~EuqT?R2vP|tO3*|4$0*w6st%VtYlaVJ;EmJnO67 z7;=B6v0Y!K9?X3C`0L>diyoB^m^tJ(Gvs5f9OMfmr+RBUsYNZvF#t43BDlea?zV;9Bte{&#Zgk*NrRXdI~{x3!CAGlDnme3_BUF7h=9y=q_5IPuKNXN z;&$fL^BwRg*W;3}|I*EweVYuw1_}a_0r@{(F#cyZr@XbRo4Lb38+z2X0O%qZg2BQq zcXhjcCi|g1#-!qoJ`^dmu*E|P?6+YEU1b}A=3!F^5{!QM`GfF8{o$lJxW8LlQz4tN zKX}M(x%-B=@UivY(yd9Ck4ul#go|puVsg-@^QX{NpitMUMmljo zHZewMFH?yoJ|~eDQSG{RsigS0iYl(QYOQ$VE_P9X2rs-G$L>RQhToVp2L_H!0M0hE zHRaYmaA?G6tnNeYV#LaIc{h+IfE7B(F&QivnG0r{eg8+6cWyoY3$nvyN12M-gZ%2R z))_OuL8A`gYF2JAsN^BrVjv#TTn278Jt+y(k@UAroD0^X0j5LC>;+ymt2Do+00pMK zv!w+{Hw6xlC+5->6K`p%<1bJ@u@(u+WV~3){4Z{BD6(B4^dba@0qUAjt0U(e4_T)! z#}lNKH;=192nK!tR8G*@4>o3eC!{OLZsdDVZ2tprFPs}xeo9U##ZzC1ygcy#+pq91 zm)hO^(mNpk2FQ=Uo9=%o$h#OjIhmV@db^qb+a2_OROQW;CS`%b7y@mv3f}}P)iDN2 z<{St*Jv5c6)!?D%+Y_x_bX9@m@+!Ik)1lvXr6RdvA%=&K@_dO1ECl$=f&4Q+-vtk-D9_0nUGe@lAO4gEYTuE zp=DKn;Ta|2UPTiwAHZzQYih(FWDiKeY7L;_W95$)6wn@nu)BE{<0GmAwE509b$ND`^?kiudV(x6n{A2!M$GBQPl1ggn7AbLPjgdc zqJETQ@m;J}1;l&32)M}P)e{kW1t|H^C5A8svRcVE(u1Z@YtHgLHXVMm<~X!=*0U`F z!~3n3E_ zp1AGmAus4jCB=+Wg^|{~h<(@CB}a|bg1litrR{O21^)h4K0*g3&^Uuh?Xr>7DgW}W zP<6SF%xQ}~gh|d%wJMWwp8r^4`TtP%PC=qX(UxG#K-4l_SKba>o;>0>T_t|Uhl}bn4QxV09ksoUwt8E3fPG;<@x{ZWUr`1(g zhm`3i4v7X;F=gtaDsvZ!G5L;(7u5<)*LU7{Ym1fj`R&aH$qjGDi7bDgb*>8%cA{MI zeQ+5`$`oC+<9n5`3pdKv3ys|0m3YDAM!Kz&EvST3QeK?9iS%(Gc?-5 z^4EBQL4S9LBS)^yX$oV@tU6*Eh;V!u{h{yu*7wqzpU*L=FwqA2G+?96gY>S|c+jbG zZT+=Nrb*Gi78jYaf#*CBLfs4gH@;oy&wpbe_m?3)ij(g&CoONP8J{-u?MjmnvMO{-VfcvT3ApwAL#?Xi$uW2Ifa z4r+A;)zr}u=z!(q98k_bs#^F2ZCw`>$=I`hi66Lt=(yS1%^O78Q>g2zsKGG!Xt`Qw zuu@?Lwsldh4DxBwd34f(_b1ul%|$P$Y2cj|5JK}_S16iK)e}di;vq@L>%|`<@X!)w zTLa)Jd#uq9J$(<>ZNFueSW|)~6bxB0U({n8q!$ISW0vfl42=A+-$|5V;}KH|J(c}| zpm;#buYq4@9}MPGJWB;HVWcBq5f6bUb&u}EDz=+IxOYh+KVZgu5I=Bf^>bb%Lm@(t zLyI1<&&m$?2Gh>PtCH;EXJ_*A8`Uw}+?3Jv?lzSVoYC4(O#KDyM2 zb!v`5uphpI9p;&4*O2wF2urjHSQZ`2AXYr|U7uhO3i)0v_zWryLdhp1A!v@D-ee!d zg1N5+OTQCWa%u2mh6G{b@lN7hH{+fs=WvV^2kEQCW8@RDSAciMBl>3>xXY8X>m9ob zggNqOE41)q)XAgzZ+vNkk2M^Gg1)HYpr@Y{8Bm8~6dU5LDE-ZY=xyB$R$svG(=4Aw z%=QMv`=o<2=FT%cYTX`=odVv)E92(F|6qOcA0h7taU}TaS0tzO+rGx|{~7ZBmq16% z@SmTbER~D@NKn2*Qf##(DS+=H0sACqiC4upa*P=`2R z{UzQ^wwLSohJZu=BdgIsc8spbu|PT2F%EXL#Y?wZ{GQEKUv9N&e`upS+7S@NC6~C7 zU}`?iIAHyW>=RA{>N`yB7~-F4dW*Ky^{0h3IY2fcFSCsDJ;l(%a2x(z#0^?M%orw6 z3qz;QMm7QCrV;4@`PR?UVQ5bVWx!`+Gy}9kq-fusYHPaGoPsNch7YyIS(e-+aL{GM zIiHAjs2@2*LhjI5%NYFz6KHKN9XcC4*kHscrP^$1&Y7cR%}j!F8M2Sw(M!xKc|b?U zyiVsleV4H>_+E2NKC@f|9B(Em1uc8QY`evdB3W7^?|l)2^#BHVDru>GHswM4q`V+) zm`T@){xm`%;UT67qsWOY$&pHiOSfuinBorb%+?EDxvxi z=79MK^BFv+h?3ISmy}~ct<*$s?LJPfNq2Q=jKxx^7NQ)VJS_%RSWU z<0Rl`j;6eB8~Iqf36O}FPOpd>-VlklD^d79r07{SGParoA^Z3hy9Y?<4fseiSd7&O z`*3<1#1{Kmb%(@8?Ur@-c5QUx4gOwa@taRu_- zJN=d6r2g_2LfWu_M~FD8@E01X1tVWwlU zyy?iJao5IJ7F9vWbViJ6H>oCW zv#N|1ozV-pH;!6nJ$sOlSZ@>Geid((-oV1G(q1nj!~PbDE^6CCIH{uHD1rVpoKE6| zmTKQ_;Bm72hTSBH#*^+s0CC`JcZ~$j^S60(B~I+N_A2fs?xfs)Gp6HZcBHxjF#Q`q zsOJaff1YaN>l!`SU+1Za-xgcC|36dxpFyff6T(Y*X^D?4Z8AezR}eJ;ez{iSA8{rTIRA$!6xKbhRNV9YF+{$|UYg(j{d$h?DRV$luU+6!m63YS_@;hceAX!_O2wi}@?{x4v*;F$ zT{Dqe@kSlJQvATlyD@cgy8<%XHeWfj`>>kP_q2&GQ!pIzh_%`HFC%Ey6yt5PGoEd% zM2}YsSb+Z^cd~JO@~xhLxS)189$IriA)3u08i()^R~IoA}U2Dm`)m(4!LGCp?N4B`OsnbE2qC5MSqP->&1863tg^TJI|Vg1LKG z#$e8mUhiW6qOgZI&~EpJl9uIL7u4qH#_AL3%nte7F5%eJ-zSn8$I)Vg`8&_+Q#@Tu zM6$)gt0UuPmy4xa>HyEmi%m%&OQDBywRS8_`Q2L-zkYNB9wKBt?eUzy7hL7NYp)i; zl(2Zwd~_s9rD3jPO$(Qv@W`yXGJD|A931qIbb)0+Ua_Nw){g07D9WfKmYa)I1)gV9 zh$&s~dzz@GzE_{46|J`IoPm$wUsbKqjde@r^-xh_4&^yq29KCRTSk6Q2gcoy9rLi) z0DlruF4p$`b1rm4Opnd2K6qD7qA7xbjnO2l>jzIDnWKs&Y}Ex!p=}t1Ju-+7OB!um zk}Uh3C?-+xd2IcF2vM)^drdp4<$1NY^gr9;%*OOGH(i`;us7x6qiE*oPM4G1y|YK8 z{I1b#^Rtu8tgz6knE83|w5^?t=rF?N0XBe5Fe95V-}}^t_DjDf5GM>th)cw`<3rdP4&47 zn`wy~v8&r!)Mu`OnSaMaPg)c%omPIcb_I?Fcq;2NR<}r%9FDF<*mbp_x%8^bPs7n6 zXk+y#+BtjMK&4L^FaL3_ZxS_$;NVy-YD761FgzTG0Gn|SfkD$3Hg`aia1CsfN1jPw zWYpb;pj+gTHbv%Y{P72Y2sxrz^e{$k{5f2LTfQhPw=TbnvzZHbxYkV-M!lJC9=9hO zdN&O)4*k)N6_dvD04_8AQWfUIwfEe#W@n{!70Vo&&65q|&a5rkLR<01uKi{kcO4Ke zYZp)rBcB=C2os%63#PlP7z#H>ns=K&a4%HOpD(t=)I8H1e>1G62(2#W{WJvT`3PK? zpyp3vh<^HJMrE5f2%eG3e{KeM41Q zfz*2d^?Eu5sF7X@z@zA3o83CJlRA2sxZljp71eO5g?#cpR-jDPw!Cruk{qDlu|E3h zLWZZltc>f?vqxLBj^K~+#>=!sNYf4iEfS(uIR1J!-_(1v9=!M`~=V2Ji2Zuu@gb-1nA0uPM}Krs0Yw88IiP3%lTWmiV9-GqJc za%P>|M_%%BUe$;T58 z!6#$gY5iX1iZO|?^SMA3%ILbLzDb(^z>S1P{a(e;{)7V^_Gk4M&eFqHHn!gjYrJZ# z9Wd~UcG!e8)K*2noP1#2C>h0UFR+6QGCw)n`>5cuTz27t+?j#}Zh~ov?8*WRr*~?1 z$->JS80VHa+nF=dR=yILO`zG8STi*LX4yjQnQhiJL6Th2SI_g9<0~2GmQ)sgkC@^T zxS@>hPk_8qBglt!U!VLRg`S>OELznll#l+QD$&v*v~cw3A*_JB{ReC0W07n%Z0Oew zF~}CVQ)jBJ;)N^cP+7i0Jc1z((1QCshtpv)d2Q^<9q2Yhr2Sd6(^1JdHP z@S-^Szd6&A`<`>RGlgriAI=`y!q2VL*zoPJvx%5L+9w}xfLVBlIIA;o7N50~my7Ob zf6q3jI$Yknu-_oIz@EiO1&K{Gif6@%R)L++wF=Z*{Y_3tNJm_1|H> zP-7m95gD>@GKZNDf!ov-!$xKXoxeeD7To#xK+P7_c&hFWIDZnhmtOs*+)9=pr~jB~JLD5>j7Hvh?2@Uh;SC(jJ_*|b51`g_%IrRw!@RB zbH;|u$Q+9vc3v^E_)h4Y-xZTc;Znxj9f$Ph3*^@mA+R`4?5n4NIP^|>9%R`Qe7HoS zfASvG9Loyi3a_9ryQ&b{f;M&0FzLPL&VH;;qcuX#u#HS@nTIVBPSmrsFrzA)7D9D1 za7dOA*GRL46>|j*3?!!NKGOskvF{{B;*M<|-eNFx~88;##qC*Sqi9UOsaSF`$(K-Y`b8N8A}0vKcwr0m1JLE&8u zm8&90E+9BjNEMQ_4cW9VP2lN`r#yB&FVbcnndWal1J#OhW*hmjtp}NND@hGrM1f_4 z0LdNOT*bI+dTb4REr+}h7xj(*L99FK=p_pvG;hTqsza=tqQ^{lTexn+{rfo#oeG>t zjNiG3-acdUs@rC_T_)>k( zp=l`@JyFy-8+COVA1Rba3a03RB*}!c`ab1F-JnG#-qZU4#7y9_3+0|TE&<72knv6E zh_nWRp0+Hpxvap3Oy;fjksK9c2PwMETYGYYuN6iU&2vGp`rsqGWtno6~xz z3na$V|B`~&!f>sbAg!>KO&;wOQv)5N6w##7Qt8eXoAbtQ&k5bjb24ciA13M4T_q|6DI=B+hFBgy@~1T-a17BC^_+>r?a^LKriOgE5!a1-$| zepG*tNMDSxr{a0qC>N_MS8bF7pw1C=~$o zg;xYgstd5y`{}{;p{eu0*3_}q=*)A9{na8_^(IgN`0VvMr>qL$h(LVR|A>l0Rjom92H}o=T31T$ZdsuxsrCL*^xz9 zmwJHp6VKgImpDstf$V|!T?i{X1ZH{gU$)uRJrEt?W|2@AF(32E*GRK4=969LR)t65 z_=n-<0sdLU5}0k2r^@u?2l`O|m%Z{BQT6MfuAtWy-SWu3O0OOh3>xbeR?;`p8BY1pGF(Ma;xhX7lc$MK^Y$3by&KT`i{vYvTj zvwU;g9(myK{fAA)OJ&#Z=koadnBxf(J|T^7o+ zlvNK5;+V|DqDR{M4q!}@sATfS4mx?5cL0aDaA02uG;1>`Ev=7Z?W@M@OtRM0XtHWU zQ5mOPkvX2>=kHb2PUH-UEA#%t?)7>o}Y0oXkBlrgE4k z)5I>M!={rLjF?Yd{yxv6Or{J=!QxLjslhOrCB}Ek%~_i`yfSQFw8t~hsR?HXEbxKTypHC#&e)<1(>3cv*Ar7{>gMfgKW$jAuB77_q0deyin0@J)$n!;;>r7*bIN| z3po4|4RD8d4iO|;o}*A{795&*_QN2$u~t68c2qF06X% zChFOc)-PBa*^)v%kP=wG2E0}C8wQ!1T%1A+Hw7N1VjHX`9B0n*YyR@nxZOP0Z#pf7 zGI_o|cQv|R>1x9HI_OrnM4spIKItsZ%0z#JJ_^?;^^)I_JKmX(A2KA(7+J9A2o|_u zCp$vO7{gVX2V{vIEii+h^r z4Jo=RB-WET02Mi88^f`1nd3NC=^PHc31R*Ie5Myak4s^(1|kX)?Xh(**s2jBm0oc--WdAuCE=l4chdq7LuZ zziapBxKy&FbXj{ zM`(6!>cDB^$9#%UlVl5L6Hg5}G;CcZ-hi!J7L_!x!MUMwNbPu)XE(Y6!uVc{2`G6o zXO=tysDMUVnC699?SpIb;Dy;=vLIfaJEtvi&yNXu|PN#4uYQ^-p<_TX&OfZwVF_dh9Hkw?p3@wE2U@J1X4)bF z18Z>`9R>syCQ3XtzL0eu(UPc}MZzX2u=k$@PPQ3If@~SJ6H>4PS&)NTW^5D^sO7e7 z@2G(Ol&qk*Eg``Rwp3W)5gkGKj1VjJ7yq=HHz1lJ-b9W%_3i=+_vDp0fR`_}xAnpZ zcp4(T4)>~TIu9g=GF5E#Wxkyq(UgCOg!ezvYk4zI%JFdUK_Or`I1xZ{1mfiC5U#f2 zG}tQEpAATsx6!n3z5gyP{vVUY#*PN2&QAXWbMhaQeaivjr`9iXa`a0Wv;V)BB>!ui z@P7;^7P7W;G7&ehHFh#Lurg70xBoB8uB=}Rr3HCpAKHuMD&&xjOjvoZw00O1SOI1t z-~f1W)Mo=HV}{|)XhujKt996eo`m?YIrG=cSjKEm8)#rchn6vpm&Z=-nKqslK40%I zz}%oz2J%rWa(zt^%^@V1f`174=px!gCrStk5rh@b}H8?rPQIrW?<7Rk%9=SSL5iRaj+iB@M<13DExZ97lGA4l%NdFD;>rwCd=0pzK#r$(rrkr8_>x1n zHIjTkdlWZ4v?CCP%SA0FlY{4Y7i*XN4CA_<_(z?8I0Y)btw?5Azyj_IL}Nfdu$9Q@Aw>#82Rr^&QAB7TK_d1^O+=??&R7p5-=SXvu2y_X)9dp2wo zMPugkzi3R{fiU-kegRwf3s~m=1Hk^@SXFX1aQ<(wD(%Rv%Oii&(x6JJ@ShB}F_3Nm zu+4I03{Tt2sb+Iz<2P#7d6%zW$Y3S_F(^X ztg)JSijlhDE>C4ob>&GV7e?6!jq6w?eIBb`H}hPkl9_Z%C@XJawCfyHQLtC|sOu)p z!lPlal+2}fDc1JI|b%be`vK|%)}g|P+mNeGkZuVk`SB%78(hPr3!x>#v=@KU;F!@Xvm327Gwu{ zi|#_s|AO;6G4tMAB0^8t5Lr*SwZ8hK8y?ZgMlI_%+7MKP#`NT@dwnMu39`5TnGOWtNaoxe)n&Eq0@RB z&l@(v*PqMF;tq@);fUf!!7z#XY6aD}=O?Afh&K7gC~8y6@SXpTzW-^TnkIjYwDv2v z`9lBzK=Qu_<$oEGs6(i0|NeCY4*DTv&wmzt43mbn-sIQi8(bsBgufoZpBW+&Slrwp z3U>e~nSgP1s?!X|OXg3e=e5_KR!$dSuEOvadvKc~^nNiO-2s})gH*Y@ z2un|8x|+&Ex}}c@OU_H;D^&SQMfqDkUQfu%(q@g-D-6p+hL7^T6z^vWp4jaMrq4+1 zljI<{kJ`Y^TOEQErq50+UoT#Y0n)cPi*Mzg+-ED6lgTUNx3bMA6W;e`Xpg*S&;Eek z`>mSgbIrsp+iN)@{mH<}_^r!l6`XI0>i2f2FZmGPe$L`i zGp?qWWl<6tYLDgkXTB5%h-5ISm6zg~SWRV-2}y3c3vZcX$8tp4f=ZT7)t6Xk%#*9gx*Xh-3pU@}93MV8=LYF*AtHlPBF*Jf9a(D) zRXnDZ+h(gdv<_qFLinlsf-O38=ttJJtH>htZL_+=1TQ%`>{908_VXb4OZ8d(zNy@C ze{C8jeF#bmzZ#+Cpe!bZRJ2nfuIHvCRCAjIrUXWTYx`d9yL=3t2_{iQMK0}PkvZ1B zYJQ$gKkEi#L4j#`+ptSY1dN#|$VIC9Q(=~g9HWVD;g)&WzB#D~5|#Ux>v%-0Nzrm= z-r_$5Jgd=!#4>0o)>R6k?3g(ocQc%(tHNGKv&KJGE3I=;GfsA+6BZNdbqFWUR`aIk z`Dx<|;J98!xL>ecP$lz!aA7J|h%g%_Te}>2)^R-0WU~tm=6Eiq+t;>`oU~EwwX~Ql zi{_i}kNEdHF~}}IaZ(FR=bI5N?Nbp{0y_tnomD~lJOwKhmzLtCFju!qf>(EZJS*8c z%F<0J*;^!4dSLcU21M5*nmIAyAtt~l?eG|^3)+sMnU>u4kOSRWpnkgNFyjd3t4!+03k}R_0AeRun3)+eHt-a3$uW zj;OX)nV5{@5`TOMMfzVBi@r#nsuHvin-t4viBuW=D}Yk4svO^;lC+4FEg+#CQksTw zew#{J-altF3E2Cwo2$OXXqsFV-vq4NIn!e{#DE>A)p&MeMrg?bCN|5InnVOfdvhmX zK-D0wqJ&4Rn@TbuTTJ)OWSe29V@@V+NxyGdwSa{XI0FR{%5;{K7w z_7I`5hoRkAGnz`@Cf)G>W0fmt{!$&~h$3O}_0OV1W#mI}V#hG@CEh^a!JpJzPx3}( zOY!@(6@zEzx92FIT2e3`Gv&9FVKqNodUM&BiVnwg)ku`m#+3`?0aguoGp$=)|3gz< z(uB&^*OxFcB0Vc5Lb1nbUMIpoh9T-A%uqS8!=+8E++~gQ<=ipHdgaJxEpI{=;!Lps z)sm#r!vM#D*tsmxgGH@sj8+HJxFsgCmDt=-VR}+c4kq4>*?|Cq2}(Mxrpno(5IbrN z*OU?Rx0VZus~Llbl*h6^d?`??X{VjWMz~n!z&nil%4#T@=-tju{NduR{#$HINm&}3 z93D8LPDjh{hWq~+%M02mI(_Wa7!L&Bj{wQ7(lhfN!Ns!tq zt{zuKiiEHw#tC}5WaOxw%6nE~xFiM!8pFbTZK)lzg2QTN!`{=-?(ml=4OYB|mJE48 z2I~BoA)pcpDsI;%Ej%Zdj8?@gG9=&e_oj(_qEdUNY8W4p*&Al}LvNvVew5geO*?n7 ze2-FyGY44+=|H=%iSP(;w@|H_h&<0^FP(f@{s=ac^+mqMm2l^MRoMXp^cj07LEmtS zF`=ml*|``-=Tq4w&654?abkOvA_4j?)P1(e{JKr(IgU@}^k22VY1-tgP3>lWq>bCn zCJ)J;lPIgz6YctIIH^+z3)mF&+nlM;(%MCnP@qgX_u3BPCdxT^h?NgNBcjKvMdcq3 zL|cD1R8?f7%idGGpSI;pt%ve#C}4SY_f=J!68Sr4t{M4XFAG5_u4wR1T3S*|e$O1vP;gV#JZG=4(pMY&Rr27TrL#MFg z^uVS&HJ-|cZdITfjqwQs#l7mTc-CJ@K=*?FNS!F?#Kh{)(pc-)$8Ug~Xs z(u;I#+2kCDU$Ls-L|m=#$Nc*zDL~~(%rEOyQkzjpqnk@G(jujoP7e=SG~d)IkCu}7 zT?IEvOh$~TCSE%I4#C4fWJIS_Qzh>dG_E|ZLQuu1I`?TU{LRy_>ZsErv*!kzPyPia z4>Q#)zMK+mW(4iCcYIa(yCd{iK2diDaOQKU#{ zXUr!h8FNB59hcrgL^hD>{&D1lk1rq(D$*jTfpF%~=MAN|BY$EEBK$2)HNBksY9q37 zFW?$zfC*#==?zqLQK?rex0Uh4O}6MOCzrm2eV#tVne5&# ze;lP%j!1ci%qun9F6pI-r1OQ+v)?t*(s&x+s&?^eTVllIF?f}BH4MX5_|9x zizX)YUXA`I1;HnVb-OTKb}=cDJ0A4D4ukzJ;2UE94+p`&A_&35!y#E)>oXy!d?lxUwDpL_+v8-3-H_PS<`BeA>fGoV3dA<Kzb*ELa?RL>`RDLs3FHzLPqsY{mP6Txsh96$brFY&FSepEJLhcb$|s(RZZAFXOzwb*LmF>X zMBAeEd4W7#U?wZ~TUmfT`B*^boH)3jUX?v#n&IjwGheUeO+#5%?B=X#NDmG>WB9IZ z3TjSsZ*WYCxGSV-(Oh7%z4M>Tq=66z17*o%Lep+TYxV>hnA5ta)c~#9Jv0rQR_{v2 z$;FfjBc1}i@6e4)43u&e&G$LWqY7?&$ailqw5;~P7#dCmjk%5xY}23!&YRD4yhotB z#+K30nbXd^GIXCN605d~5F6Tk=AuoEUTu9V$v_~Geudz8<|=L=RJDvLw8 zZjnE1~l;MF9*^LwwnRf59ko1Z%~}Cm|sR|9;`nUwhH}7 z=osKtbBWfmI?cK@ox@}1fuA>(E?;n1Pc9-|7U8QhD{XBS-2?+r)x#GrDo6V`3vQo@ zHqdy6Z$FUUNHm6hziutu!3;R>w|_Rww^I0>yvT3^X9zl#iBp&6>F;K>B+D1~9>;#Ki^ufWae;4IqMo z68HhC=p}3u{KqEgnG6&(D%Go8C|rUyi}GhR*9k5E3`15`HD60rxi&2?+phm=k}QLN zcwS^p6X@dxPu}*@?DVGJvmds&ou2E+!pL_DInP9KFLSY0t8U@R(xRv3xjePGqe8jd zfjv=hDW1s5INTbMjgWDzP8?`uPwrf^clV)jZ*uK!g)M&lulHm#86{k0QoIbv1aDzbl^+@tJkM_4Z#rC>n*T>Z+Mo*02F)gkV zmzxy5bWLj-9-bIKLAZAGPv|JU3KCuKWE7*~_f4sy!k#m^{>tuYU4D{~=@5;B-}?mj zTozvNqjtQi2HQE^UwMW0|7C=sfLjjL><6SNrrB1g2{!tckCUK*18oww=tYaRR45ks z9?TyOs}V7}SGIn(c{l?3%Ii$XVyG%?s#A!Z9FUx3YclWqw+yex(ME`DF`l@D)ner` zC;x>?lS1b7t*^9=sIjmc`DSb-Y!z+U-R{@Cj%E$sMBf%IrD^odpUn_rB18(QfRM+e zc^o_b4obS+Yn*Wd_ihB0Hkqch!l)rB1k>s(AIw*((%igg5s#@sJrZ*6?cdZLruTj) zAXT{rCrehG-%PM?6(#a8Uby~`4@bC_Fulg03N`$Eetbf@sR9F8EW=x?vC|}rCTpSW z2p^3thOHIq6(20Hnk}gFa=z7oQ)!@tTxLS-}=3*vT-xf<;W>l%CjuX}Y4?Wwa z8r=&?GqRWzkPo^1UdKOB(vS+HZuGG3HZ;}fu5g_P+U|DENWc2S^Rg}pU&Fs1{N0Fi z&CQl`=t{Of#V2aAgPiZdhfAT=6b`_1Rr!NDz~g4CmV0vE`SSbmKED$9)^SR8ivB&&hE0gxfc#!BdBN11w2=pPy<()Ow~S_5kHkW7 z4g#!*Q3YY1M-*A6LldBK*6TR(Y0kmlbahFiOBXbyzLHI|$iacT!9{Hh^z^}ojc-07 zVZ7j3-)A~|I6-e};%Y7I@K=41=E+TqO;y4RBLf#N2m8VEE(x|SxC%aBFx;KW%SUy#)mPMfz*E?E;CcEAzTj) z967iRogs5>#WaxwHt z%Y_fJr8zD!l3P22s6Q zQSOjQ4L>C$9K>Cx61EaoD7}V_i@jY?eg)|&yqm@%uCsK2kM=6*p-Hg9o6qE!4=Fh*CR<&^B^*!*r;UsrpE> z^C~_Wz9siJZ}5WWQ2`v0k*UaNht$~_d{k!3m-YLZZ6HNM97P~QBnuOgC&)>M16edn z6A=W(f0e(1eh|iFcNEc+e~2yLnSMm}{;K%I{y>K6A=yT}5~Fh<&MUs!<#+WAAV>+h zy{uq49&u3q1n#K4=D0bl*}aUMXY}cFBKoP9@*;>!^`W8Ov zCG+jas(j<&f$dP-Y8S%MpE((*X%8<_T-^_cKk5R*3$6aTU zLebYxuf)N^%c-5sJfa;YKjrCDBSIEpIWTt(wIFS$>y{Le@pbrZrN|3Q#rAE^KbRpG zhQgm1&B;;#Or<|ae#&HlgUh+;v1rIN>ze59+1&v_G=a)kof1AER7AlO&XH~5p$OGH zupJ#ALsA3y7V7|mJ@(E%eHEr7CuUg)-Y}|2!!8{j-u!9s)QDQ~{=uE}8}cExC<81_ zeH}?!dVymP3kM&U`qa!dsG^%KcMC*J9*(xINlNRbk0mOXiIsa%~TY-69TVW0D%R6t)x`X%29-6BjZHe zs8f&TJ&uY(3=V06_2?tvZgO}2G`yygg}40v!2k-@R@Wn{%YrYMXcj7rD931@67mO- zh{;b4ChUABTb-Od9+@|8d}7*n-=r9SoV{}mt?w(ks&5(#yQ*%OgJjsrT%A%Lfk&%Z z%u7D9$n>rqQ$n|#(rWxyU|Urd5}%~1tdgomJ9Js@rb3cDg$7H6Wjubi09J5l2Ecv5 zmFK!B!ut&%r|*2!XFiEm8A^Ij=QRb=gS+M+nCYS=^r@V|9(2q7EXYWGC(_if(W(a( zp@>v3#jg0G9!I(Q^2|W~_LO&_QDzh&)X6Lxq!OmSv5{5Q(~JMFk1=J)(4g;m*<4#) zx&TQ&Sy3+qRnHj87z0-1OEjMmQaMQvemlfftQ+{;f@W`3c3^xfjlz0;ZWa^v73L9p z)myb2gSB@N6yi~g*`YGT@+@1sUoR6J3cmXRYzdr%oD$!NmnJi%IF-afVOg zjQ$8bC_v^;9C}eJM###t!ZLD2Z`a7}CiYQ40`S5YI!J)UT!9Z=qLT%ti60LQijO(l zHWw>=RFHJ6V~%mG0JljC_fFV?=#Zo0MPvJu94@ydY0@0Qy?#Bs;Z=dr#3jz%n@aU>HFVexYYK7_lfyCfT?Z>z7_7W^qt3 zS*Mb${65DP$AHa|r)zj5m2;_(^wQCUqo&5hlF|L9!^XKXDMeQePQ zb7GnjXiWhQWdRUn38=CNN%Lgc7wUuO*2O}XsO};uM+onX?!X1c+aLB*R->L&T)_!J zGUp{motT{gPPqOF)y4c&iZwEe!GJl7@vcMkEK@#U8^Q5yphJK(u`$vhSEA*r3Nsq< zvZB65ShVVua4EJJDR?%JeB}K~{TX;WH9_1WR-wJ(j=Fx4!N0~i`SH?J4Y+vNo902e^?jPvja4m%*r!BZh4`ndEE+gGOu2pnp`24@fmS&WNL_ z>P`1for_&D^~{Bw0<^8=HmE9|(I|0;j5Z?It)9qjk`yvXuxg(8Es!EF$;{^kF!!7I z_UbmJs$tWiAF>@WS8(#@bSqYDvpGl|mbbs^zsRc|)GI^H16Idb=)FWEa`M@QF1bD6}JIoHY6QZk^jaLGU)t_$jPsW2D1 zU}KdaS`@xd9-Uq|-cH-tViS~dvJ@(q*!m+2?A_AoOIkK8jx8)E`}ZWeZbAy+ol9m# zF=aFKGkMqfT^7Zk8Ur!S=`5UiJX(~Hu!rFeHl$}}Q9Z){JaSp)^(e&g7Q%B;OyWk| zvPU?8Hr*?)4+l49MOuK>6lQ6Mwx?Ae(m11tnX~N(d%mi+Yqr$Ux3xmsZo+yx8lI3i zBf1^IUz{~^HOc~Z#F^aEJffS*FlWBVgWXO@gIpGj)U60&x$%0VHKjJ}D;B;@DnK-haNiFH< zn1Gs9xF7kTl#q@G7k%0{V}srWbO1*Ge=+urftiI(mYt+y+qP}nwr!go+qP{d9ox2T zr^7euWHb17XTIIpnP2zU{d1pltLmv!b&fMR!8P646@h6`lxDssUirR_M>6mGVn|nELr|$`xXqo(Vwe3 z(%JP#{|sthzhS*;DJx%*S-)|;VZBS8?$)y}DdDw4Z$oF;@b}<^9m1AQEH{q-{0YGg zyU8E)32=N(sxQI!&o1i_$!&)WJQX_Y1*617c+JwV7kX!ZRNH!v3(#n2HC==`pkrNR z0dUQgg=%g%k==8p~bscm7d70A7})}wp1YSlLF45n&) ztHnJ{r8Kf=L0F!WAeOCNijl2Hly0z7+gee^(m5jHg?g{}>@E4E;AGF`TX+*Z;csCcO>-S zdpd3GY)AZca{*lK=%0-Z2nM;`+LuvBX5(E7W*)f?u;L3WM0<^c93^5UxchJI^(f6e zaP$a)@W72<*os#i7Gl>ju@ztQi99@K$ntVD0e$J{rD5znV%1GnuHrUZcdstXb#7Y7 z7aUU9u9>$2*3!(F$|h95I&XVMB|(<6wJA_D&r|1n{QO&?-1oWL~Roo;^scfO`-Gz5j`J7@yW# zW)^^)jV8YU5g6VSCzMtvNAbA3n3m2D*jWT3q^lOhb-{IU|CQjCJTlVML4+En^>j2{ z<(1=gPllbaTBVnkd*QikBJzSzXMBK@ZbO%N%A=Hk0e|R&HO)+sWlrRoD=MlZV4YB_ zKhk6gJzGFAE9%7;_e_}6lZD=Q9(k@vS8|$A+B+kCw%Uav_d9yWkOP{&4Bi9u*8r+R zYYI;=wI_yp|GwIt#wU#Vz17UIRqi0GPP7+g-7%}qWZDCl-3jd0K-LRX?IG`0-@C?P zR(k}z!3o~;gW=8;{5_g)FvthX#VO|)y<_<92}AEJ<7c?GEZdG9))2Q0u}7IDkG^H* zfOCAi=0i^n5%N0QG0agDic?K8m&McOLNL855`p~3iH zedsVt%Lg-*fkz$zFw2H`K5-s>Wz+1LTRG6DON~7 zcwh4{IC`h@2_NAJu{Y17!;d%~8D^3sJKU4-Fw6QoWWyo!YVKNs(j(Eyj8)qggQI(% zi_R3Lp?Lzmvo}U^foJkJjJ^B)XNE`Ot^p?ao81}z*2ViDHS^j3oy}3X{uj|1-bFOD zR_(}RX%tbQl9GYI@N!jRG#C=p7}7tJdoJ7q6CF{^n-_;K5M%gD_R_grqHn>ed?-Q0DNwilNcon6q0&^6!uqZ22FqAitDrpHif9#KLT%9c>K)|3nsAni ziF4bvpem9CXDx`JB{k42?^;7Vw;Jm6r%`oGF({zTy`)tpVt5v_gs9#WVH(;!LELF+ z4)6vwtOfthmS}Rw%M+Ls|vWwQt=LF>e5*J;T*-pY2MIF(}W zd@PIFIvS@KHhX-NF6r4?i34AqVN&!0{$f!YF=;PIY#x5b>cW*=-lBZQoB@oQMN``3 zX5%6M4)-@xjg_96B$*#^m&W$>%#nrSHRiXc>;B}3FPJyz%06cmr5)n5` zG>xLxA=8z5mfee=txcG7F^{mj3@7kUuP^S+C}3yy_9ocZM?~J6GDxw;@15^jY+-<5 zxiSq*<$sO;vH#CVrcliqg8iOj9l-maA(@@^e~+?ype*Blbx$X*+l2l^6M_i)2|>7u zBtQpgV23;geU$OyI15=5V!s#%FA*GXW`vj{B}Du#J&@k( z4=MfqpSCTZfhh93WSrd8L1rfpHMrUF{Yj^nNN|1CKdkgnn;wpO%m?L-oeo0zUJP5|-0zv+zdBb;(jQ%= zIlZKS)0-ZydT7EGzs7*~rrh@)^xq!U^rj8s7hm`#A9N9fEh^RUk7L?@GJg^+e^udp zl7;npD@Oa7?7Mv^C;pXYdifprMe$PSUsWqCummMj2OU;eipJ#r&Eez<(#xD~riyVs zKpnZbExWipHM2jnxGgoajp;&^!`eQLcdx#T@(QoMffV%1DKop??~vyI6aool8&Ylc z;k2PG1ZLK%U8-H7GBzX7SVs!aR0Y<|3FwbE8-c;waTvLjr8P9JSGsw+TJ|p5@8Rvx zr1ZRNoe&#u(r0d|q%|pe9)=Ny&xm<$@nkDgAkfj|wz+6&2mspNYtRvn6Lqa&FL$>n z`1}*^Pk$`u9XHCv4k`rX93>zoc@78UuG^L;or^V$yS$nGXtgM!aPm$^2Zr5DTTNk?a|3Fpz^S%GG<`!MW z7ADl8h`v;)XgP~5wV>O`EvI7HB*jp{1vr=6Zqs5nhP7KtE^cl{cPf_1Q#{%>alLI~@i!x4 z3OAWQqMlRQk8CN5*nF7jV)JBO`~Wf}XX<=rMT>D(M}8anVwVCV`4@{B@v;IPQpTA{ zRckgbp^Xg<;#vE~A}4xGnW29{g2T#=dEl29OJ<*X7_QV^FabjL_hjZlsj7_-RX|H! z(o9ypj|$MGu%g%TmBBZiDf>06!zQUMvki5)HRyt7Vi_-Hz{mtkivr8^gZr^xLxDNF zxSr=1O-Vpc*z$CMB);%y`frBATRcIR;RM8_u z3H62-f0x9k6h-;qD2!^UpoVxGctFmd)LV%lu44WJ@*r7p0 zYWRjIR^Kz?$YY#EX%vT*6pJHG3pEfYRlhB|K-J{CRb(WV(Ac=26nbG2eu zYt^7$sW9qhIoE0sL`4se0frv`J!hsf#$p}%KF~k#^95D0BvRH04#dvh#n_Z|e|^ZO zI&wO3C2dGHDydGTK~$$a(n_(Y5d9ZbFX}ytVp*gY5xDz-e`IIz7hkNr#5A_bJO!PS zXp)86uo|Ph!T8Xxy1qh4xCY22IU!_ku1=+nv$a~170hLPBpj^vZ#(ePinps*m zM@y~n1((0$?YEpopF_+dP|$^8F~Mji9kbHiP2B(~;JV7>JnQvtEtWZTaW^S-rb5=qW3tNdNca^GQBxVyJEr+R1gwqD6{MItvGAkVh1OxPuER|ZSm3F_) z>Zjm`gwzs=A)1U%`oKH`uJ{)!d@O0dy9g|ev=r?wIt{7vjk@NEF=Q|lsIvN#?j-t} z3oh4e1Ky^&zx7PTOdpw4+oavbTTIsR7;XLPvbRQcw-yt3#NX)F5$^1CeKp4;)6!^e zT=xwW;hyQ* z{h?nOXtShG=Yr_}bN%Cu>I$mnVl}c_aX#$ATfBjgLC$cZIpJ6=8 zJGjvaP^(mDxQ;wbUp<+{=>M>*MR$4Uq)T3W==e+5eu>{-Xy>O?iaK_pA>Op2oElY+ zAgd8;hUG)8c4%btJy1}TLcZ}*x}DfQl}bkVpw@-Cs;*l)M-*1#L2bV9Za=u$ zPW)uygmctlLZ952w;x!Gg6@I*(cKo?70l`lu6X7&2at<;@5H%TkV0ZxCT~a&*IGEC z=Z`HJRb+`YrNa@q5d%ol>}u}ug(fQd0w|<(|172!Q5>4|Q%t;a#6}JtT?pdst6z<& z$shze?irh5lR=zL=yT8#4>2 z!R+5?1W#ZMbS2i{4}^VQFaCYqhgIy;$(Y3*Md8dUOc61(5!}`C^Ak4tY*1|pdTZ<} zZm%fTCC*X)qD=LL4r5ph(f4N8k=2(0!LNmY8Mf=(HnlHaClWXi{aDx2taY0Q9nI1O;P&O;e?-@=LSDwuJW9z_}7vLot;QE^ui>us7EhD7W4kT3ut>twR3N-K1Ke=`y7K;VCGK`+{_6}rD*Qqci~JOKxafiOdk=Ff z^3)Mq?$E7k44Hnv$ph3KDgcBC**zkoO?;}q+lcW7dAK+gV|~D6Q3BGAtPV!XD^RjC zXpAEUx|%ob(HBQB`#NnrOvmR1#qs1|S`F37jpb%2LFMY_y*WoOX)MLTtep32BZG}? zO+K=Gp~vY|bXwg0fifl7qvl?B-T|&*FkhdJGYcvH3AsRyebkUM^JwJJRW$iRO+-i6 zI+d|ND=f?Tn8{Pi(=$(x%kVs~JaeW%1OI_nqmJwoVmgrWsBV=5V%)Zb`D%qV1}WiB~p*e6lgQf^@kh zhI!bd_3qlC)26ZQqf{nzTh@;4@Q8e;cRt}Us%;(q9-E=uFFq)7;Tg-IU;klW^Ny?|DQAm*xCO5N~HzuqjH?`E%untLy1@l_+X-=bGdeV!|wV*;q2)AO{cu18#m`Vkowdag@udd3^#dse7q zeMgMW$FFuyPWMLnSEis><*ZKUs4#Ex4c#q&0sKXN&#z+co$h{4fAUnF?hX4*JLB($ zXm3HU^4YDfir^PPo?r4Tf5qc0(`S^_SLH%4& zd&hgV9;F|@$5CnJyu#{~UaUg2GjO~gC6*wBGq}@FLJRMb8OuipDg=M!^{X^CB~;K@ znka?t;Inc$BHk8yQcO2dmO$w+G*jtAr;?6&Nl$qx&^N4qd&F9C{``^_-jYH9{m zO$&+(%3?|dd9hfHK>7gcnlz$MYXbGuInhI4STj58>l(Dcj0lZ?D2bCL#TJPBpFPyc zSlT$b5JsIGEG7fu6C}hB7`Mze&7-Twpmil?xwI`|tJ1F^c{B79a2u{+WF0iPQ1k{} z?l4zdF)Nb!3|Pd$qE)aSbzY+iU;+M!-r}WdaACBa7!XQsE9wumIFd;VdqLcIDNFA2-sT0c9`CEJP$uRcph& z$=JP-5~h~Xl7@k@ioB>u9&^%HWdw|OI?oZMkS{pcozW3<+K`avSCu_XlP0YPu}D$i zNgqm;x(>(3bkzjWHW>0^L7q~gT!=_wv77DT$xND&=XnGrNcs0L(%xh&pfQJl4mNwI zdVL~fW+j!Ott@gami)PYWF6=5VM_tOX?{$6KrB7G!myqaDKsS3%pNMG@h=pr2s zX`o>(I066U-}Ve`oYlLaya}KeO90e}9Lo|*mlQI%;>A`_W~mw_c+@+Rz)tacoAu|v zK-#r8`-e*!c*CsTMvMT^LscyO%;1$h=b@*Si>LRhS((}CS5}JoekRc6Nfk$&HnAF= z{1Wf=B)M(KC(7`g0jo^^aEc{ysyjtB@2jOB=|B)Gh0E;9*w|RhcK~m6Q#T7;7g7A82+lD>kt0(w9}*J)$MYQhC98 zIb462aaCPBt!cU&nqLhoTvr-fMx7-Q9$5+3u#~F})FdNeeZ$zUocA4gxa4fgUN|%B z5G^V@v-B|5e!vQ;TW(A0B)FNHKr4kN$J?Bdp~1z>^iXzSb+_)y@n*R>zT9g=uCKXU z^UnrYQb4#4W9EqK7gTkwn_#sKd5N?Y*nO-(vTjB-@nFbg*Hih3tSYDHUAG*OcWXf$dZlNIaf zGE46bpk#!tMeCVztEZG>9C1+BP1a&fObC#aISTG#l$<%8uqk5}v*$h10oFeLifYU9 zCU_uMPgHx0*Dy6s_$_Mcilk1MK71?AAU}<4(PJwNvB`Him>|?-&=+*AW55 zbfTTi@(^@eDB=mIOn*b|kH6JnIsAkUBifnd+%oTU$As)jfcUlkf z5gQNz2B>E*&OQ={vkxFp{N;bpS$)Id2`|WrpE1UhDaQwWB=!ff_y^(&nR1?|=Ux~g ze)96x-XVXG#^e>-TYMx><(Ar8eZb((y-YrKjLhC6mZ~z}TQYN_>fE8uuM7Ih9iEB~ z>mMV=h@FvfoN_88d~*JDQ0Ma z*NeqC-PU!oSY^Ak47{NRP^6`>=om%o!NU;68kx%saOi$46)NsZ_ZhJGiCXb!hpyhj zk|XO{_^7G2%v2H@Nz|4oMihDD;LH;FW-7MrtyqzLMynj!rKKzpV78hoB|>~2;bh~q ztCehp@{{}#4(sMQ_D0t>tMgl_#L`TQ?>)9u14dqxwMfJN%QgmM-XS%rMA>`KWM%f( zEG91qO*FYcTt-!9SiUHk(16JT_v~U4Fm0z^J~zj znG+Kw`~-b;1juku0t!!B`G=yJqjaT`)fM9V&T-KYkNZo}v@T}|lO#gY#0{ooiMaIC zZNt{g3L#nar$XFe=Qo#Wyc-FV(m!34L~`;Z(HiL$Zen105apm_*ryzBQh^CXSZ@u| zEB(5)Dgl-=w0d{7aPlw`HqvFt2geyIY@k{#Y*<=NFScw-1tug3u^?Ni(OJFEu9<@+ z!#YV?Q%=Uy{*Xvbou5_fv0U?S$bk1I1!g8NAnRHertD|S}4>kB(ElB=mRxwJVl zr|5`~dMpGb>GD@>qSD2okHL76;o6hXMErel=aR{*r|PJMM}3nIQr9eCOp3f2*Hc%L z#H8x&^UWdRPTl2X)NRT)=ImV_k{q&V;>$&5*7jprt4yY|sVt!gxhI{-9Oh}BXqBN5 z*V%oomx;_y@`gR+DP;`NeVR;3z6c)zCAbmsuf#3H?2u@;uQNjWMuh&qGd2B*0W2+U zE-lUakYSm}ysdvFc?q*y?a#NjMw{OTpGu=j`-Sj0(>523CgvCrQbo zX5z5IWuoBA@+^O|IjI=kZ^}5u%T7nYV>J-+$OeKQK&}6=1$3zcO>x3Oo}YQRGRCEAVxU%_Yr{?*pQ~-{T$dQEk1{in4Pxd z;mqkuWuB;VWJ110McA4`0GnY`YO*{ia7lX761^rLNK4XD3zWJ#RB2^yTLt{$QoxVb zuDootJRtUmvdTK7E3X(`N74=~zG~1i6HBe$?k|Bl{N&xwGTF@5+SwY!PSH2cB*8giR+rTP~6O zZsD--q00`2=jGM$GqQ_s&bGcC`|Ksoacoc&v2_Ymxuae;bC~)mRgH66=cKN@V%hE~ zPLY$%s^xK}fwk`}9Sv`kJAP%BGT&&^hvdDH27slVF*&5cJCf?nXT~v8zcytSvj}=* zO#QZNa9W&?!wQM7?Il3mvPE@QlD9Z~s%D+t>%<0av`!I|Bk zM{y0GoYxFB9^gjQBG~6ZUI^|mgX}#5`a?S{{(cbNb_TR#xqS9sfmaoe$X;vFGBGIeF9^q&jw-3li9!TLt# zwgM;kf>_*@8TPsd01g+olVU?&&btKcfE&WaqVj3bn)m#sqcoWL& zLXzYwqJq(g>AxYYC=z4g#Co*+0}x#i^SUIf&(@+C#^Hs=%uPV56`Rfulf{(}9B2Lp z^^5lM&UCG5-(={EDTPO7g0aJgWv_-ya+y@+@F}l26A7!RZ}8|De5Cx@0quZ<*4V1< zSJ2YNDqPY#3MeAor2OiNhk7~%>rTpwN1_^IPX02vMT}&(oywn0(oT=nmDokpvS|g_ zIRuQV5<%x^fghN(E!DyG!7W0J0%Qp~O8!#rN31Pv4Z%=D{D=D-;Sin3^Ui7GZXvFwxx;W=c8z2C z?75~_wresBMFvyaeu;caP%-QfNhdbLkQ>Q4wb|)`G1H_F1*GXxdKhJ5_KO&-gZB~! z+9MX!jX{u?iu$UXCfH=XjbI}?VA669*J196Mmr%NT<{sLh)$LGpDkb+&ESfy$O*VY zHn*Zn5h5vQb)FH03U81SjmR166B{z*=P6eYYd_aXsN%r7Xvxnjk)Sk~^mHRNh2%2OTYo9zccJrO`{=(kB z;Mm7+o_b6d@g>NDu1Z{i`LN|}pZXi;65x>e>P+3jOvN##!eQ+srE|_5V%Y=^4_p z{!UYY_XM$CB4b%sfm?Lx6}K1BB)PR3Jr5UW4&b=v!Sy%ex3UUC%#iiqd27_tj3kkX z?~gdE6!Wq5=gc%{u5mcGbqLi<{{nN!jM}tS361A~^<@_b^`3$N+x48jD%}RopBD>K3=ED{fr3R_5N{zI#(8t^i<8JF~$w+(vHYJ%8gZbz4N*eO0UFF zsd9FP%uzm3Mwx?AOLv1MmmDQ!$((SqKn^#Eqfi7>1Y^8zK|Ze}v;*Gm=ueF0#ouR8 zZ)_+4HocZxp^w}B5|1#u;#*-(zfkpO@bD>oqBq~*=!eC?7jKffE^z_nXCF-8k57`sRLs)I zJATGFTLPq;)uG(z2$~Q?z6MDCg8aSgna-8_4hfZ{PhtyS@Kgne3mJd=qBnkQGrzdN<{?xn;h7C>5A4;=1$?)v(w_!m`FN=5J?i zo)_q(?^v4I_5Z=K@d0Ne!6<^p?@Mzq9?(XZ)v)i8@v&)(Bet5I#{$sY` ze4yV8QPT!Rfj*y5L6$;|2}dEjT%z~(8ZvwpxJ0fPnYaaW%t5Sud^PX)P1&SAFsSTl zLxDPDpkW19UFIGO9pH?1ztg zBb}oTGF^G!|H;b*BZT@E_xr?czIEvS3*p57fEYJ-4AQ0l=LFVSYIj_@K9<#napTK);UZg1Xnj(1WCBI3hTUl12+VuKhL$xS? z!#ar(gJW-bajzKb#bHu#EP|-*qsen@_@q@8W^L;4rW6v8N*N z7%awfxbq9@;>!hx5u=Oh#)vrg4boD-&NfxTlvy{(3(;`72?x6i@MWseKZ5!BQ4i;S z>qm|u+1uQ46_yHF@8vkGa&8+vr8sAm1ig>fZI6u^8M$?;?k<>(pmi2N2^$Nvob_5cggITJT z!QYPiz_C(vol=s5M1?kJ% z&tGH_qqcpuolTfFVZWHno!njfVur(idg0p17c+IOOW%QJ59G%W&i_H6`B%t^IT_miUory!z+B9B zX^YNAF$qhFz$AYNnjuu6G$N8!1&WEIg>KH8?KUxf#YGe;e7h3}6Q=2bzxv zyJoav~k>gGOO}P zi*ZIjHP@wPim4cZB0J*;vB0G;j-0W4qv{WmZivHNfKK+5;S@YwvKoG6^nWp^GLz)x z5_C1K%qkkgUnvNzJbp``#hl$++psjNhE>1{Q5jQfiGQnS2y<{jWF26rD?CI%^!y2yB_-+C?{ttqL|B{oe4NqPc zzoByV4He%1DOCQ;gp@dMha`v+`bD{^#HOvSU?DiPqSn+p(voQbGcweS#fWXM)y@hc zV{p}B?Uts7KS_;5@ACtH7z1CB*IWaZh~#3LpV|ELi`$&-{d_Yl?#Hv^^a#=gO_~N4 zP1?iSl(Dn{tztu}p!RS?>;QU=FwmWh!7%|;l1iwhHkfeB%kj+W?bAqSN8bVn?!{w) zz)bfJT0LB0E|SKRYk4lbzPpMK4L6Xgl&fQ(+363z5Ta+(8dODt98yyfR5- z8#%@6!dAUo(lT_&I;4zguDgusiWJ1N5bvwY3hJtZ54>9-^w%v#jO&`coJuUXqsz#2 zrWqF|!2XWLPh`aX9r!rIuyXcna17Snj{ThiYee@+bnCADe^KE;L-%DwVrd?0@ryC>Y02`CtG2@IC;2boA!NTq! z)CFgic4=0@%X>RUfalM6~&5#gcfknpB*3w1P!_>so)a0L%Sx&+(9f;s} z=`!Eg^4Z$_xznai!Un-ELS##t5|gz6&Caxq%W7k8>K-Zn2Me!1MPvxX19El`bSOhL zVy-QIJU7Gn*{AnG_T>2Q9cCZZiLHquli|cba|mYWoybsP7%U<=lahD~6v(DI2BkRF zyv{ioJa^&O(bLQ0^LV>4##*Y>1#W0`)0)9pYLNg#w5L);kX$F_f$$DYh0-6Qy!!0D zWcMh|Uu4Lku=J7IH=Ml(`!QfJ^is-8ilW`sZRyzD?v#Ba^{;M(Y8b!8iUc#_GQ{l@-)@6Zr$I zUt|+ptj4`ZOJ3X1&|`DbKqk0Ib>3%S-_p7U#B)f)_!fU3eA_| zx->FKK`-Sz8^Rn?u8Q?cu9aw(y3aAB;?Dt)6Uj9RLz4NhI}x0z3<4Qok}67Hfd2C_ z7GLwA{{B8j|K;i?Mw`fZ2mbtq$Et+Av2&Q)s0W2bt+Y}lCZ(>rhs3-^?t4?qQ$HHq zfZ;pXa7XHnxL@x@V6$cQsPU@+5nhLuVCeW7yUHiw%<{gsHxMlBo!JrM3owVd@-3J* ze_-Y{ILX8I=lo!Rt^G#7SK7P>_Tp*CnVgfYXIvp%PO?4dsyCW6Gt0{|dz*Q0v2UE3 zL$S~_)iktdYy-T%{D^_oXT&^nG3!Rn=^Fx={+jvgggXRW0M|g37mD!42y}>W11g{@ zk7s@!DAzAZR;eIPp*P6r+FA{evH&NK%mQ^Dnb?;!u?iZd){A6#5j2<9X7_DVW$rt4 zgm_jT&{PRlr#Ne*HKaCea9ZPwdij?(xta$q&{U%e!D#1geD)RkFx+5hL%5HfSM~n* z2N?eE8x8jVI|G<~mj;%0=Kmy3!<-&u@$)+n6n>-VzcBIs$BX|e2L7)F#=mjaF^Q7) zivl>qUrE8~rQE?KSK5Sz6_)J;j!xN<^+#Srn~>AvPDzAPkc?7W1LlW);Co5+;eY!g z2AV*|aS#Sp#vZ&McKpz0F9*}=!Yz_oSvrd5L&dm?x`?-I2hE0P#G=eta7OnT>_UQm zWspwv7^;**Pga1B5Etc8*kjVN>g+=+uYHe|?vq_`t2lYqoZkiSl)1_(%ASKDiJ3CV z8*CUIypBmYi_AS*1CT$4ELsR{CT+lJ2U{yc?IFoAU!t{o5Kyaf=g`HReMV1X0p2gv zMMjJJ+^}|UU0CS@6} zSLb>>7x3QjEE~boQP1MInwRhf+HzGZV*ASN32T@&;zhZ+E=! z8S@j>9c$Z3IqCB)ejbHin)496WmFJA@78>k~MEFd=_PS?YhNsz%=HI{ket$9gwnf#bfAl@5lIo@ARa@U z5T(Z*0O{Bak!tpm9841FMH9u=g|Dj*AFlqqxx9agf#{*U?IB&GXFJ$z%sjX!MWm0~ zr$+3;>USr4sSSknDmc@b&~M@%$6~)@7Gqb?lvdau&Dj-PQa7;T3-?YOHhE~KSLvwEPl^ox9;Ixvp zd{|Di9j&W_;Ifp(UX~=X37^8YOQRqM!Q|K|ps`Y|NORT7 z(|R%LwB637@OfiH3Wf9 z_w?yN=!C2#Zz;xIijCesvzQB!rv+X}tke{e?D8nLcuP66fL=?_xu`L3P&!vse`_O5(M5>y#VbfG=Qh6ejwOW`9}tEAoOcf`3B=tuc?;RdbOBkRCAUc z!?M>?QA0iB$jC&F2D|v@QY1^u8L4G0B4?JR&B$OZLJBXDT6KRWbDX`AQ~5^biT-Jg z%sWJ<@})dbZ!0{Y+CjXljRgF$MlIqfF+z8%@&GGS%|_U^caRyjca$Bz{o{@5*T)Fj zc}oqRmYYekp`JEdCRgYq(;s{M?ZhrKDS7lL67e^o{=|iQf9fK_b8rRuyLAZ={g50+ z|I?iP)fCw)(Y)G_f57}weKac2`Q0Ds7cnumTz;YKClmuWpla$|U- zCD%~DF2pE*7Ip*86$p>=xC3u98&Sw!Fd&W1YMt4^o4hJTn)5vj$>L+g!tEp?xZ7Pi zX(g}|B%YLa;lI_$V1H;hnB31oH;b*Vo_B{)BFyBooxxa3pgAhO&Ul|upgB#p<+7gr zNUp8Cp5d!gTgiQV0mGSLSmR2^dfS{j>wLr20TXeh#m=uo!>zek;5ko)sRv@OW!Ynb zl~0Ln8WYe2=F7v$*j8$-R0~F~^Y-JRmmHIIlVBrUNHVx^HVL_3FH+d0cpNIsLS^21=-HPH3vu*Ee~FPiZlAQ1WOTR zApuGaLDP1US7bwmFgNhU$B1V$tcULpUJw7?4z-5dj8?DQY`51@fkx9pil!rCfyo?7 zV2aJS8L=$5)E2dQlJn$fN*+LsvBx*Ydho`z_s%7)kEDGmrGL&<%jM}pt?PRCD!8gT zz^&!Fe9@V>on%r`Fk%_xbHGz3MeSkd0U{WL3v=`}%(dalDI!_QkXdoM8GVaoYIk19u4JtnWA`?O(S96b zg`yRi#tV*e25F`wRd6&AeF+t&S_;f0xiNeVcm%S;T`rMZyhRSjkgf%&>PO$p(<{BJ z(ETxr<|{kt?98kIfOS>;~8D2d(TWNU*d z6QDk#|0IS1G=mBsnquH!&LLfZI5XiR10Cm)n6+LLv_!_6W@4|6790WO2yQui zZOQj=X$AIUNTjX3La+6eou?#^4miurx;i4;?`PzP>peXF6S+>>F8a|KqMH~^dm*n{ zkzTprb!Fi_f3bcfVl9$~bEP{XcQ|FpnJ%wqWb_$msa?~e6svG;yVrWAx@#24%vYK3 zRoKUxb`@ycmcUy_vL~m3z1VC6-NTlCHKdPaA8VtQGzkBGPXS%uB>-pv+RkV)qK^2Y ziS8M*YlcBx`}ZS-e&s^z>Z7l!{^-_ z*d9tJP$du>hz%qP?rZ4+aLC)?evrV}>GRkqS;3FZso&z7GzwOhvd>H@GYQBX6}uRl zQEyH}dASvbGCTzMt~EGR+fkX($rAL|%;Xl7J^_8}@K%|>v05HQN~zk7CO<$Tfq|jB&^#SNfaM{jasFr^ zoU}zEHCba$w#~3(X9V&d`_vhPFq+Wq;Y^~x|A(I6zxeYEilpQee1CJ<@7>aGt;qiu zG4YRT{9nJj$#;jDMBc&J-sIoCPE!82G0#SAG5~%3`{wBiVwiuhNoF%;m`an?5Y+b4 z?^0sm=u*1*Cy0Njmyj5-X#USSz9|o20Rb(-QP(M#hu40Vv-5YauirbQ0q83N$=0$1 zJOFiy$|K(p2fp32*hq-@)c9L+Ml{`6N;KG5YnWxUjH(c4Rb|RSM?Kzf&guBu?Pi0@ z9uvmtwR?H30rN5Nazn4yjxEbA$*^JV&vWAYNx|z$kghdbwYwX2`(*}rY-idQNwfP@ zDkk@&9HT_aM-^1cCPi{1ebtaYiqtG;GABj5(K-Ts@|s&~TT0oCbe*>iA%5l)+iEM0 z{9`8d@ld?5=xB@dbV~{de{8z* zI><%7aaAJBjAbL&)SgS{&z|QPQeD9z6~A{ASL2#Oys^evL02qB?zx1)4m)!C0^$kT zz%&cHqMaFoXm=;MA%xabsC41TVFa{ts`Y#8GSPm+SHeKOmt*%qd>P&Q@6N0;CTbVU zk#jPt42D%$gwX#*+B*kH9xiLbGi}?pZQHhO+xE0=+qP}nwmt3c**^E+-gEYz-Milx zQ56;S$FCyldGpQ8C+Qve!ggi2ID#HM0N>3to(R{^tOYuNRmU#yWrkf#d&()i%Sa!B zX=J>oNX`?I;qyW9Hn{OcFZQ4d&lNm~_|}eK6Sp+eZ-;5WS0bH|g@_yX5-_ECd7IXfD-gEZ#sk z9$`Rac|aue1aBw^hf{Zj0_dj*^J<@;d=e)bL%9Sfp@{O8-Xt3cCx>p5$UR>KMckkt zEo+#uKV>Tc!Rhhr8wukc?|%}8zsS41-kBEdx1NFfmU)W*p}hZ%D8x?5^z$JF&m7eR zgog4CazkPuk`5AMeyf@MKB0sDDD-tm@R!7h2F4N!}e2nL=Xh5i6tojcqfr6>mJHY8~$A1w4l3zPQYreD{5OUNB-C>nd(- zX2M36Gs#lZpMum&duHQ05^S#{P2i@!rS8~D(31kc{BvHHUnPMAU@B_VVpseC!CHLO zM2HVq%F$ir5I?I+A^Y3eo{e$@0fqI2E!@?E9}fP7^rP_c)3Abks~DJXuJ%8KUHp4Q zG5z1LS3UclHi`77i)F0vObnkoxE`f6wisF;z6?oSqZDW&pL$V2z4)vUn)@d7CxC_v`b3_Q%DY;ty&z zonSf{I(Yyzq0F{Ci&8N<*2zsU#Hcax>oE(RJO?8U2-$`cj6W;;AAWZFp?-%UY2WRWnRViB z%Y#;kI%(kK63i_H=%tMXat(3?a~bl`0ro@v5+yY67Go*)GW~A&(%pZuo1m4il~JZe zro)Fil}zrPiXSC9cu8ST7Va06BTJ`BC@_W;Xg8J%h8HohFJA#Ls}q(Pi7e$cGUSyc z;`_gDSz$9bDm5DRD{$6_1zFS=8&imcxGmA=Vl`WYm{=EJ2~Pb2=E`yrVBSj4yPhEd zRc=s4Uld2Ulo>+)tTnLcbPdL_6e{r2G)c0hN?Tr0gt-uKb>^BbCrCmu%g)NO#zO$8 zFfF0k{ho29g)87kp~PIN@!BpVIOVDyj;H>7Ouv0%!1XH#G;98nz}g@9u*J*Y3w^0R z;VvlpmLC9pde~upZ>rBL3^ioDU5~JA7Sw<1z@FLKoScww4_bnjk+@3$lI*O}0#4DK z82p4n5WD3i6iFUR!cDQ)w#b7jA(~1qMOIrC?5C)N`+Li?Zu{D(^>dlxN zF7D_H9IBC5P>iux|E93dEjdrZ9lIlH+Is-5R~TfFyZJJ)k z{cHNIxpm=dlW+>qaWhN%?Rh!9Rn+SJgwth!7bJNSNWvX-^=)5I(rs4c&0Szn1w-_% zD8MTdBjDm*15SZCJPcH}(m`@>`X5Hx%+@2CbPYX0bnB*B)wxuAi8;npp{^-yS?}>IsRNvXVP&T*8y3lN$U4fK2Y}}FS$JL8&2<|)+A9RnlNGHkQ@kA<1 zbB{(xA$sr(q2knb@0 zvT(3FY)=xXh*ij5*lX`BnmoTA&$bEHWjdl7AvC)7GT>IMe^&_sHUd11l7)hXC14X< z4Y+8m^}($0)0)@YU~_`CZ1M@epeo7qI|6R!_u#n`VCO%`2YW2emw>!ixms!WOkNch z24m+9M8!H23T1-z43OFZA~^aSQ>0cHOiyU}wVfNB3g5zOOXQ`@t)&>^W7NgRS`uqW z;VX#Y2gqF3E9PEoNaJhpow16kLRNb>+c~QToet9)YS~u}wiZ>|S6UsO&yQY=V=Pz} zN7l74-51vnZ>^qS*gEPz2csgc7gf~-TdkMuo>1UN2%*6_Sm4C3Rotl^IXH!M>-BvX5+6EP1Q2pT*YT^hmGNFbl#+9a^gs#5Xk6mTp4RZNA5GRb~%jAb<)AIhfI4$Ip=q&L5DRmjoWy z%zW2c@|Axq{Gp_%*CoLy!w;=sVlbLpo zvRKth!6Y2%BCxPMuj@F z{k?ww>i*0qvF*qgd$7-&4DDEZGq8jnR300mC?_zWifk3_D64=dmxSHLjevKczoYio z2rK-SyixP_-{$;wn*L4h?%)3Pei6A=9JNZK10ZpmSBxVd)mdFb)}3W;UWmaf<~ z&*zzezKpj&c_glt8SsjfJCMw|A2I&}irOhs- zt+3obT^>FWC+$=Pop-o2Z`YlGUFGoSz*qT(I|2z%h+w3-;f=%9j}k)>bdw+A{xcX6 zu0kZO-(VnrgTeUy`QMar{U;dzkbr-JA?ojfkZQ(6vFZj=kQ>pI6`%%&5)c(^6^}n0 z6h(yDl@SbjE4N<^$B!AIZ^E;kku&n(0!k;m;(w8Ql`Cimxf~&7u97bI{PeIFt(PUa z0NwdpT&Ga1D11=mq%Pc~r*OVwqjC~ZXP6xEjk2tNpA0cO#U8_fr;IDeK3O!M0#@}Y zf=Wy+;y{z4TRLdlbZMB^UXKRjla(M*g9R)o9ekows{x$l+;0q;Ed(wdS@Z(e~`@(opm!4Mmp;(jlUA+LAINt2VAOqTTLYX&$-!UQ(wI>}D6hVHqw9i~#& z@wA&F=ng8XT>F9VBvmNiH!IV!N@0BBjkl zdq2;W&OCSF=_~nTET*~HI=@FfgT^o|ZRRyOXmO|+9ne`JHp9D`af=utPw0O4uIyP@ zYfNYSj*3fXuW*L_=c9&_dj;+MKI;De_oG%cc5wMep5=SB$O0cyru1fNI}9-scpK#gqy~vJ6SreE1#2- zO>nnU_Ug#bS;;E-SD@DNdV+cdFZvOzh_myOAT^Z#m4+ z?2qPp9hgJe1%o}>p*je^MFltnabV){alucFd^oXX1ClBC9pM)a>q!s6+nkyvW*k$F zL>MPb?ZK>kTW*rKct|Mf-!__Aw>?%oCR|BjK z5tE@2W6(7Ibb*7M=x6>+(Rwi3`(q^KjM@oXh6^PW$M+isyi`Ku zgmP9Rom6%`CtFJi?I~3vj4Z?y+AhuN3DJ+3SUQi`H!anx4yHx;Y=|#6E6tgpB|;pS z*`tM@!Z4=Hl@Z6uft44ty^Ys$-X)M(u2L!^&j{@7DTBt`8nVS))rEPe+GJ7K(Xb(s|VeLmuF}Dr-L?DdiWPAjhUf~WWV6DKLMl}y`aJVP_0#135LOV;kdSglI6oCOm#(m zBZ>$0?R1pmP#F=;VV82RS}ijrsv3*R?F7r;W4r$lB8Bt>o%Ei%k})eQ3>D4OXmM45dSMJR^D(x6oun1 z*wC1VP={fGLjVAZB!WZ{1OVc6iR~T5!wl`+#8EIbC!p53Dp#Q-`yz)WLYAUYCf_dI zFCg;}v2-Vw9{jxtD;gQPLh(f$pk~Zd-G>6B+OjoIKZ@Uyt(nv+2LHZs67K4jW*}~z@hcP4 zd!{im-TWrhBWOosziXz2x_)vo6QrfN)pESUHqza?VWd{gaWfhJ%-0>i*;B?) z)J-H~V@fCE2CSgn)xsgB#+pdkYJbOi(F?fk6yUhzf*Hrr_R!Z-XoM@;> z8QB6tw!!AUN=|s@jO;!{0*Qj*L$m_MzM+y%cqpakK==`)gI1YNFUkxr^#qAXhj)7x z_!y=F_};+`Xp+f#Cu*e^OXWRjV&nDWR)`wo5fqGc^K)k8ygiU^{5v9Kz9EVuhfRLD zzV-<9=Ca&Eo&Wb*CFjjPZS3dUhG>p!MyZ&Uz8~1SySdQ_IH#-qf*=RJHho}MSy!g{ z{MwxF?nFo3=FGv8?;V6X%fP_LA}-&1x|-I!1&8XWB=k5~q!~6^IAs<-l&|W;d9raK zvxz1m(a?&ed|{uRpwg*)NtjTshL5M#J-RqHOZ-ws=d%?Zb--HsJ^hiP4Fpt~*5lJe zSv+Q2;ahDDS`h#~CTAPHl3UH6Z6Z<(Gg?uffJjf3C;W-#Gf?6#_+*WQXi(N*${zI1 zoQkCjZ{+I};foOIw7mdTK2YOEY~j44R&O9ak-cHz1ZY&D(2dTXn%c|Ium)HkQ;LPt z2*YnEwm`gm37R8bbj3cPqxP0!Y4bit1l&N7vxzoZ*p606$vP%|mF}rO{L8e7T;n_< z9!1Wu5g6Yp=6QZYA%jC?=iRbrlBAg`r5}7Zkw$T44R=~7#=|`zO~s1#$(p|)>?blX z>bR22xq6lMgaY%r2|H)c4h64_Ub@m3RYo8=^3zX3%MHXMSZFZVgPVF+x7To^&g!fW z`Tsg-Oeqac0hDkQT+ggg%AS6efX;kIR05+uXds-L`eG?|CzrE#5zG2rcD57MuloY_ z&o(kmj_Knsej&oQO8md_gTGqEe|U#~=LeiN0Q^uPz7HDN3gK7=sQ4m_kD&zcLs)nW z5zL*95hhTZQ2~HEzO!V4b$ zL9za78X`y9K_eQ-uPDVFus>$>kP&t9E9l{SWK;zq3$`|6cJs{)gN2FBH^t67tUEyBDAt>fd&O z{Ovg*V-tO6DN=67v1LS{sb3*qDK5qSGK>q|O^l!NS=-u>{Jq0C zyp6Ek8dureC)*cYuD_pod%oAcfoKf@*i^Jea#FO%D%+_FBdxilkAXLo8h}qw@C=zk zs3?`Tmh5(i6W#Y$hF8G`sVm;f^_@UCfh;{(HC(=UeUFxzutleh;-1>;7I{doK5<-X zVh~0o{K<>Fb-}E+5%e<{~pQ!r)4)J&LUcVz1%A`bP z7ZlxgcnKVL@$ZO<43K8jeyulOm4#YCxal)m+-c+rdG%VOHV=3nqM>y&e&FPn+2343 zc@2@T^Nx2PhiuoHKN_#skB@kFT&i^x)jyfGuWd6EMhnwkSsk;+h#s&Gu}V^OtgJUt zA?21nVPW;IxZFH>cRXPJ;ri^2BNv+xIiF=ABuF5t@B}Sh;(ox?Ij258=^e_pOg^Y85|`}$_sXW-3?iLf z&5$?@op?lL*nndO%EHo1g{Uu4e@ZYz68dO!eFmr&jhikd^pU+Pi^4$Dx#hiPj zIWg}2Y!ApW}usfhQ~;>&Xr;)i&(J6dTeOxx!nUheP30 z5u#`zX^(DK@B2_sFX@qmLq~I(HvkYD&Z~3iZ-8m*S6>oY#N(YKpCdRkYbdXc6tr7r zZ)vf#Or2Hd5G=m@JiI-0!oM9$n#PHqJg4eeFIk0Hwja$0>AdBf{bi8XPc0+I<9U|z z^BK;{X1!>uu7P*l z{sx0$QNohfjB%~w@``)rdV5>D=g-RraxYu5W?U~cGKLLBYY{=fhJaLQ>L50-A_epg zvVle@I&cF-J;XKrU;y;Q4X)wnp_Z-o4wDY%OpAM;>r@KYtoL=-arRdb>b*i-$_^rv z^}Iu+UbsHfZ`6kn74&@dmQnO|$K-*O79Hf)=T)-R!n4t~V*MJ7Y~pS~W2M%SA0XC! z_N^&R&^srE=;oQtzL{7ytlTz0oeYDw&BZ6kfob{j5Thp=BEmCjkY1nJW+V;`lprg&Bv#Kkw^#z?+?^D30%?ZwdnFOuNolVzheaWI=H|Y>n@Y%=tvR0lVcn0dyA=@5&P>j-XQ`bNrsLB(V9N>#>tR%Ey;@tu6Ax*vt zJn`OIp%YLWe@t!TVJ)_|?xlEa!`?0{ImAVVgg7LRu@+psC)9QK`$9C8>~sg@8!g55 ze^x1XalpGk3UDdamg4^+4$0#q5#2SN5=g*zmCR#noTT=8 zfE72;;2Ik;uq=H;M)gG6w}xG&QKXe07l*h-ea$|Q4F6`ak^sH{jwoCa%N=lBN!nhVw$P3$f2BmI(;8I} zTvr1d=?EfQjLn${0QaGj5W-`e2;A)sSTtC`C{KVXG@KS2pIse70@_7M-OsZ};`uod zaKns3mC0~Z9{eY031>Z8B3sq9;(p8#xYz!8#-K#-z*g*I_GFS$H)a_hT$#!M#DUu0 zKCs^fi_r-C=BIhKF=C|qQ6=Q0IkOs=4Vej_-O#_-!wjh=#WTNtD98}K9j%{QFrIF` z&z-dq&{yxLN1kwuB|N&s()i!kL^V3rE&oephzjb+vDUXAXZ?L)MgEVD%D-OLfBF7T zZbz2lU$W?M*}#SO1^IY9emJ}P!;WF_@(2Xrzi_zHiz3x3ts6T022F2+xn6$oB-*#f z;=sk(tx6qd*mkGc#(%zjy#V<^veo4p@vj9y1Olq&&$`8UlRD+dGrCnc3$h;)(!;|l zUQz-+1kGZFiWM}f#(^ksSq$0k>$x5fz=CD7uK#Xo&q^6>L62m~v>6;(e{f$>+<=*2 z-=>4}po;5zR|&-YlfCCKu?3+>p1+&`2Jnc^WC@8(dw7kdw8@XFeHGk?JuUXgy5~`B zkIx_ex}l0%kXl2$3m(e7hL^w=N@gXCVvamRq<;I1m;`;1b(?F#k3U=|okxsg z01uG!2Z;%I6PR=#%@O;kqE0TCV4c`$cG=Yc{7|ciE(Az;Mvc&{?sYwb0-tVE4q!H z=gE(1V6%yevLZcdaVu@*y8Y>eWUw4nY8SQ`L0n_%VltiG=H~nPb%)4@DLXD#N0s8q z!KB7SuwNINr9F3J zjM*i1LszP z%Wv$EeGw+OM2+u|U&h=>cW8?{Z*JC_&EdV?uaWLW(hOmBXb?IsPF~>(>9OfZfs~j| z{r1;2L_*I z7}DCXW|AZG6s$sQ;D~)rt;3wqprKOD&`WbIa-p=#qeGMfLvG^yfwfAyb#qamj_Frg zKDqZ441Rm*EO&Ud>D<}DjiPI%n#|v(>R)XxqG_0>4pfo`r)y1dxrZ3b7Saxa@<7a= zg;g$|lfJPt+gg}>E*{njJqL;?Y6cjj*GK&DE-P~SMfRAUihn^RZdr(Ws@a73OV8y2 zF8mWYm^SS|Swq<&Xuc0?EF=-!2xkS)7Xl*$d=kZ9EOnd}33KYERjHRgh-OA?;Cl%yJfI}~mVx;dcToBeO#6D<8g{BSD zN7>K-9ZAJ_fwi0T-ub! z;|tVJ@TCm^8cptw0|c2!DN#>u8j2iEMLwj@Av5lgJBegwe2)E9T*5`DuQc2mEn(7) zc-m0FhXh%xl#iN5;y6BFVtyML_@<(CBv%4Kdx*af2`#=D8BDwcNs2O6{tiP5SXFtF zpg>Q?e@Kp*MnQZd6?wb$Y7*iX|3wSc-lLJz3Nj5K+W4ep_bsp>o4s<*iea~@i9v`p zdiMd?M1-^HsGqrXPLhUwNO&Q;^;!1KY<#yg)tT7pw3F1iwmKX+YbZ%Gmg*lZ7DQft z6UzYxq7g>x32x(d4+_G0D64pYM-wU5&0#odld$DUNYf!bhTSne^FJX#fOjy_~OZ%?|~iM^bEB@nx5P7>-iPN!VVOr6NL)FMdEHo3ryGRz8EJw7*Z2?o2Z(^HoXTB zx4ssY;Lf){yhK`x4Ntr#7*7Vzhu&4g-l=8TqH}%=c{GhjD^n0MMt9*Mia#7-ixm5% zr8jzyz?Dd+?Ok2muTZ2|nhoGX|FVzAS7?L)?^ch~QH;PyhcjMn+vh!FC%Sx^lG4D5 zId`6IG^>qUvV)GsYQx}q!8oqt3+05dlej?D8hj?k7oDPOU-iuVnfVfON;OG4qoVG}?6^Kg!O^$)||ssuIHpr|i`Cmcbb@@Sl}uZkg@LwxHIu^7bT4m!FvZ zJVUodALrSUFeO6bmDlE$#CTl$Z4SdL$!X`JcQ9e7tukF$4KXmmYA&0De9@p0tEeJf zQOlFq#E2fiNgbJ6u_7A&#B8px1TENV^CE|-&BCqO#>~RBMk0N#$?)1K0!O>vrpn1h zg+2YT0~5jOebz!D`TLxhdn*;&-bqj=hmtbj1Vm6}{&QbCjvp(x z$k-rY&~-s#h%u9r#kgas**O1H9s?-#uN1L*>wNOJAIj`XJJ4L%MYh=LfV?3P+tF7a zY#Q!Z_S?ZNV#RTy_kk_;Q1?ko(FctZ!?S`)!*Xj*utjsCZfS-?g%rXcNJ`t7sbv!t zD3hb|nUM^gimU5BZ@m5quUGUD2m<(fERwbO=3np@XkS9s1Rk&(xca}0&O>~Lra4P3 zz95rgO${P{E{lOyTf`M6eFAYx+&>%S;}fOFk%Qsy@&4&-1{*((So(@3HDBHL-scX0&m#nm zG0fuwV*NoCeNW#xFfuomaJo;3hWCYaS0JSL!3C7liIMLV#Ex{Hu?f?C&0yNA+) zaM&0_a47&Ryd?YzvB%I3C|4ZNrpV+FnCfZX$agQ32_x64&F6n$@-x_>vm?=yLJ$Q{ zNiiajJ?MrHoSH!C9@AwT8iMb-QtJGc&?t|#b|D6AZVO2mko#~4?~LW}kBx%+4n@Vw zf5`#<#g_mncPd^+`|*RAK2WStJRA!$ zp`{uT*w3)o0F^8$9Q{!vl4&Wm&5Gu06^jaiD$T0ArE)TKu_lSR_9YF?=jG)hm8vR9 z&87&H?wz(9V}>*-f!ZBhcURt%&4wIK_qSbH9FlzV@^wj8$0RS5anrcIh_1tZVs^Al zGDgWRCrDMy&PhpjE$RhQ^v+F5lA2ilC@&R^&T+}WOGQ%5&UHz_RuzyEH+SfoB%Q1u z@8NwHol1HG>bAFKIv9qqGK?=3IvA#bY}!1gXkNuBBzD#`?`=9BKhtdJRvFv^Q@$IZ zC!#v%Ciu6B28yj<#5XRB3}7&^?&g_n;$-;HmsmAL6hcMG(=pI3eL zyl+!qwu#%Wa(H2(-I-RMIC*b#!rZ~{!ae-XO(yDRJbsUr_az(gAsV@kpV1@%#YD&@!_7q!sSizuQ&snsa#;yDb|e4m*B=pY~qX2aEX;YS!zM_L24o z0~RXU<%G^lqUTEk83U=C0|z9F@sZf*aj`J}9(?I5!qYQ(Y+BSMw)#?GqlRRS^ z1o<0;mo^afP^pXVL^#by{8%S>hEm5T$(J%`2mK?xuZQ&o7NlpIsdKu#CJHFM(ya=4 z%St%q1@KPH2{S<*8%A?37~hx5WaxVj`}2};zO+hWSZX~gwN9(U-2PINl-5)tX6UXI z9!_M?(cr!G*VI?|vKyU}yycLr-gp@_OUUQla_NxLoVWASy;x(NK=Jgd!O{p*emK!M z;_-gto~>D^20b5+VGgvRBs0%bHt-V#i-*A*iBv+Ccb}NBUIA`lumSQD^%WuHl{nT| zv^u^d%{Fl7JHDr~AFI$O=02W*+&FMDsG&m-y161ct#M9`8c|gDil5BpU6lO9PH&=Z zAo%M*6mrQadmbGcWDo&8BT5d+U7?IKIfJ1E`gb+q0 znV8NT?)T(9<-)R|L8d#)aqhSVjVcu|M+1}aasf7YDAsJMj#^)H-say`U`tcf_?XVK z{M-$^uIKLCrM6qO{ESCIKJZD4Vdd8L6%sj1c2d$Jbe-(;L@MzGzv_0^RQ?PqVMl95 zC7&uUC$EAOm(vo)*@RGbreQ;Y9ytDNXf>ivu*4svJw}7lWUiX}t@4QE>phCV9Rc)_ z*Yss3H#}WP*-ejzxc@E9V`VzVOc@8nbN}XvWAy9O@GE$$c$xL&P^cj=E?0!bsYoH zPKgrJm`lDaAg`H=W%%y0yo#JT%ESb0@4OlQW(_*7spoyC*MMve{Ma`{%-uiO_}JzH z1Zqp=ZU}{;2x7>Y_Zx)<>QV3KmU*H2}-hS1M-gtL?qg%u>xD zQO5*hPFTyrtbbVl3BpU}_jsWADB%fRI`@OGVj?wLNlPok6Fnn)5hMpPS_@`@ zn<_JHCbX1QebDZ{T>-&Si8&3rYr2-H(u)AX6_DmZ+-JdqlSfD?6YOT}Tc#jzwI_tb zCQM6epd&r6jdC$EG{0-8E29z+Im{S>ufUYoI6H09YUEq=FA*&Vkw4`2Kfrwo+8(@o zNTfaw6hOpV&jsT=%+w)@C^e~Wy@&SjOw^F0M_2@KDUw~DFnWEW$Vl5pm0XB^#nF|( zwa6)`-{pBLs%|BSU;K6k!6jvkx4yy+h--g@(&kAC7evyM_j=<)^O z0iqWw*y)dW+(6aECV}qM1vcFaEJcxswe#0CGtvYGNKF{VwlpuxnYPDFA@9OFiFajU zUcJ;&KVMtYh!V&j%=I)Vh^!j+;&B!B*1Y?4iWFX!q_TS{WAP1=#()_>14{`!-CLx-IN#cA0uy*HYCJ1<6+ zoexlLkOd&a9#2=U*hYieNrwPIoKxmld7RwpGFsZwj`~#T5N;Dn5T?bEaKCn^PuC_*jix&l?W{~+1Vs79hUoZ#jL(d^mR$j_ zilKEAuG)`PgS$mzK4qMsoh!Y^r&+qchaG*T=1cui&oSH8w z;4)glvlv=*)Lkchs?Tw=9yDkRXjV~-0L;h0f+_~#A#R;74;~z2W(%1E&8^(EdZ@Zu zH+5YG7K1E{{qWPp&O){YK#AiWRuIC#H8?A)D2=Q%$a_pQg_i$h83(*skgols>B7a*Hlb1b6C+dp;Zka7cOE(KK-Mnk~=Fk-lc2E4E5)$i2P;E<4%4@##vT%J4G2YS1v0V z;>Dn|fNuW&a?>MR$oJvGdI~((y2`Fn)6%>S+W$%=lCrKFG{W!UFpL~Uaj6L%y&3(Y zox1<(QkftI0U4mK% z4!ti@7}<=ORdquBl2bn8Ij7#rf10C)I6Um;ei0lB^GRB~^r$8@{v>@7w9dr(gX9Za zQpp?8^GSZeJFxRpIwsyir=@gy?ydF&+ymjDgf3l{CX&DDhTowIv(bXK?S>TghIpX( z&fKfZER1DN&mvzp*L0oq6#b2O-Sm!>&ZlUP=huzm8w!p0_yy$^unrcM<F>bq`-tru6PX~mORF_ZRUHM z5#JZcX(tn~gDgi8X}!{;S3D;JAwyHqUBK{bepJGR|3cuac6V3nOkiSz4XyhIIjXj! z_Oi~nWy#O(N*9dKFn$L5R_zJXQ4TD$b(w+joLsIQ9*k`n!u20{SXDJl{DgHSKWasq z7R;PRay^weql8^I+vz>aYO{u2ugJzZmYFA+k6qGV@TB2-5h=I2xtY3qxA+r~mXKQ! zogRs4Y&ah^P(@W1KN<7xmYC92{3%Hl(U<0_+5=1$k{W}mixW;UDzzj_=3UnL zR^$`ArBCKudnYdFJps3bSm&+LTIOV?*4lPQnr3TKPK_NFf|=5E`qCxc5)YrMiCSFe zDm0?!5xY%`ZoN~EJ(CBXcMPswXPq^Fv9P!EAUoWyOlUdg3{dZJ|LUWAH}|RF_^~*h4?C@1qdX1)PhlKP`j3cvuL=4BVJ&}+0b;DoziLoqW!n}%0jWJ06Pxk3 z^SUF?`eqQQ%7(XG1T;r%yW}dH`3e)UBzo#1q>9RRX90{}{isKNluh*{J!3jC5HXLJ z*eIjODulIvDnR;mCa$xT;FS8kzZ<4fDWH5F{LK?2KyCXYbHFqo87a6nA{bnQ$@5VL z!-R6|ho(3RsoB`&oc4T6)xP8C86<|lpWsZGqF9a7-O=K>M^tL$;+}a>n44nGLKDEp zP;Vy#jHb*a0c#i5C-2a<7>=tA?XZsC>BSbWi)7r>ny7&omF5K_`Y9mlE&l9zQP-6I zAN8t@qcGCGP!*X7bWm1DQu)B$SAaab~ z-3{@Q2yhZk2V_g)Jn%L(CydWx*fxKM^GM%H5FsZ_w;BX#OI7vNE+as5;Is))mc^N= z^DKKj^ImKeF1%bQDC#)G=KJX;w#Ejh_*~1a(^me~>@^F9_JRnZg#<3C;OZqM<&LDf z^R;IQN$~-&zkv8{?ubCL^+&S zMkDnt>%0z7O@bV11*KU-yO1_T6?U3CVATL?hE}Fv+hq~MbP>8$|HH|g7mnD38=P9U ztmz$`ogSI?;J~Q^j?9KT(AFs784Zr$v)#|FiGtEBQN@6fc^@26(AHR-0|Ji_(pg8Y zFrB@EGiaLP=e8i8BZaqsi8DA^V_4aPpIliF?jW!ShVE3jBMELOs`qzZ2;C(Q;8u55 zHv8;Y$FG~?kS|=-{nn^=O`WMd6Ou0~JaHRteWAKm+vP!!*!1mUY&KO zZ0)Igrb=$#J41MPYi>z9qkDFLkMAlj{rKJ$wad5!^i*N4RYSp^d+Zp<5k}pV%u2?~ zS`Lk+#2;M_XR9z}rpZ<~y>GHKuHO_zcn&bBJxG0Sz$2;MPwz}_E3ay&r9GChMdYXE#%}L!6Ur?PEkKHQ+vMG;(U{HstuL) zC*n)mMmcQqjQ2L(hB+sC*%8OijnnI!jjpi1I2`iZ#!E5-UYOpNtDjS0P2w~S(-^J6$Yvp zpJxei{ihwVh?tWTH_5!_VzcDUMA2mw_n|d%^pybxlAhkZpQQ6(3$*k zeIl758(z|f$HA;awc^|)#gj!KUOXo?_M`J1DdPGW!VX7e>$DI8?ZzHv zciePN#prH@IfAYrvKMvc%Tprdl!T5s%6+zMhqm~btu&1E2)pVyqPWv+5dt`kWY4NI zIqHNY_+|N=ni703KS6P(YoCapV^Wt8jWnV=B9@H}4abq_-W|n&h^pgF{me(9{A>H;wDP4A+voWPiAsuI zi0-eROsTdY$St!*j}xyf(owP}QS9ps^}V5Y?d@Vqg0#{>F;{Z%d8B-;KK>KGnOlx5Q5*HwtgaLYV` zfe!=_Z&tq{p?G;5(b6t}5K~cK^fcI0yHo89z-0{#qze?1MlTLT3aTwWyE}NMr$6NjTh(@OiDlhu#MOqbCCF;Kke^ zUGco}l)}HfMh@VrgUj#0*3v0-pv2hKED~Nc>I}z! z;aje&?}9Y7iG^+|KuQR_Zm}#z*=T}qm>CuANgb=0Y$O1KR3G_wVgDMBxn-4YQFbDr z4)lN#wS^vbt}SDv(+S*8KWs|rBMH?FEdR<5dAN|9V=YbGDNOqiE#G%N75ZXiNOLu3 z?-8wd_0|~h&F7fR33+9tyBYB!e9L&LNmrKa+dkqzzyZSikfGIFjWg0!jQ5rvwYTb- z9YoAyR&QqoM~{J|%8INcP59DEs^-n%^X1{r{F;>%%N0`K0pi58@=M&-l`CH`3$3W^ zsGRqPW&rzwh2EdhpVlqJqY@*a;zJ<-+ma*5Lj9pno?=YF`m0Fy0InY4yl68qMF^zQ zAv->A6D!%|go0AA?JWM!q#X?IMPkOdv+Md;ClY{C{14+2PMYMLOW?#0m70yTTkLrp zKz;pRADDiDhB$F1G9DCp#U*w$#7Sb|;c>_Vi=f7Y72MN5o7sc`V{c3Rg%nZE%}Im5Z37;zRkbYxJ458JdG!rKp1u>+u}9bxWSqIk!btOZg1SJ@(VhPJKh*Vp zXG;FN)<9<`bE|);>bA=(j#&n5t;$+yj4re*WFt zV)fa!cej)jOfVLSP0J|ts3aCd^Bm+oC@2w9)F9!4`M${o4J9ktb{zng^E3^BW2e4ho^d%r!^|9K+1TFFpW7 zf`0t9j2SZNo`+qfk7mhg)uK%s=Q36U<|_##(?DqSbl(XTC~Y(UvLuw4q|d!!Pnnow zL2a$e)P?;8CcDDA^$r-Dklj{`3MCQoj(ou9!jbW=2(aay0us=PVguy9F8Da%3x_@R zGx-c&?vz_^V4yzEXy~+rfVzjFK6{Qw#**W^^B`IGBXaef&dl%YoeXRY0%R;3%HJGH z9|^3AK5~IQL6HwBo+?*4-WY`!A7{q*$9urw|0?Y(;Hp}>x9KkFR=T@Wy1N^RLpMhn z1VK8ayE~-2RJyxEly0Pz@_)EquUB7hec${zZakd*JTq(7teL&fp7khv;8Tg=c30uf z?sSt92!&F9{YI!dG};tdwcjJjjFHr$u>T3dWSprlx~anpv7wim)}G}tTRPMnf!cah zt(edJwKhffD6uW%-(%aEke8(q*S>7}g7f{+&ijPWaxJCWwjd{tg8R!&VZXWm?~W{O z=kOG$3UmS(*?#?sFhX75CKiC{^UlX`boS}fFX?Y|W+K3KVfTC-o`+|r-l!o46Lhjb zEu1eF*&Ix`(Bg~`pfkzI1>^7rVgyUKB_VWGiNjlngbS02VPJfu8t2Oi!EbvM!#w(V zAtD*gBqd|zQecbcvAyT{p=2T$`-d!y4GY&*VVecCi^+Y*`n3jotg@khlVk{XhS+Y4nNI-(QTp_d8#}7ELrUapTrAV=4d(j;= z{P)AcQIL|Pp>+*|p3{}S82a?&s#3(q3)o1ABqb*GE!+88tI8#Xk7|9fWU|t8 zJ0Gyk6Gb9b<&(#4qoSS%#IlS#O9*&#_eh`Mh#L*Pbz72iL3yD{^R}8YP6`EveB~|9 zkQD9svo1MUiOH&LAxUmPeR-)ilHXvYBiYhrcVXq(-5Y;wC+u7V9a|z-W${l0YZlQU z9r8mRNqS-h;$e;vZ0%m;#S`P#JS&vB^%Z2eaj70ta*h?XU2ni9Nn*#jThMd+eVnc3 zWJX4F?9d1qrye~r%}1Ora>z!I)z>05Z7L#m)7PSmLB)dc(3=Z0*V7`|tg~Pq+Y=#6 z(VGhr#G&1I@55iJ)U32#4*e1#{_TfoQ{yf<6r%HpfLvv^-9h8y?mQf1h;?6);RI9G zXw$`3O^soy;gD`vZ<{7ty?Ibh)dQ0vbFUrxQZ>OVs=nCy@b zW70hno$wwZNioSRicF~2!{r^8GgDIzZ>qAXXYH?N&Oe>7^+1Jbi-NcUqX1$9fGAi% zVh;X&-ezC0;jCoay&d$0ZB~&pc$dk-?R>iJ+))SLa#9h)M>2-1aNaMBngf-aBQ>|J zTV+<>b6jCp)YzxlJ&CbfrS}ffz5>VDk<`n{Jmy*M;JAY3+R^kY&;jWyFNZdO0&BKNusFs0^j))*m+xJFHSpr%qD^Chy_4Y)m0dxhyA=K}pUVGp=vI6R{3&+FYb@Gh0x-YGyVje#^0p~0kOJR| z>sYuVzN%H*P@qekc8bOh$eEa5w&Xi-ahXqt4uNm~l-1)FX8aKx(%@rE(#x@g;0N;T zBoY{F6vuBrm2_o2^96|_@-5p*Qyd$O9`HGj9O<<)U2hCW34%Ltso>*R>5IbgJ*Pjw ztd^CM>w^>_#+;xsZFngla$z+W6ePC5lxNrph7x>`C50LWl*;Q2cncP3QPfEmvm*o+ zh44&{m6!tQ0TT2^LAn%`JoG@;b0Ny~8bUhT8vL~yHy^jTAzEs_iCiHj3-1Df)o|J| zl>}Stc()n$p6j_7lOs1!(pWvgM3#ef7kK-5G6d@M=&^k?xfC1r)q+kQPM!J<8;#1w zeET78yIS3yi#B(vSl26}NS>G@R(hpE$(59*T(gyzRCf?XHI)2LX)rn?X|F(wA8nL| z3M?=POAV>;q-h*NtiG=C14c10a!m~|tmo5_cF;JJIbx2ni6YyqqWsAs;?2~9x4b0E zM8jGICdDtY;P$j4TYyV6DzPusohnsq7~n8gdC{eIEwE&%n&Ao}?Ur&)aLGs`b}N}F z(YXL0QfldePUBDY z4k%y_BzewFkoSof|TJ$#i0BLs0n_{*{=MZWux-q;V+#B{t z51H%`N;h*`n*w$Z8h?EtQVUHO_`tFA&YP@OUByPHu7Gly9YkL_T|F_u_E{$gyC}0Win$+lZTw-~&$0@I&yY%Xw5P^SwZxdR;tkd%UWW^u zA)t(x;^t3sOH_Q|Zi`d}qKuBar{!}U6SqasouQOFHdpNEdx;*cnO}juo(Sp|))Qtp ze40AKz!(FFil2 zzJc6jGTgh9C(zG7!q&!UZ5WiXo;9EO+^JHwBfPG-9`k$ur@dA83vgb<81O)H(3PYb z7#QgA4_A_37u^S*?p|@z(_flS`A3ILS>K30c_fNXh{hZcz(8U=heR&K3@_DzUKt?G z8sNu_5euIhtW`<-O2<_^|G9;plB4XH)>v~L6ow|i?#&-R(^!9v)qsxrzp;&1o zi|f&&OW2cs9#>HQ!^<@1(aWVRJj0ty49Q@Nm``;XvOmB8RAT%CDZ7z2T9Z!l@G9G`PsGTpN0U4@o6_( zx|~oyi$}K%2VHXRPOOUP4Ve1;iMi&l%60L`Yi6r{uhIH${`wC*+JTP@;YvbD|Pax)A3zyz&b zY=ULuSXrBkU%i)ohap|jWgM~ga{DpP|@vmF~A_n;t)OdSz@q@ zZ)q83xM=RW)LV5)oZHGynmfwY;PDP?6peud*r1RnXfGc!u1SyRhrGtuJw7lx2f%!e(To(bv-< zEd>{bqzz3x{j_j0G2lLZ3UKD>O3Y}l44BTZQx6N>iW{iH4|hfymOdp< zi4qmFRe$OTkUn0GSy(+0KMgZa)IfA9OJlH5az!l_f0{o{>5|OuqvUEbG3Hm701+cm zFmEdj2^$e3VH5JgC@aRny0V;R3QWDs*9l*=YPDdq?rpP@+{9j=IZOu3znxJs0%zZc7k@+^_b?1QE2hoqVqhL% z1&HLGN7r3MM;LyGZt^<3*0u+ZYJUCh4oDB03e?;K*!{R zloBI;hbhDO#-TUb`(j&XP=-gzRccNIQo(MDfIUWMgpjb~HcD_Sk3XMUOC2C&8_zX;oiv zT$pS35_rX7DJ9bJvK?9|F+X)r6y6-y^||}NRhm@5KC(j)gJsGxiZB2%cCoIWlb@sK zP#@jW*4i$zzDoo--)Zn=8oyozqC{2sZrRW}2}TZVo=RLF?t4hWuV&&)QM?Fil6 z{r;uV_7;vMe&L>41G2gz!lZeIVD&j`r4rVc8y%wWJG@K!9xTvX6aha9woJ~SU++)k zOhnfepxrEwc3u%DCe*&%Evh3f)QjSmqnU}VPP@bka#O2dXr6ulh9modf=W>RIcsfg zNvAqv;znqF_mn%v3Gk*gS4t=y#SJ95h#Hczuli7rUL5)p zIdrVhTMyfY*eS)FaSUB8^2H6SzzQ`%z1NP^hmdv>P$6qF zd`jq9QuKO4^s?4)gWM&cQY4)~LuA3ZvGZY{lv&6URi!f#aX{H?gK|m6Pq_^Q%B?e@ICgB6gwpAM5@UCjqH!dNC z7(@aO2r|YNb6ZzoSMiePG&is`hiT|yYs?Yw&!3{{M|#i5zRr2qf_@uO#jiHmMyNbXo|-g!MtPILi--_>@Y(i7xJnJ4c;9h})D zwqQ74AlSt_B$#lO6NddXZkkFGBarTsJP(caRAJXCHx(YZB)x6Pa-NmX1nbluKu5eRrh5o2kIEr3NGdFPE z6UipiJbB1;$$0oVNiVeRxzKI@1z7f&wX>`mjQ<<_V0dO`k?je=f}1FchMpXTY%oI} z`nLwWlx@^ciZxzv0p88z=|2HSyxY^KxbU|!=2G8P+R_F&XKXpa+}Mm2Jbce1fna>P zY+_g6CjuP`)^=It3<*h%bv$Yh4KR96Rj!|hn!yr4$T&TsSI)T>ZmRhh_#{?Oj63_y zriFFVIZrdl_KjtzMh?>Sz4gVKtqg=Q?|scP=<#F%nlLtmPS)?b=-xdz^5|B45ZMhD z9mszXzyn5qie=;&gZVi_^G2>U>aAgX{-bKCM#Qch@cb*&*Yb)myBS6&9LMxvkDFHL zRJuo_`3G4gqb%5!aO?uwbRbTg!nH8waYF-G#lHgFUuOvEQC*1UN3rK2`3X-6LdWAiGS+~ z`AYfS9$Uq&>;S ze7S6XwS~mV6+{ZU4MwGq!K_nBdpfJ7#_{%P^>w3{OB7)eRJc?Metr(<@d<+N7uM_3 zWxbs?5$t zMLumWc3Y5lHOwA<0s39|R-<{i{7C%PQ~G>Sc}4R2z=LzwmHhmn(CtXxm44Bh%<~gw zcN`<1iteMDPr_j(Fr4j9&&QPfd&P`fG zK0Lt->epQ#T9SoyVm%o?8!qtF<=fFI@bQJ&G~F(38eXp_N`~RWFJaN=z;0$e+GxsL zwWlF}&HvUm#Oh;W^w#99Lgt{{VuE2rb$g2SJKN2&gQX`$FonzS)sXf0&J6i&M?UF{ z_8TpCwqWT=`&WjI_CpWHa|3k_9F$`_<#Bjbwq=5X?4IUL7)U;Ao@McECZufJ$Ca|@ znb@X6dFZ{5E0W0JVxka#LYS{6&7EzV+kOS^Laz1l0Z+EeTL-0!6*>MnJzow z0Mo>L#&gD743(Q9nHr|D4Skip!OHA^rkb+qHKG5(V?sZ9Qux-cz=q20ODB7l(rEv* zmj`U};E9uWGt6UsPR0s<7)I;IcM1*9BK?${!l{;7{FWl6+261v-$Z)h?@(tsM$)kN zD@#E~vboDbCygoYoRQV3rHC+1$nHa{ZUf@L9~pSnRu;>kL&xqFX#E(OC~=GJ1a{*1U>2yfP^}+m@%V1>VomYs5r98Gha1N;IjAkp zhzYSW(YZ3wX+Iz0x+rh{{V7q{Heqj5Yhkk1s9QkTtk#YX;ab<>z`=67iEG8_;pSos zU6t!4Oj`(cQ%i_OmgDA=5B|-|VJ5yN`YK2c6S`-dpA^?6#cRXOc#f!fA^}?PWg-=u ztwOiW77p?$6|sSY@tN)7(Tt(tjQBc}(mPoC>lOXeY%aiw$^j&k>*2U@aXb$9^f>K2 zS7nU|!=tA1rgfs+O=mwu<9z+xsu+cOOvuOzB1#Fd z&d)vv(Spy7S7JYam;5yn?HqDiE6l+x_@o{53SwL{Mk^8bDcIV99q}a`#P}p!xXgzK z1HSkb&&j+JulUNzCLIOxdF&o#u1UzaF3EuR+Q#k8$;J{jOaglab>4FeO-Hs^yjTOb za^RPG&`Ywg?iTFAOkY)aDi>WbIIGJ&dLRiaaKJ4$%AN6~^N2O3kh0KA=&P#pJHw@Q!ZKFY3>Vxj4J1mhjl%xZr zJCOT=$XOpryrDh|`VKK|n>1?jD(zxiQKZq%FZ+nUu1DFZvxxoR8A?4m?iBgP)p>By zQmVT%t|15pIPPZo20oqrxX23c5+Z+K1|*J)DS?&58Gj{Oq;lr~MeB5vL>M_sJ$+1x z^pRI#m4LnD7<+^7of!a{`2!gJ1((uu|Fs~5Sd@WY?bwiDz4wJPO(}lR1Ijc`?s!@T zN4e*&*t}xMGGcmhaV{Q*R}C}eNA;`b*+oPBeQ~MfHic)T>6aD*x6+D=3oZr|^`}$y z0#g-R^>yq{7XJOY$oW1gQ7{&w7I_H@&?ze@S&+UQPK&Hvmbyz}@Plly1C7 zk-b;45pPa>OQU0~Otvo`QHf0e)c%Qqv9$?RX$J^Kv#%Qay}>i zc?=-D5Qjn=hXOMrY%b${`9ZC7y}S-O~BX58;0BYiXu^x~Z(7dp-n)DVoe^uYK!kW@kB5^T=aM`Nfe62Opes4965$-rZ za}|CfqjQUhz~ub8PU?=$J6Xm=8*OB$8T$esL9i@JCtiKAEE#5GIMyzTW34&Hcp%fP)(KE(NhqH#&-Gq72P(Bh6HnXa z^wurz;MqQG%Q+}?t>xPmutjaFSeAI0b9-s=MP!kQa3Q_p)iPb6MO1LrLauS^MN(49 z)6nDvj2x{!bc%)89J%Xu>e=@I(zjjVG2}yR_tYEFe z>VA3hLe54UKCd+_MmKJp^NK)*CMT_4iI5_SzsLpuR*#f2+q9cJPEBq%QjGXBjl4Li zB#Mjw7=6NGP#fr?X-UkM@!_p5HAiO%WNVbd79{`Zd&sg#n~02PFDDkxL9KM_sPu}S zO&yb(n4YV%&O98v-7EGrmx0(q?#vo3HrtxA_tp6&?}qsh(wnpesTd73HTPhhD~Wx~ z?xZu1={}Sk?vs#l$r?uF5Qwk6e?~4gldiFx&{(HSii3<NZ_i-2 z;}w24B2zmiw~#oyH7rah9^g5IA;~tM7>a~!MQ3=yDe|=P_ zS8-pW=GAh0oIZ_+i{`aT8f?+f)=3M8`-dLF$Z2$36;q~be&*sZiP=1LE%O2NlKQpN zIf7#T=0ShiWra+=Xw4q?icRN!?xTa5YZqSRfhBON7F>n;*ub5ZBCXfqGUtQEax3!j zR}C~}hT_V%RtrUjqKjwNJEXTB3;8QTiMw1AcDIzxA}gX?I}H=*SAx7nM}eA~f3 zz8TX;AhpbvZK7M^E2-Csg5wX-iM^wk&rw*!jxfm_Qu5PXX~7fgS|7;wdd!iG|6QO`7+Uaa0WX&GF)Sci*Gdmb z-D@=5t%Du)j`3LvpizaK_7|fQ3N?#9rs71x<$>rWi`W)IGtVv3opc_{c_N^lIA4BW z%k^rgUVwm`skV6F;K(DhO+m%iLjtP{k`GM}vM-%DI9cDsxoOMm5Q~V`aW9M0R)*TPW_Otx+D;&)6FAAw=U-HAwpN+YmJ)0Q5 zdcDmkIwnl^f)@!@0FXBk7MN(j0`!<>-e#zM=6j(yeuq>0%qS1e$W5#ynsy?>Z(q~? zIMrShH%$ttwevj45WQp~%wqn}RYAcjd9Vx1pczUdL2 zRC)(;I*%jbv$$9coL7a{FM>wZ0uH-RPvq1mYdWmktO?B0!Q#qVaujiM9zu!>-b$QF z?#85PIk7t?X`J&~^c3a!Z=ypU_-}RWVys4Qj6w5o zOC!?79zw~k%ckaw^Tx#c>8lNDwoISAKq=o4o^lY{T_4W!-3NKW{TR`}+zv(yFP67ZiR+~WX4g^m&w>6U4dY!PU~Tr*?FxzP!@r54G` zvUK5((#@xo8Lnn>?Q0&?uN`>tN$cArCd}{bx>pCplG_(iu10_rUn@HU7IVO0)piRG46tuPZR`uBjc>6_ITan_i}nt z9MfyD0|_*u!(QTzY$0(T7o-(F8THhj>sx+)bxDbv=AYbU)>B~l`m zM4DE4O;NL2z8yM=th%fL%(=_Khs;E!of}zraC}V&stZmQ`Jt8-^=^}+yltA%n)SXQ zA|Ii+iWxTG^!#yHkFXW-g}(2FOCo-jAIcF!&Qf}3x3gr`NBBU9Re z5APti>5)fm+g{a0Iby7fKDmUBor>wfg0SlK-1!cCWB2^iD*t7sfsOXr>2=_QhkHPs zh$vm$kyS#1a2|}#Yr{w3G4i{@UZ0;m4TNUalCvYINUj-)!R9Zn{HDmi@m&v zv9*Fwz1N3qFez}aQmqlv8$QM_gFUJOsin@ z#b+mwm5L%Kh;3v}7AvEV#)*J93zr{pIs$TVCZAAWxl><3H!jFdjk@8LUm(QYncy3@ zq9l68%7ix*ceo{r^o&~O9)lk+3l_+RD{j-SxdL;KJr_)FQtViKL>sbwGLP{H0LZUJ zuM2P~BswuE^}CLBB$4KOju(U!+Qh>@blpiTx;4!8w4|cjOXb4{)*KT8Gr9dw?a~h) z%p2PvT0Q`b2=3=Rd!au?z=JE^p3_o! zLw8V(qV-g85kN#bXR(=D)$^*)i%G(hKql3;Whii@uQc7l!EvXpw1S5giac`m9yEHggK?H#I5c~w6x2oKtND5`$~1E1#R8_OZgfG zzS=pLIg3Rj^B5w=nuCuF(St!!h5FueB%>%qz3Z2ZA6L^lYuiNBT*k#+ZnpD?;@z7x zJ~e82JNHqGWboukNe)r7?vG;o_>=X)!HvQ^{lJ6@=%h~qaB zV#-YwJ(#R0nyzXQ;Ea#So$i#zMm_3IDes_=-*1r`T3?gSrfqae!UcQ7HCL;ELH}st zLAH8octE#tE0%m{HuECEOZHY>NyK2ElrwVMeNjbj;teAPxZvTTVP%`j=6lb&5xlpA*g#fO5Qc%J92xf z*_v|k=1?^m@oonJ;ayLpj@M1s&H87BBK^Hbw6i4Uojvw>1d?J6wX@WU479VloQ(@e zuX`cGDq)%sTt~P+%L|>gah>OaHwZ)#oEAMqZaipfdgZ=kth4Hhyu9`La}V>D+AQ~Q%r1VSwvPT9=a$B7l7cgF(O??tF6W?- z>JW4m@hRb$S`FcpwTABn8=dfVDxxrKQkanZsot31rtuhi4Fd3`HZt#=9>gwN;&T+1 zL_ZXcME`|j~Mu6YQ@dZ9E1G;>5kll!0F-gv|E`+I-- z^FRLj?c}d$KY#p<+;_;DIS6PQKN=f9k@`2uHh#r6exP^6ZTu{4{B~^o@NE3Jbsvpj zzXS&QBcqu^N_lWj8Y7$5qpx#1{Bz6KPm9dF!2x?99A1c zm_*dEynxiVxPa9+MFA6-Wf#Utg%mCwVjr_|M%zYrX5Lnrgl!%oglJwOL_mP_EoZ*X zqI0+1V!4HxRF|_(E;qwx5AvHy#>+Z4qqOi(hQ?FGmh3>+( zyFGUfD^$ODPCe9Hv#J!UMWV_Yt3{z|535DEiU6xcx+)cGF?Wt3bh%{CHuOM!-!pW% zd`__Yg3cw#7#6cdwW2zpnMJ^^eN3np7Dz2ez375mZwZrA=b5@@hJ60neiyiMXNCr^@V7+Pu^Tu zXj|UgU}#&;Tojh4detnZr+yU|rl)FE1E!~LRVMXCr125$g=+UZ)qV5Owu-q?tZShv zRIF>MDnsgvDr3+GWV?Ox=PIzSBaAa?FLb+o3g?cnuKkTOX)Ydz-YQo;rnxZhzRQ{0 z3cXdYV#2&mHFoU2E1&y9dx6>=NpqpteV0G?8jBC*0?u8*=*t(x{ZW(c;uqlIs&lA_ zU8OBm&&-~3UG$bJ8a>OLV~WjDoqPEB#qII$hc7VK%h(rN((B38(dIE?8U5()Cln`` z%qMb2>olh8Jh9Q{v}B{&;r!j<{55#)o6IM1pdZ$gA;5ZaZy#G`bYXb3IXKxUPdNWZ zI6qc6e|$JUBAz=o%SqZ`UrkbUVQ6$=O0+pV*{F&{1|Xb&5YOET*Ik48WQz3!3eSBP z*L@ey9Us?SB%I$G*Bu|veTMZU0Q4`*NtyY&rSbawn?4Mq^$^w*cD9qW(Z0!!zR7_; z43l+BllA$&z8Yy#)GahNo}i=`gsTsnP%u|9K`pi2pDpneehsxQjsB8K7HlN(lkR)7 zWj^go#+kO%rG$`wy^QvJkbBY;J`jc%Uy2)FiWi^AOv?mNGw3O5O;c_PRCb5XJqf8Y%y|lN zO<^|6Vm8ZW#>H$Fgj+MqY{tcERsk47VKb{R88R46TJB0}^JC%bNFv%WSsCiR^AfyZ z@Y>h?JlFeauEDXnE_(8ne43r@CeRv@%3ha;kLSg0VdY~VgzL30kBy%pGo}~Ffvc>4 zai(bg(g54+mj&mDeA~aQh$P#jvYtefWA@&zDud9t`G%0hY^*`*F5Hmp@j;&Kx+23H zCTP@>(Fb3Ck`Q=L>ghcW%5&cY$`Q@@H_tJNS{OMw1At~v?M#4{_IA#{ZzIsK)Fe>H z^$E1?01m`pLfA4SXyA9ChrZGf#-tvz@J(PKwIT|XPU1`siG{D#alK{m$#+9ppL5oE zd~JRMOPtAPitdy#d~mUD0Ahv=n2r;mg_99-m8`&oFt=ZW3-H7fl>!{A7_VGm|7s@XrT(@ zToF9SeQpZX&uNTN5H86|ENd}+fIK;%z!P~8zE^Iki(XzxY^kf$!FmwTUd$ujDKAHy zh#x)1Y^77cN14qz(?XgZ$r>228E1*-oPX2&f!=bD$Ekxxch-q6#U!+5w9J`nI48hu zz@-}g!{LYeDudedUZ954u%2=CDvxS4|1)u38~UbXJ`6>D|ImXfguXO007h83D3Gkp z8Uvji|EPHB!Ix@vdMt$cHGBfqgonEr%haDpq{P9GI7HDgUlpYm9PR0in?xZdd~D?$ zC&*KMZSbJt0W&Xkyd2B`$6PWJS?(n{Do^J?bLyFvWAzZ4d(rc}ws&*F0#G?2DwHPN zWPbJ65Hh{$llq;>UJN(&LY+``M%xA~6)>r59<#A%9Z%hdYg=of)WptSY?|VUlfTyy zu}~ZRte;1}Kq1LhAU{rQ+dKG}I!;}$^Qn%WK}vfrX^`N>t~M>hhgH9$7cm2!PIMt>-x?oe0mNC++6PN;gd3ZGH(N#dpb zv0OK9d+c#r=);e>p_w1Ur}>@z$dO=?f|L)!#U>UeoHl#(ho>XOPT4#^GF^q`Dhd&4 zu#mfOvCyyKV7<=K71=Lyb|uF<-HSp>PbV0_FMmu(6a?#NIa$@v?dutTbY}Lbk&YBR zy?4NlPbWKP&QrwRC2cAieLehO$kM%j^vT$sgE3Q>dqcSG>wF5muylIQu}l5JU}nd9 zj?xV{T6-JvS0W*3=Emmkx}&S@!}STTS~aMHfttE~1d>5V9_tQB)9dG7j#Nn-J5<#9 z(chRI>$k+Hz~dOdWy&^jgWd_JP_&6WoIHIKWMQ;>chiAhSQ=(1@4EuVV!6cOG}`NX z#*l%oM^S!$>@79gR4j~Y>EFvAMUZDD4#slku}g?z=#Ezx2dlI8Aw^*7FwY>%r_TN% zas_`pOkdF{GN&@81r=2&8ZUq6K`Y|;lgBXppEZ!sqa0W;*F^+l!%EkIllyh5dJYBN zIGs}%uGwz3HvqisbQA4hq5%;&`?Z9MXN$89G@88}R}c}U$Fhl?CxUV5JmA1A1T_F_ z6a>*D^Ox5F=7J-Oln;vC4Ltd$cBMli_G7!H&j<{c)MGQjIm?VE{duu;C5XcTx|5ZuxL@YI0;l zkDtR@hCYFam7KurSl)dDbZ7N#4WoOO^|^^l7xuFqW%@~)+4lE9Is<;y*n-1th=Aakm z{ilB~d46=D-~KpNURXg|LR?jiQC{LZ0vOnR8pv;F+#kPDgQT=Uf$s;?g3vF4O@33N{b5Yq8#7+MB`hA)^@N~t1v>GMlIMpm{C7CN z5Ec^sjp1**?hAVFivy51sDefs%O70#qX8NuEAR_*{9fxn2E|v7Z+oAA_6*MRZ5&vT zrAI-pdzpf7CC^V-`oF;cMEAE%GCiy?L;;1+P*CK!SF`_C^8CtV{sZTK?PXZQUxJ%D z8JPi{f9U0VH*8o#ztIKReFN0f+}~;lI_CL3{#zWedpL4Y8+&KK9~xz9?hbzumfRun zKZt@@@<1%?Kd^i>`n%eGW%+|Z6=($f3x;H+O^kVvr$Uf`@(=&O@WS*T8GbhLSD7;L zJ!{7nkiUEaRh<6^$ZV&7gfwJfCYQD|u?NK!01zPVW&&`yzX16)6Owr-au5y}SQ*Ik zsefRq2mTwTU!zJLS0M#}>fR5ETtA}vhyM#yu3w{4tEYA$gACmP3e-QM%18Y(Di_DE zQTwcXC!ah31M>%^H~0}XEA3yPa{i3^zo8IR-QUZ7D3mDwB`V-sKm9mR?!)2LnJ7gP z$QzPC78Uvi1v=*WJ^x3n?~d??EB}K>;J%$OWU~^*;ty2fuvOb zfn|53qJ9e0ruU!~!@UsSx02_#SN$(pB%F+F|H-|rjW$0`f@t2kCNwyUH30( z{;l1foYpHifT-+2w)?R~VxYz6FQ$<{^|+j+ttC+04PXiYnEr#|@(%d18bCCvpcefY zH4&TsiAKR5s0y$%H8QsOYrFlg`x5+NwR`u)ZTTgO8K^TX?f$&J{u;^HlKd^8Ko-dX zRrklWhVtJ7{TAPU>*AjW*jHc&9>@%LSkUwaS{~jjT7D~eei?0lTf^_bKL|ShJZ*QO zmOo|y*%=yCd4_M`pktn&dH3Jq|5oR}gub8nI>qACvq7-(py>GHf@7uUpP}z{ipdon zOzchnVm?xSvZKcYsyP~n;>TsTF?T4ftVQaUU*ikk4*QK>+8V*N>h7J@F4vUsrN}jQC&M z;lZ-9X*~#=4`kyX2Rhi~f5ZPvFZu0?!c~m25k!LpqG1Cazm+^cFu#o52{J3ZcIy`C0J$I|=&y zza{xD|NY%Hzebv$m9W2~YcBj3^j~`aSBjtIdB0Ooy!!`=uXg#P$A4|0pJi{q<1?)M zH~hcwsQ(?r_}@5wyZxf{{+BerYjXT-@t>t+zd_~s1^+G1FRuT-n&&SsmhQvx&!Ugt z+2l6E1zKTE59=WN>jf8zX6XzkDab>GCF zMYO)t2_F1^(EYD3-;@0;_41tz`t(1L{S5xU9*p}9`8N-yMgsrUBJTH;Y2R;T-iPj= zlcs$G%JVb$8SkLKcoMgV&yyfD&{|;|8K&TpW%Pr z`~Mxj2>+kpf9|NS5%cG7;l3j}JpOCMUw%|K0o!&~M+eqAG%Pl5%1U3crg%0SW#T+YIB? zetT^8cA@=MOjb}%QcP4?g zp$ZfMOg4TK<=&bZse~%6r0kMK?SBM+1Lu+u6@|_kAbpMI#gY(t6-g5*t>heu&T}3A zoz!u-9=U~h%7cQXG^asMvy^R0eLSUKC<{SPsuzlu3q+B(>n{zn?>|EfyI zPCi!jEx*k-M*M$}mUJ<-m9cbop*OZMbau{C-Bd6xqByVuNr+?HLxZU-SllwH3}V|$-@zoTON810d1{2LDY zX5B*!@SO^pN+s0SwK{?Q6SFNrB6G}4BfH)T4LL_4LPL*l$uv{QoXxzW6XROd;?=us zqn|q@{oOy_$M`WTYq5aexHx0G>W68>iWTd_wvJ6D=O6BY24o#>nMIuBl&iq-GuCXi z$HBLmu3mvvcc{$|pzuY0enlUNgI>JBu$xA}SXco2IP-9TCmHWK(gY4MTVEu_)O?tn znQ3jCWXm#m8v3w3$IzTk5M!n4SVbV~tK+ePU4zC6);1e=ajlpTwf04Il~(0Ilc|gV z9`h3hk|w;lqg?KBuDvgsj9Q;IXU!JzhVgZEgetr>p`C6V%MrH(a^*VxItQLr@t1x$ z_+v_|rJh2F$Z=B}s}@A4I3um=7ra9l!(F--&UD;1!~HE$v5ei4ZBk<0)P zpb%@~1(-^^rglvb%GnFZn?VxKzVnQ6H$xnmK|q;|^Ew)2;v>1_Y8x@W;lT-?#7Z-7 zxPTkRo(nV(hR`nraH4V%r*=o%D7&kL#1aZZ`{j{*c^>M;);h`~xtXMd;uVy)W9j`w zF_YEDJ;O`5j(4&lTG0brcu*5l7)TSx5iS^?oiIS4Q12_`QBD(UaFS;`Jai_2BY#6? z#d!<$2-V%N=-`Ek$3&}k_gY3QN-C~*7;Oih=BD~h7w&pMJn7y-NL>t7OikU2ld1eb z>I9Rtf|JAO09x-DZuVHJDWuvH*zDCFVr~kr?HHUPIPm1A2)On1!>ehO)T?DW+GP1E zMc>m*&iC0vN8DT%qW41!wsX^B%BM^^aR)x(d}pA~bmv@Pl_k7n^9%S?m7f(fD2i%V z()U;}MoQF2#3L0(RHH)4jO$37J0cU9W`yi@pu%-L)1Rm^)9+U|m61x#(zd+7^+>47m-Z3JQ@^5m9ra_ehq0 zjAVzTWq_QEEd42UcdA?#zLBV%jGajULs+|Pq>!|k)5J3G=Gnu9sqc@6EBGGS4m6~I z-M(5ssC-!q@hD9a**OXpN9i6)J6Nb~gxGcvFbSD8W22~tfwT`f!1#123D!j&n+^zjr`^F&lLbGg7ME=^? zdgOq3F*!1eb!Im0EbWoP6dUE)MX1NZ2l%}LVoX~)hDqyWJhz2(BJ+0(QT01tPHrQ# zYAsD72aN+h%|Vf^47{q}E$Z@~*zBTv%epE!2Dp}OHBGYPYKw4G&%oUn@l6^_ePxX& zHe(#Eq~OVpa1TigO%;PE|mar~glCR!M0xE&nkLmPqhg|HqX6^j%K z=UaM*;kz~)%Z%U->iWWB8RZ8N)YlY6)6gQ(DJS;H$m%5}nU%n7F}@LbRrZQ7g{r2q zG0SypK{*;ZKpAU7u5ft`fputXFWPGE)PzVLEb(rFDX(w@0Z>x zJim7WBf@q`+S=G5CkX{W%}n>SGxLyyUZ9*9Gi4>;U=IqcA7>BO7%4h*MVG4TNsH z&NfXD$CHItDRVSau~C!QhmJ@^*+jyxSo0A(iPp|hjfjI?IDNV_w1KcmetEz5!4g!nSMKz#mKhl>~lGQ4a~<<~lq=ghAiF5Y3KY$SmuK8kHV zYK}hHK8|K~f^y}260yb}MvBxVfj~l?zDjCVPS8^-Vi4pINCqZ`CI)5(z)ZmZT}sJy zaEBF8ARr7VARxkj>A~_wR;I?kPa>jKY~4^*k$mi~>xRu>Ew!kFiJ<~4*~!!dYxAIj zh^cG?)KGdCi#lbS3)>ytMkDdNJ$PQgeFXWnx)RlR@%gs6UP!vbSTf*k)02cJhO<0# z(z2e$*3urHHaB0u9I&e+6fM!e8D95jKPv<5AH<4R64tRB;YAZ68VMO)Wxc} z18jUgmD}$}yfPIXghjEkytw z4YH=Q9kvwPu2buyBe8%yldU@O_FY+tIm-^bgwwuW4ff_pyz4g5Dt1#OjK`~h7LmTq zM_YRBVdCXt(XSfwjIm?`i!nD>k9ra_9B0W0<|@^wM0z6=l(!f;U(QghK5V9)9W8yMFPgTYEG zWTgReiE|>gwmO@<&w~;Mu0*4q>>?%G_o1l5@EtsOaR~a_>;>P1g#~k6IT37R3X}iV zg@|SC^bBK+8=FjSPy1|?_h1Yz-^NZ6p~H|Xb};&46HImMiq!~6w+pvC2q?Ep4bB;} zV)2&~7(oNlvEDt%5aBW&>|&Da84Y+^2<|<#>MmMQfA4isiFa3{+5my2RfS-3Qga7A z=6$*K2Q+AESI1jhl#}@jn=76*Q#}NSNAh&K`hA%iB>_$LwFs|+2U+*f$R2)|6fXrE z6;1fV^-nilhn;J~v)*>+M>E-Vo~n7|Ls|T2FBEtFXC`6YwclcJs*)Qpz!A))JMX}~ zDL(mDRl8gAy&Q?1*d1YSH6XD6V`-Gl|;0YwgZGO6!sp$rdSbS`CA-At6_op5?b8=IeqN1u#(;#Kwim zRFRaGT-)*xz0E>~OSAdp{PJewmN6Hi2nF;3bJGk;|F5r4c@h8qj{8eirXz_kc1 z_C4?tJ>r5#Z5LpHS{#z!>_Pq8MfNXtLD|L0)X-M&pKKVt z>rXR=AO`Vrl|L4*@>erv2>+WE8}oX0_@oopXof`snqn>LWF;tR=A*~N4N5^0==G~z zn+u!!sxx@?HUG_;0oPJ-g?k)6zDR184U-8J7(#eH_C*^Tn;4iF7y$u`VTeJPL0}N( zpbvpg+rYv7XQ}qvl*RR_gGBsox^nln;`}$WtY&EQ;diqft*WhzrjGP7;gn{GMc?j6 zT<51V_N6qVVgOc5FuDRtj3kVR2^6l@WO@B$f|{HO+xYC85k2{VaQ^3r@?BGJ!6?;M zo+9c83J;k*%~@V^3=AyU;-j0x*^;M>vzp1Yhn)?1e$b^LYwRY%e1IPW0WmEC^?{;; zgfP=bHk$!K_S-Vf$}KKjMTf-weUJUr03UdCECa_(e+cxFD1KBk+?!vvA{@Zxd?sFSd3P@Jxn3N}SQCc9Pk}OHZt!#5F zmf6gG(<1j_rZHM&r>8SWEIT_}U0agYUpMG$`4Y`}txEDQ9qkAG0=bbIDQ@LrH6*#y z!(c67KWg=6z)V1^WXg%!9`{Ul>4lR|VQ7Une_93dRJK#`v!l4`Tks5OtdU7}ubm+= zn|VCf!XRe<$XQ+MVmdI8Ip)F>T?KNCQg(S^@*Wwnq(FH%72Op|GMH<>FQ(j>+Z9TM zj(AT|HLF4+e>9u%#slHF@TH&Sb80}di%yS+|H$4$?XxZ3)5S^rIB)ov!`O@?^7(;# zO24Oj&PwgUXNF|PQ!=K`v@$~)GJrno2Qn0<(Lx@al$68UugoQ`Iqb?e#q?f;wF9H$ zAC~%{6SEYe(9FLGm>RDee;;`HdaZB$sM- zoW1gPq`k-hI96s%UyV}xu_8Gm(O@$~HG0wU^mlOdOt759236(e>yv$0l0PTcl1~~` zch3z==PJayo zZTA4YgMIG#6E@TimTJxs`z*%7^tl1-J(WLz0b$s-;cAxFg8rxl-f{Fp?s-)Ey4Wit zLHl~J{RKPB$EX-CG&4_;g>Y(Nu86fyavX&S;BpcVx@d?fW;l3xi?cF`sa2vM<4WMma8Eg3{e1)(EXSdCNA-WmkBKe{&(tSCw z(=O$ORIMej8;PMGn2v_avMZ8&`-84un1v=`alht79ve-W`1D=(-IypV|G2_m!PO<3EO>1AY)>%oLA9A0VDMuB3tMfz^M_YzHv(gqI*mtOB5i~fBcyG#B)KS^ z+ZF>bl|@6;m{icphWQVJi-Vz) zv#HZBn_aowETcb1q%Ut5-M=dd+uOMqTH2X9i5VKZ*gO5c@>GqHh55pW7DUn5)OHOy znQP|-=|C1x5n=A0te|A2q?bQc(Ru-dFJ(g$HeqIP&zHJ?`~p}R9HJC>O58A zTy|aS#$Nkb3$3`~gW6T}A-0UDcy%+(b@qC=!?p0l%h1^URK7F?c+!UE)i)*ebSsRS z;I0k-Ye1o5>Wy80Q|@HAh#-+r3Z)trA;bzk@nJE?AGPw^$i%BFM+O261cdUopr-lX zFKBA#B4KD}Vq@y``@;H@pcE(*TF9$KmP_%9n)P=uq4iYI78EKKWO2$C2h3GQlT>nH zawXhyUth7pu30fpFtdgog;wzsRVU2?M|Lqy-Ak{boo$8cbd~E ztLDn{v6M2A74p6vOAHRqF6xX`V(P6yEj|-H>py?4`<7+E`ElqWzCNHLO13JFy1ly5 zuD~`R+|52}tJCbF7woitbD<-rx4Ms^iiNOYB97&8PYBV&7Sq^Lr zL5{DhO|R-XM-|K9y*(95_3aIL$iTh$N2twfd{a)}{VRyYNfZWGfH6px4YPo_zfL0@ zLpXH;9YZcL$-OWGaQ?e06ZUqDU*9%G1F?XBDE_@Fe{N4G{9jx9ts09oY+Z0w-}#uC zxtZ6$TWOFDfGyHbtXn4q1I{Z%lbl5Zu~m-uLDGVkW)88PS#RMklYLN#3?Sa-kPr=q zp#?Egw=j~ljMVQZj(~FF5%+bExsso}JV2cMEbg7d?N;ADOfDolxn_Qrb+^-c-g%d{ zoc(wgIS8Z^)J$w4x)5S+ObUYPS?&POH(#7xpj4*gg7-;zTP=D+SAsHJm8~O^7E68SB!t%$(nvJgje<@K41xR>6w_oD||eK z>lS@Oa<>Mh+ia)Ts!Hq`Wi>(WhKSfY-WM*jFwS}x6#)+4d6S#LTx((`Y)Vv|S1Coup-!eOd2R)&X0yi* z>fhwjO_La^>sG6sA!3}AR+VT4$zr$gy|8D6Jk9RR3H8~|jIBTwv1Q|%3;QA2ELD;} zeng}{`ie1S9Ja;TE%WeP&ruSYa8~n~(-Y^j#M1_!TPjhIv^jW9ni&mFuQaK$otbz3 zq_nvhO{hL!mIqmV^z7J6cY`XGTTOGneob3fRK|tQ>vCbcfAW&&cwVxFv5^MK+@qj2 zOWIcp$+3BJ3}yTNiVfq3^+dOS6=U03_@r#pc7o9Smd0-h4QIp00x-hub-~h z{Yen?z6J#rxDWRdhTxureB~U#o|9QeMBt0kQ@pG@Jppjap&fCz65w@25pdlz`4F#g zwr|G`$iru{%pX0TO~}4{CaKQ}Ur?=6Fdyob?D(<`Uq8Hb-x{c#xmQ7Y3ES}vkYeN0 z|9SD!8q&V@35VT&n@v(L(`r#-MEcBC8iv35zLqyZa#T?FeP5J>1f6(s<;NFVk)HZt z@BC^*#f|U7GHPO0#^~UbnR7J~ptlF5$(L5BRND!jPf@Rw zq0Jvq`KYPGF@N4ZpP1TI(lK@bcT9&|{!PbS?J!jNC*cko}SfwKv0tpre0ts3(Lf^#osv>b1p=Gye zz>m@jdo1C5pnz}nPRbuZ;-aICOMNh22EWlIcwj_uT+g8eUQGDRH}Uf?qkL2TN4`bY1x*G{75t;5a%8^R%QlwjX;$Vd*P`{dz|#$ zuc-@6@PQ&YwdY56h$HP1ntgoP9KIE_Om5d8oEYd1=TpnQieWX{XFILJRkIOo?J=Bq ziVrJ%hpXDYDIKZ-_JgKP=NSSG=D7PdGfOC+g1OYcS@4gapL5^OSJr*OM$;i$Y|-gX zm~YiBJ`XoN0H-ay^tt!dDZbuq6N@F=u4{3f1taE-;*Pl;uEW-`m2WjurNL!ZS=7OKVuaRq9UZY`yqd`S|^Dr?%j2@(QNjB|R>uxr1$C(j0J z4D8&sv#P1nHxOHWT_ssSPP)3pGd6hktno9p2ixw27*ms3F~UGZvH~j_yw!xbLtb$F zoV$q_gX%0s#)P8wlPayx+&7bHHtRw%Izx1-N)lC_eG3gym?u+45L440f)98t=p9&NMz@yGH)%RWgJ`CQ4w-F#tq@hRHw z4Q%NUY(z`Ll*y@)YRt&>r^AoKg%$jTx>P2XcP6PTA;1=GPe{&bs>^#1K+^e3a&46FrG8$p)Z`>vv@AOWRm!9Q-$fCNR@`evn$#_p@#jz+eI{%ulTM|jO|=idvqnq< zkQ;{3kcal8x~92}vvI_N#Dw^H%nSG0b_j`M`mpev@iSbcxA}_rnsKE(ct1Tt4lf7bQIA zP<>9Yv$=Y=f-N+(czSda-f}KWbJdMJU8F2ONLvVj5^0v4Z&3)^d${MHd0)s}@Z>YFhNG(O90 zmHP-)*#_KWr(ksrZFIYOo?w!NESU4UZ1snsogfQT52WEh3H*Qv$T*&`U7}L=|NAL& zMHnBNyDdnHNc`LLF>(A7hsNLjfTG6#+wG=Q6A4T1bO&we;?d|?J=Q@@{RYZD`tC6OH8kMCy3J6%m zD2<3v63MGn5|H{tOitd?6A;|CdO{z;?*+Xn@S2Jx%NiGNu?>2_{cit8s2Q_vIgRDo zo5g%0lgszz`3JlKTp7@NM{YlQ8P@3|1WdQq)Eg3fKSWfJ;+C$#{szA%9eyN65(6~> zp`J`2(H`M5pWVR@0?80|X%-eMS6!B>sJxN{XE+=GJTk+Bq1M-YzWOTQ43@ByOHr^wM3q3BYwN&K@jD{|nZ z)1uRq^0Jwc#9cy+&tLnELl$ZaSCm>8QSRtx$77iqxC3l=1ZK&w^Qf8o`~nN`Y^_@Z zy3=>kNvAUw5TiKSRIq~5@$9!T`aT(+_21G7$7-gjw^m||mXSw0+62=SWu~WVaaHt5 zV@lH9l(l9SpEE`ceSfa7xBM)9iT&|GYN9yQ0%lT(Ng%d4vUnqw&!r#~f70UxVoF*c z>bc|=ypG}hiL{9{f~TKP+t!zK`qtb~7*{{ez7{DZ@(NUZAt0h{n9r!S=ahWQhCz66 zZsANy{b7k%D5e(Bo=v^)YRk9l|N|;&j(v@ z70m79Aw5;=s`Oo0=i*??q72ZN=P=g?Hf)09>86gvus1X&~R zCe(Fxb+mLeGrRp@!(c(sllJ>;DHme!K` z8jgSY@#R6Z9-WLq15Xcg!V*ec{hP|yjH3dY5}KXz)X-Fh(*wQNyRI#5>0*P9iDh}>4~zMd zjipQ;s;ba09eBR1&abo)*5!4vuNh!E^aUiN(-ayCSzAlCSjraK8CIr2+S$_CSXxDh z>^PuKi7M+n?moY9MJ%LscB%icQ2~Cei_pYroz)aJgJN ziS~8X8?YoDrkblZFzK|DceCpe?8Ibh?(DT>1%G~zZ>6!|c319hd3nFhM>lGGEd3=q zBK~80gfrj@L-WIzkuchdjhoY<_>i-XM+eTaBeK zH&F^BZthgA0yN$zFaxF;RaICe`>f5+5#x1M$SC^26E#WxW#M7P1IR=cai51_G)-?5Q zba}M3%hD7j33K5|wI*tNB&t6o>XViFVFQlrj1x*BsHMruOxPsg)pXFnGNXvBDBbcx zzz>A1V5fX7oc&&;IjGyJ+GStlkL^ZJ?YQgPtMb}yU-uktH~SB#&zdOg13braDBRqd zc|X9{$**s&-`<$XxjB3+Y(GuId9*fo;i)fZKV7ciS~s6@#&m8=QdW0cz1H^3&-Sft zKMkhg#L0~;lU0=XcD57j?DXVL;?-eLBd=Bhq?dn7L@AIm1hP2&1xQzF5rUGuRqQ>7 z0FDKTe&Gv$EKrs_CRnNe0=3lPzFfLAjjkSj3$4KTjD04?$AbhQZ>b#cQc0hkvhL(JPaUsX`!VG(mH)lgn7G2C-XOpeQ22ugTUMs;yLTcyMh-w6d=$6GAgDB~3}W^c@Hi3h3=fTtUofvx2ODRO zoV%5(xVdF0cagEBT8CWivySzqnI!dK(n^BwW?+-jK}t9h`zrqU(E72foQQzmRgy!$ zf#yK!p_qMGcD<0YfVz#mi7#D~U{6$}4?b=D2Z{)ZY#Q=4cHvHHvFXBq7WNTy!Dshx zD-Ip5=!4g)%B&;RXC6$#^Y{8C-Rz|a3VWJ&9p=ETHVBRSQg|c2AsORL2 zl0#)uSX&x0HT0WyPq;!iL*L#lj27V9*+hx7UIx8@#MF46wMhtzWIx={;sfp-Ej5E* z3tT1C_#+c7$?&M?!uqj^4dW~_wU=Q;ce>20T~R&Gc9@iX=b*=88fonTt+CJ9J~C@A z(*;6l^9p*_uh-w%nrZEuAYshD*AvagYAG{q?j|`o>FF@KKB*gD3vWqW2Bg9I0@}C^I{^3I&(* zdMDRpP_A>mGB~ek#(HSr*(!qXjL&^^u5*?Y z181#?tzc6-HNBlf%FT(g4_-0ip^d6*W_0{>FTMz-Q%)v zIcTomRXlw(^XRWaaq$w7q|!y7bnwuixVS9@EEvet+@^aF>V%f@5*zB9Lq|{Xm4?Fc zNm*Opw?{&Jm?)9z)k9il9cDNAVPKhS9S^1gR+K!MZ z&9da@EHp0hYDvw3#Y`TwQuDLpoqh~!5lDA>PibQE`a#Ewx?O6~; zLk*@p*~XqLbgXLm+*ICTZ5v|r`>w2spUC9GB{#M9mh5uY5xKZLCYvsXb%hsKtjE99 z3ntQs#v{j5xf!e#n%^%?JzQjMTD}%+7-x?!Y9Sn|;O28_LVk3jJ!JGIN}~xo5 zFVk3RSPxs7H!pI4FNS_?w_uv|HQrI$es=nnG^FSf^8Fe9Rfvx6kINxmsRU^gweo`! zmkO@;gLpp_5e+;Wbw24VSNE{q(PQ(E*GCG?cC=G^rrTr6riMUYtM}+W1jvnLo`=X! zLInrNagoYVu?V+Y5tBJxKe+Mh{_nQ;PTa^6pmp&NQ_(;ji5UHI)~q+CU>%lub|Emdt3gQL+llD?}|E*!QXOb;+NdnjD{@jGAew}xy@wfWUU|VYK1^%Rds_@w-+`jKO z?_PjIRftQNGK(GF2hJMFDaxrkw#CizX5NF%?_}!j-e8p6wQS~P-jg4oa*gk(^jo%$ zrKQ+iigJEVD5kaJXO-6RAg`2rUzSizkI?%5aQ9YNQ^~}Gn<^!6=5~f^o_=1mr<>KBvftUKVQXPX|eO?s)J& zihJvo_8M_`W_)sKqU~*_e3X=$E{zE%i&v1Ht_D|p0OU%KB%y;_B|=aAF4u!?!B_Xn zoza^*UPlWK9mpnRp0^JbcrkTW6cj1-l`E&TtFovGk+)Ns>#RPAE=a4me1ptRj4s9?a6fmOiCV5CyL0;7Wsq#2|V7;q?X z7+`e#&S6PCxK`k)eU-ptXf$zYR`4dpniwp2V?d#S6n<#{Cg!S{((NQdAKz8Za903b5}1^8suD5WQN0Do6>ItXhGo`;cdLNdQ&AJOHtm z4#1|j)j0GD^@FJey#t{GzXSLOv^$AAsymB2?7i}Z+6DWC>ji=Xjyr`rraOl_qC0~- z!4kp?TnB*{&=0N_JTD|Ks2|`hpli@)AZ~$(+Ja1Y4)1&E9T4xOFOVG=S`fX^yx_cW zPatxD?gHflR(U+Y z9o0MfX#_F25Rod(mUI$X~3regb`5ROY9KCrZlEwotWxDNdqy-$acL& z3nbm6R12pAl?|O7h;Bfp0ZtEs8EEc54?uCCa%Xo(aHrP*r3dW;IMrfQf|3AW9LQQ= zDk0Sat$QFG=&-q;z(-~ctse})yyXjIV83hmL?jF|{K0(59|LV~}+oE~b! zB-TN2fF9*fD5a43?qi&b1rw3?PoM{)&#upoCfrHQj}nhYDlEwSFVJcHKERC9BIIvS zdM6+e5@1q#H(mlit}q1${x`@8$nnn!)c4a5(D&C5-1M7*0k2Yk>=gzW=8-G-W4rjt zO@X%wA|8Ny=Mu;OfdYV#W^#$(vHuEzEfpW3GV=h8jNmfhvpp`1ptuM^D6FJ{!v798 zU`P?Uc~I{MM^Hc|r#^wf|9=B7WG3uH{XnEY@d1kfR6q!!#ec&A3=JtnL~cdY8-HXp zsO;1f82s2jn{f?^qKB zg@1z^2-JpYEQ`Ppc8i~IAY1%MY@CaLeUzK`D?CbB2Ve~acCBzuL3Z}P0lfFr@8F#U z-L`>685AO9@e>X*WWUo52#~O{3JL!etiRg9v=S5{&&TX;M_8F(y+fa`-hDuCx17V* zs?8u@dWCxVWqa!-)>XjuZEINOE%u7^e{FBM*jt720TjE|W=8Fq-3P18f}D>;0tq1u*Mn3OPtPIiDY5kq--~A*f@9{cR?T zxvTl4*YorKAOjFdYD^v^N!65LxFKtVHB%7N7bfzv#eRpt9r8iCm{nXi&NHVdXA>^+ zue+U;{_uq5#X|BRO?`2X_S+6HZYit z58|DQ?k^Mt5b=&?_+H(a)Z^L)rtmHZWP=dh;ut2!c7tY|3KK`_g~Ayf%9i#5Zd2$( zYP*%)-f1=U^S!&738_ET$cSmSOVYP#VR)t$HpxFyeU=RIDR6hERO`fh`mWd#R%AWFcd(QSd7N$m5!2lBv;yazHo2mZqOD=M&0wmWlAXqZ0KMdVio z@Owt0_e#s#F6BzbE;E+cvPOMhMepDX?|Nre=!GnsVCi@%6+)&sN?#$1d}?=5>7b{d zcjSXo?xvNbe8mqU8@2*1bf(8t&dbEgU{st{6#khC{eODb{73CCp_l(Fv@5-Rm8*{{(gf07NoMQ;2f*`I#dzmokL^zkQ|-CIrn z6WL!wKz?QW)m8jYwh;J#X8W7t_^*_|I%)q&sgLl_lz(yA{*&zQ4e6)1;cw|@i`YT^ zJK2AH5C6Mi{OW!92Th?r)?4)PuT}Ot$v^ud{#m|%_WS#j`r&_5|LO(!EAg*haDNhu zVEk*DfAxv`mGswR(LYJU2>+GzpAJcXCI0oy=uhIWB>zhMmlLF4`F + diff --git a/src/Logistics/app/src/main/assets/em.js b/src/Logistics/app/src/main/assets/em.js new file mode 100644 index 0000000..a5af1ed --- /dev/null +++ b/src/Logistics/app/src/main/assets/em.js @@ -0,0 +1 @@ +!function(e){function t(){this._events={},this._conf&&i.call(this,this._conf)}function i(e){e&&(this._conf=e,e.delimiter&&(this.delimiter=e.delimiter),e.maxListeners&&(this._events.maxListeners=e.maxListeners),e.wildcard&&(this.wildcard=e.wildcard),e.newListener&&(this.newListener=e.newListener),this.wildcard&&(this.listenerTree={}))}function s(e){this._events={},this.newListener=!1,i.call(this,e)}function n(e,t,i,s){if(!i)return[];var r,l,o,h,a,f,c,_=[],p=t.length,u=t[s],v=t[s+1];if(s===p&&i._listeners){if("function"==typeof i._listeners)return e&&e.push(i._listeners),[i];for(r=0,l=i._listeners.length;r0&&n._listeners.length>h&&(n._listeners.warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",n._listeners.length),console.trace())}}else n._listeners=t;return!0}r=e.shift()}return!0}var l=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},o=10;s.prototype.delimiter=".",s.prototype.setMaxListeners=function(e){this._events||t.call(this),this._events.maxListeners=e,this._conf||(this._conf={}),this._conf.maxListeners=e},s.prototype.event="",s.prototype.once=function(e,t){return this.many(e,1,t),this},s.prototype.many=function(e,t,i){function s(){0==--t&&n.off(e,s),i.apply(this,arguments)}var n=this;if("function"!=typeof i)throw new Error("many only accepts instances of Function");return s._origin=i,this.on(e,s),n},s.prototype.emit=function(){this._events||t.call(this);var e=arguments[0];if("newListener"===e&&!this.newListener&&!this._events.newListener)return!1;if(this._all){for(var i=arguments.length,s=new Array(i-1),r=1;r1)switch(arguments.length){case 2:l.call(this,arguments[1]);break;case 3:l.call(this,arguments[1],arguments[2]);break;default:for(var i=arguments.length,s=new Array(i-1),r=1;r0||!!this._all}return!!this._all},s.prototype.on=function(e,i){if("function"==typeof e)return this.onAny(e),this;if("function"!=typeof i)throw new Error("on only accepts instances of Function");if(this._events||t.call(this),this.emit("newListener",e,i),this.wildcard)return r.call(this,e,i),this;if(this._events[e]){if("function"==typeof this._events[e])this._events[e]=[this._events[e],i];else if(l(this._events[e])&&(this._events[e].push(i),!this._events[e].warned)){var s=o;void 0!==this._events.maxListeners&&(s=this._events.maxListeners),s>0&&this._events[e].length>s&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),console.trace())}}else this._events[e]=i;return this},s.prototype.onAny=function(e){if("function"!=typeof e)throw new Error("onAny only accepts instances of Function");return this._all||(this._all=[]),this._all.push(e),this},s.prototype.addListener=s.prototype.on,s.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var i,s=[];if(this.wildcard){var r="string"==typeof e?e.split(this.delimiter):e.slice();s=n.call(this,null,r,this.listenerTree,0)}else{if(!this._events[e])return this;i=this._events[e],s.push({_listeners:i})}for(var o=0;o0){for(i=0,s=(t=this._all).length;i + + + + + + + + + +

Simple roslib Example

+

Check your Web Console for output.

+ + + diff --git a/src/Logistics/app/src/main/assets/roslib.min.js b/src/Logistics/app/src/main/assets/roslib.min.js new file mode 100644 index 0000000..506562b --- /dev/null +++ b/src/Logistics/app/src/main/assets/roslib.min.js @@ -0,0 +1 @@ +!function n(r,s,o){function a(t,e){if(!s[t]){if(!r[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}i=s[t]={exports:{}},r[t][0].call(i.exports,function(e){return a(r[t][1][e]||e)},i,i.exports,n,r,s,o)}return s[t].exports}for(var c="function"==typeof require&&require,e=0;e>2),s=0;s>6):(s<55296?n.push(224|s>>12):(s=65536+((s=(1023&s)<<10)|1023&t.charCodeAt(++r)),n.push(240|s>>18),n.push(128|s>>12&63)),n.push(128|s>>6&63)),n.push(128|63&s))}return m(3,n.length),p(n);default:if(Array.isArray(t))for(m(4,o=t.length),r=0;r>5!==e)throw"Invalid indefinite length element";return i}function M(e,t){for(var i=0;i>10),e.push(56320|1023&n))}}"function"!=typeof d&&(d=function(e){return e}),"function"!=typeof y&&(y=function(){return A});var e=function e(){var t,i,n=x(),r=n>>5,n=31&n;if(7==r)switch(n){case 25:var s=new ArrayBuffer(4),s=new DataView(s),o=T(),a=31744&o,c=1023&o;if(31744===a)a=261120;else if(0!==a)a+=114688;else if(0!=c)return c*U;return s.setUint32(0,(32768&o)<<16|a<<13|c<<13),s.getFloat32(0);case 26:return w(g.getFloat32(b),4);case 27:return w(g.getFloat64(b),8)}if((t=S(n))<0&&(r<2||6this._maxListeners&&(l._listeners.warned=!0,f.call(this,l._listeners.length,c))):l._listeners=t,!0;return!0}.call(this,e,t,i):this._events[e]?("function"==typeof this._events[e]&&(this._events[e]=[this._events[e]]),i?this._events[e].unshift(t):this._events[e].push(t),!this._events[e].warned&&0this._maxListeners&&(this._events[e].warned=!0,f.call(this,this._events[e].length,e))):this._events[e]=t,r},r.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var i=[];if(this.wildcard){var n="string"==typeof e?e.split(this.delimiter):e.slice();if(!(i=_.call(this,null,n,this.listenerTree,0)))return this}else{if(!this._events[e])return this;o=this._events[e],i.push({_listeners:o})}for(var r=0;rt.secs)&&(e.secs timeService = + new Service("/rosapi/get_time", Empty.class, GetTime.class, client); + timeService.verify(); + //System.out.println("Time (secs): " + timeService.callBlocking(new Empty()).time.sec); + + Service serviceTypeService = + new Service("/rosapi/service_type", + com.jilk.ros.rosapi.message.Service.class, Type.class, client); + serviceTypeService.verify(); + String type = serviceTypeService.callBlocking(new com.jilk.ros.rosapi.message.Service("/rosapi/service_response_details")).type; + + Service serviceDetails = + new Service("/rosapi/service_response_details", + Type.class, MessageDetails.class, client); + serviceDetails.verify(); + //serviceDetails.callBlocking(new Type(type)).print(); + + Topic logTopic = + new Topic("/rosout", Log.class, client); + logTopic.verify(); + + /* + System.out.println("Nodes"); + for (String s : client.getNodes()) + System.out.println(" " + s); + System.out.println("Topics"); + for (String s : client.getTopics()) { + System.out.println(s + ":"); + client.getTopicMessageDetails(s).print(); + } + System.out.println("Services"); + for (String s : client.getServices()) { + System.out.println(s + ":"); + client.getServiceRequestDetails(s).print(); + System.out.println("-----------------"); + client.getServiceResponseDetails(s).print(); + } + */ + } + catch (InterruptedException ex) { + System.out.println("Process was interrupted."); + } + /* + Service topicService = + new Service("/rosapi/topics", Empty.class, Topics.class, client); + Service typeService = + new Service("/rosapi/topic_type", Topic.class, Type.class, client); + Service messageService = + new Service("/rosapi/message_details", Type.class, MessageDetails.class, client); + try { + Topics topics = topicService.callBlocking(new Empty()); + for (String topicString : topics.topics) { + Topic topic = new Topic(); + topic.topic = topicString; + Type type = typeService.callBlocking(topic); + MessageDetails details = messageService.callBlocking(type); + System.out.println("Topic: " + topic.topic + " Type: " + type.type); + details.print(); + System.out.println(); + } + Type type = new Type(); + type.type = "time"; + System.out.print("Single type check on \'time\': "); + messageService.callBlocking(type).print(); + } + catch (InterruptedException ex) { + System.out.println("testService: process was interrupted."); + } + */ + } + + public static void testTopic(ROSBridgeClient client) { + Topic clockTopic = new Topic("/clock", Clock.class, client); + clockTopic.subscribe(); + try { + Thread.sleep(20000);} catch(InterruptedException ex) {} + Clock cl = null; + try { + cl = clockTopic.take(); // just gets one + } + catch (InterruptedException ex) {} + cl.print(); + cl.clock.nsecs++; + clockTopic.unsubscribe(); + clockTopic.advertise(); + clockTopic.publish(cl); + clockTopic.unadvertise(); + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/MessageHandler.java b/src/Logistics/app/src/main/java/com/jilk/ros/MessageHandler.java new file mode 100644 index 0000000..f7cdd4d --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/MessageHandler.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros; + +import com.jilk.ros.message.Message; + +public interface MessageHandler { + public void onMessage(T message); +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/ROSClient.java b/src/Logistics/app/src/main/java/com/jilk/ros/ROSClient.java new file mode 100644 index 0000000..f3e8f60 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/ROSClient.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros; + +import com.jilk.ros.message.Message; +import com.jilk.ros.rosapi.message.TypeDef; +import com.jilk.ros.rosbridge.FullMessageHandler; +import com.jilk.ros.rosbridge.ROSBridgeClient; +import com.jilk.ros.rosbridge.operation.Operation; + +public abstract class ROSClient { + + public ROSClient() {} + + public static ROSClient create(String uriString) { + // if we ever implement other ROSClient types, we'll key off the URI protocol (e.g., ws://) + // we'd also have to abstract out Topic and Service since they depend on the ROSBridge operations + return new ROSBridgeClient(uriString); + } + + public abstract boolean connect(); + public abstract boolean connect(ConnectionStatusListener listener); + public abstract void disconnect(); + public abstract void send(Operation operation); + public abstract void send(String json); + public abstract void register(Class c, + String s, + Class m, + FullMessageHandler h); + public abstract void unregister(Class c, String s); + public abstract void setDebug(boolean debug); + public abstract String[] getNodes() throws InterruptedException; + public abstract String[] getTopics() throws InterruptedException; + public abstract String[] getServices() throws InterruptedException; + public abstract TypeDef getTopicMessageDetails(String topic) throws InterruptedException; + public abstract TypeDef[] getTopicMessageList(String topic) throws InterruptedException; + public abstract TypeDef getServiceRequestDetails(String service) throws InterruptedException; + public abstract TypeDef[] getServiceRequestList(String service) throws InterruptedException; + public abstract TypeDef getServiceResponseDetails(String service) throws InterruptedException; + public abstract TypeDef[] getServiceResponseList(String service) throws InterruptedException; + public abstract TypeDef getTypeDetails(String type) throws InterruptedException; + public abstract TypeDef[] getTypeList(String type) throws InterruptedException; + public abstract void typeMatch(TypeDef t, Class c) throws InterruptedException; + public abstract Object getUnderlyingClient(); // for debugging + + public interface ConnectionStatusListener { + public void onConnect(); + public void onDisconnect(boolean normal, String reason, int code); + public void onError(Exception ex); + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/Service.java b/src/Logistics/app/src/main/java/com/jilk/ros/Service.java new file mode 100644 index 0000000..8de5db4 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/Service.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros; + +import com.jilk.ros.message.Message; +import com.jilk.ros.rosbridge.FullMessageHandler; +import com.jilk.ros.rosbridge.operation.CallService; +import com.jilk.ros.rosbridge.operation.ServiceResponse; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +public class Service extends Message implements FullMessageHandler { + private String service; + private Class responseType; + private Class callType; + private ROSClient client; + private Map calls; + + public Service(String service, Class callType, + Class responseType, ROSClient client) { + this.service = service; + this.client = client; + this.responseType = responseType; + this.callType = callType; + calls = new HashMap(); + } + + // A result can only be returned once; it is cleared from the hash before + // being sent/returned. This is to ensure that results do not accumulate + // indefinitely. If callers need to keep these around they can set up their + // own hash. + + @Override + public void onMessage(String id, Message response) { + //System.out.print("Service.onMessage: "); + //response.print(); + CallRecord call = calls.get(id); + if(call == null) { + System.out.print("No caller service response"); + return; + } + if (call.handler != null) { + calls.remove(id); + call.handler.onMessage((ResponseType) response); + } + else { + call.result = (ResponseType) response; + call.latch.countDown(); + } + } + + public String call(CallType args) { + return callImpl(args, null); + } + + public void callWithHandler(CallType args, MessageHandler responseHandler) { + callImpl(args, responseHandler); + } + + public ResponseType callBlocking(CallType args) throws InterruptedException { + return take(call(args)); + } + + private String callImpl(CallType args, MessageHandler responseHandler) { + client.register(ServiceResponse.class, service, responseType, this); // do this once on creation? + CallService messageCallService = new CallService(service, args); + String id = messageCallService.id; + CallRecord callRecord = new CallRecord(responseHandler); + calls.put(id, callRecord); + client.send(messageCallService); + return id; + } + + public ResponseType poll(String id) { + CallRecord call = calls.get(id); + if (call.result != null) + calls.remove(id); + return call.result; + } + + public ResponseType take(String id) throws InterruptedException { + CallRecord call = calls.get(id); + call.latch.await(); + calls.remove(id); + return call.result; + } + + public void verify() throws InterruptedException { + + boolean hasService = false; + for (String s : client.getServices()) { + if (s.equals(service)) { + hasService = true; + break; + } + } + if (!hasService) + throw new RuntimeException("Service \'" + service + "\' not available."); + + client.typeMatch(client.getServiceRequestDetails(service), callType); + client.typeMatch(client.getServiceResponseDetails(service), responseType); + } + + private class CallRecord { + public ResponseType result; + public CountDownLatch latch; + public MessageHandler handler; + + public CallRecord(MessageHandler handler) { + this.result = null; + this.latch = new CountDownLatch(1); + this.handler = handler; + } + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/Topic.java b/src/Logistics/app/src/main/java/com/jilk/ros/Topic.java new file mode 100644 index 0000000..815ea2e --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/Topic.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros; + +import com.jilk.ros.message.Message; +import com.jilk.ros.rosbridge.FullMessageHandler; +import com.jilk.ros.rosbridge.operation.Advertise; +import com.jilk.ros.rosbridge.operation.Operation; +import com.jilk.ros.rosbridge.operation.Publish; +import com.jilk.ros.rosbridge.operation.Subscribe; +import com.jilk.ros.rosbridge.operation.Unadvertise; +import com.jilk.ros.rosbridge.operation.Unsubscribe; + +import java.util.concurrent.LinkedBlockingQueue; + + +public class Topic extends LinkedBlockingQueue implements FullMessageHandler { + protected String topic; + private Class type; + private String messageType; + private ROSClient client; + private Thread handlerThread; + + public Topic(String topic, Class type, ROSClient client) { + this.topic = topic; + this.client = client; + this.type = type; + messageType = Message.getMessageType(type); + handlerThread = null; + } + + @Override + public void onMessage(String id, Message message) { + add((T) message); + } + + + // warning: there is a delay between the completion of this method and + // the completion of the subscription; it takes longer than + // publishing multiple other messages, for example. + public void subscribe(MessageHandler handler) { + startRunner(handler); + subscribe(); + } + + public void subscribe() { + client.register(Publish.class, topic, type, this); + send(new Subscribe(topic, messageType)); + } + + public void unsubscribe() { + // need to handle race conditions in incoming message handler + // so that once unsubscribe has happened the handler gets no more + // messages + send(new Unsubscribe(topic)); + client.unregister(Publish.class, topic); + stopRunner(); + } + + private void startRunner(MessageHandler handler) { + stopRunner(); + handlerThread = new Thread(new MessageRunner(handler)); + handlerThread.setName("Message handler for " + topic); + handlerThread.start(); + } + + private void stopRunner() { + if (handlerThread != null) { + handlerThread.interrupt(); + clear(); + handlerThread = null; + } + } + + + public void advertise() { + send(new Advertise(topic, messageType)); + } + + public void publish(T message) { + send(new Publish(topic, message)); + } + + public void unadvertise() { + send(new Unadvertise(topic)); + } + + private void send(Operation operation) { + client.send(operation); + } + + public void verify() throws InterruptedException { + + boolean hasTopic = false; + for (String s : client.getTopics()) { + if (s.equals(topic)) { + hasTopic = true; + break; + } + } + if (!hasTopic) + throw new RuntimeException("Topic \'" + topic + "\' not available."); + + client.typeMatch(client.getTopicMessageDetails(topic), type); + } + + private class MessageRunner implements Runnable { + private MessageHandler handler; + + public MessageRunner(MessageHandler handler) { + this.handler = handler; + } + + @Override + public void run() { + while (!Thread.interrupted()) { + try { + handler.onMessage(take()); + } + catch (InterruptedException ex) { + break; + } + } + } + } + +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/AudioMsg.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/AudioMsg.java new file mode 100644 index 0000000..29c1e41 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/AudioMsg.java @@ -0,0 +1,9 @@ +package com.jilk.ros.message; + +/** + * Created by xxhong on 16-11-17. + */ +@MessageType(string = "std_msgs/Int16MultiArray") +public class AudioMsg extends Message { + public short[] data; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Clock.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Clock.java new file mode 100644 index 0000000..09505fc --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Clock.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "rosgraph_msgs/Clock") +public class Clock extends Message { + public TimePrimitive clock; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Duration.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Duration.java new file mode 100644 index 0000000..c08953b --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Duration.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "std_msgs/Duration") +public class Duration extends DurationPrimitive { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/DurationPrimitive.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/DurationPrimitive.java new file mode 100644 index 0000000..35ae9bb --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/DurationPrimitive.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "duration") +public class DurationPrimitive extends TimePrimitive { + +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Empty.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Empty.java new file mode 100644 index 0000000..55d5a39 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Empty.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "std_srvs/Empty") +public class Empty extends Message { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Header.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Header.java new file mode 100644 index 0000000..eb3d856 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Header.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "std_msgs/Header") +public class Header extends Message { + public long seq; + public TimePrimitive stamp; + public String frame_id; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Log.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Log.java new file mode 100644 index 0000000..2c444d7 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Log.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "rosgraph_msgs/Log") +public class Log extends Message { + public Header header; + public byte level; + public String name; + public String msg; + public String file; + public String function; + public long line; + public String[] topics; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Message.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Message.java new file mode 100644 index 0000000..0b9f968 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Message.java @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.Map; + + +@MessageType(string = "message") +public abstract class Message { + + // Some requirements about message types: + // - It must have a MessageType declaration to be recognized on inbound messages + // - Every field must be explicitly designated as public + // - Every field that is not a primitive or near-primitive must be another Message class + // - If there is a non-empty constructor, you must also have an empty constructor + // - If it is set up as an inner class, it needs an explicit nullary constructor + // (note: I have seen an inner class otherwise fail, I have not tested it with the explicit constructor) + + public static void register(Class c, Map messageClasses) { + try { + typecheck(c); + + // Must register the class and not have duplicate + // This is not recursive because only the top level message class + // needs to be determined from the string - others are top-down. + String messageString = getMessageType(c); + Class existingClass = messageClasses.get(messageString); + if (existingClass != null && !existingClass.equals(c)) + throw new MessageException("Message String \'" + messageString + + "\' is assigned to two different classes (" + + c.getName() + " and " + existingClass.getName() + ")"); + messageClasses.put(messageString, c); + } + catch (MessageException ex) { + // should be changed to be a hooked method to give library user control + System.out.println(ex.getMessage()); + } + } + + public static String getMessageType(Class c) { + return ((MessageType) c.getAnnotation(MessageType.class)).string(); + } + + // this has never been used or tested but kind of belongs here + // commented out because it uses ReflectiveOperationException which is not available on Android + /* + public static Message newInstance(String className) { + try { + Class messageClass = Class.forName(className); + if (Message.class.isAssignableFrom(messageClass)) + return (Message) messageClass.newInstance(); + else throw new ClassCastException(); + } + catch (ReflectiveOperationException ex) { + throw new RuntimeException("Unable to create message of class \'" + className + "\'.", ex); + } + } + */ + + // Could probably do more checking here, but not sure what right now + private static void typecheck(Class c) throws MessageException { + + // Must inherit from Message + if (!Message.class.isAssignableFrom(c)) + throw new MessageException("Class \'" + c.getName() + + "\' does not extend Message"); + + // Must have the MessageType annotation + if (getMessageType(c) == null) + throw new MessageException("Class \'" + c.getName() + + "\' is missing the MessageType annotation"); + + // All fields must also be valid Message classes + // Note that this also serves to force-load all the message classes + // so that they get registered + for (Field f : c.getFields()) { + Class fc = f.getType(); + if (fc.isArray()) { + Class ac = fc.getComponentType(); + if (!isPrimitive(ac)) + typecheck(ac); + } + else if (!isPrimitive(fc)) + typecheck(fc); + } + } + + public void print() { + printMessage(this, ""); + } + + private static void printMessage(Object o, String indent) { + for (Field f : o.getClass().getFields()) { + Class c = f.getType(); + Object fieldObject = getFieldObject(f, o); + if (fieldObject != null) { + if (isPrimitive(c)) + System.out.println(indent + f.getName() + ": " + fieldObject); + else if (c.isArray()) { + System.out.println(indent + f.getName() + ": ["); + printArray(fieldObject, indent + " "); + System.out.println(indent + "]"); + } + else { + System.out.println(indent + f.getName() + ":"); + printMessage(fieldObject, indent + " "); + } + } + } + } + + private static void printArray(Object array, String indent) { + Class arrayClass = array.getClass().getComponentType(); + for (int i = 0; i < Array.getLength(array); i++) { + Object elementObject = Array.get(array, i); + if (elementObject != null) { + if (isPrimitive(arrayClass)) + System.out.println(indent + i + ": " + elementObject); + else if (arrayClass.isArray()) { // this is not actually allowed in ROS + System.out.println(indent + i + ": ["); + printArray(elementObject, indent + " "); + System.out.println(indent + "]"); + } + else { + System.out.println(indent + i + ":"); + printMessage(elementObject, indent + " "); + } + } + } + // remember to print array indices + } + + public static boolean isPrimitive(Class c) { + return (c.isPrimitive() || + c.equals(String.class) || + Number.class.isAssignableFrom(c) || + c.equals(Boolean.class)); + } + + + // Copied from com.jilk.ros.rosbridge.JSON + private static Object getFieldObject(Field f, Object o) { + Object fo = null; + try { + fo = f.get(o); + } + catch (IllegalAccessException ex) { + ex.printStackTrace(); + } + return fo; + } + + public void copyFrom(Message source) { + try { + if (source.getClass() != getClass()) + throw new RuntimeException("Attempt to copy non-matching classes"); + for (Field f : getClass().getFields()) { + Class fc = f.getType(); + if (fc.isArray()) + throw new RuntimeException("copyFrom - array types not implemented"); + else if (!isPrimitive(fc)) + ((Message) f.get(this)).copyFrom((Message) f.get(source)); + else { + Object value = f.get(source); + f.set(this, value); + } + } + } + catch (IllegalAccessException ex) { + throw new RuntimeException("copyFrom error", ex); + } + catch (ClassCastException ex) { + throw new RuntimeException("copyFrom error", ex); + } + // ReflectiveOperationException is not available on Android (Java 1.6) + /* + catch (ReflectiveOperationException ex) { + throw new RuntimeException ("copyFrom error", ex); + } + */ + } + +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageException.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageException.java new file mode 100644 index 0000000..c2aa2f7 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageException.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +public class MessageException extends Exception { + + public MessageException(String message) { + super(message); + } + + public MessageException(String message, Throwable cause) { + super(message, cause); + } +} + diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageType.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageType.java new file mode 100644 index 0000000..21d3cc0 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/MessageType.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MessageType { + String string() default ""; +} + diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticRequest.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticRequest.java new file mode 100644 index 0000000..728efa9 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticRequest.java @@ -0,0 +1,13 @@ +package com.jilk.ros.message; + +/** + * Created by xxhong on 16-11-17. + */ +@MessageType(string = "std_msgs/String") +public class SemanticRequest extends Message { + public SemanticRequest(String args) { + jsonStr = args; + } + + public String jsonStr; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticResponse.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticResponse.java new file mode 100644 index 0000000..624c8c6 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/SemanticResponse.java @@ -0,0 +1,9 @@ +package com.jilk.ros.message; + +/** + * Created by xxhong on 16-11-17. + */ +@MessageType(string = "std_msgs/String") +public class SemanticResponse extends Message { + public String result; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/StdMsg.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/StdMsg.java new file mode 100644 index 0000000..570d27f --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/StdMsg.java @@ -0,0 +1,9 @@ +package com.jilk.ros.message; + +/** + * Created by xxhong on 16-11-17. + */ +@MessageType(string = "std_msgs/String") +public class StdMsg extends Message { + public String data; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/Time.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/Time.java new file mode 100644 index 0000000..b0075a0 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/Time.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "std_msgs/Time") +public class Time extends TimePrimitive { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/message/TimePrimitive.java b/src/Logistics/app/src/main/java/com/jilk/ros/message/TimePrimitive.java new file mode 100644 index 0000000..238ca6d --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/message/TimePrimitive.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.message; + +@MessageType(string = "time") +public class TimePrimitive extends Message { + public int secs; // when requesting this format from ROSbridge, it uses 'sec' (no 's') + public int nsecs; // when requesting this format from ROSbridge, it uses 'nsec' +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Empty.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Empty.java new file mode 100644 index 0000000..6bfe139 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Empty.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "std_msgs/Empty") +public class Empty extends Message { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/GetTime.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/GetTime.java new file mode 100644 index 0000000..de55c5c --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/GetTime.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.message.TimePrimitive; + + +@MessageType(string = "rosapi/GetTimeResponse") +public class GetTime extends Message { + public TimePrimitive time; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/MessageDetails.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/MessageDetails.java new file mode 100644 index 0000000..c75bb67 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/MessageDetails.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/MessageDetails") +public class MessageDetails extends Message { + public TypeDef[] typedefs; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Nodes.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Nodes.java new file mode 100644 index 0000000..28c87c6 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Nodes.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Nodes") +public class Nodes extends Message { + public String[] nodes; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Service.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Service.java new file mode 100644 index 0000000..a3e8d78 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Service.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Service") +public class Service extends Message { + public String service; + + public Service() {} + + public Service(String service) { + this.service = service; + } +} \ No newline at end of file diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Services.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Services.java new file mode 100644 index 0000000..2503ea5 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Services.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Services") +public class Services extends Message { + public String[] services; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topic.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topic.java new file mode 100644 index 0000000..3ea3ebc --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topic.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Topic") +public class Topic extends Message { + public String topic; + + public Topic() {} + + public Topic(String topic) { + this.topic = topic; + } +} \ No newline at end of file diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topics.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topics.java new file mode 100644 index 0000000..07bab16 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Topics.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Topics") +public class Topics extends Message { + public String[] topics; +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Type.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Type.java new file mode 100644 index 0000000..73d53b0 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/Type.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/Type") +public class Type extends Message { + public String type; + + public Type() {} + + public Type(String type) { + this.type = type; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/TypeDef.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/TypeDef.java new file mode 100644 index 0000000..aff5e47 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosapi/message/TypeDef.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosapi.message; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; + +@MessageType(string = "rosapi/TypeDef") +public class TypeDef extends Message { + public String type; + public String[] fieldnames; + public String[] fieldtypes; + public int[] fieldarraylen; + public String[] examples; + + public static boolean match(String type, Class c) { + boolean result = false; + if ( + (type.equals("bool") && ((boolean.class.equals(c)) || (Boolean.class.equals(c)))) || + (type.equals("int8") && ((byte.class.equals(c)) || (Byte.class.equals(c)))) || + (type.equals("byte") && ((byte.class.equals(c)) || (Byte.class.equals(c)))) || // deprecated + (type.equals("uint8") && ((short.class.equals(c)) || (Short.class.equals(c)))) || + (type.equals("char") && ((short.class.equals(c)) || (Short.class.equals(c)))) || // deprecated + (type.equals("int16") && ((short.class.equals(c)) || (Short.class.equals(c)))) || + (type.equals("uint16") && ((int.class.equals(c)) || (Integer.class.equals(c)))) || + (type.equals("int32") && ((int.class.equals(c)) || (Integer.class.equals(c)))) || + (type.equals("uint32") && ((long.class.equals(c)) || (Long.class.equals(c)))) || + (type.equals("int64") && ((long.class.equals(c)) || (Long.class.equals(c)))) || + (type.equals("float32") && ((float.class.equals(c)) || (Float.class.equals(c)))) || + (type.equals("float64") && ((double.class.equals(c)) || (Double.class.equals(c)))) || + (type.equals("uint64") && (java.math.BigInteger.class.equals(c))) || + (type.equals("string") && (String.class.equals(c))) + ) + result = true; + + return result; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java new file mode 100644 index 0000000..62580fd --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/FullMessageHandler.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge; + +import com.jilk.ros.message.Message; + +public interface FullMessageHandler { + public void onMessage(String id, T message); +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/ROSBridgeClient.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/ROSBridgeClient.java new file mode 100644 index 0000000..77b672f --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/ROSBridgeClient.java @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge; + +import com.jilk.ros.ROSClient; +import com.jilk.ros.Service; +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosapi.message.Empty; +import com.jilk.ros.rosapi.message.MessageDetails; +import com.jilk.ros.rosapi.message.Nodes; +import com.jilk.ros.rosapi.message.Services; +import com.jilk.ros.rosapi.message.Topic; +import com.jilk.ros.rosapi.message.Topics; +import com.jilk.ros.rosapi.message.Type; +import com.jilk.ros.rosapi.message.TypeDef; +import com.jilk.ros.rosbridge.implementation.ROSBridgeWebSocketClient; +import com.jilk.ros.rosbridge.operation.Operation; + +import java.lang.reflect.Field; + +public class ROSBridgeClient extends ROSClient { + String uriString; + ROSBridgeWebSocketClient client; + + public ROSBridgeClient(String uriString) { + this.uriString = uriString; + } + + @Override + public boolean connect() { + return connect(null); + } + + @Override + public boolean connect(ConnectionStatusListener listener) { + boolean result = false; + client = ROSBridgeWebSocketClient.create(uriString); + if (client != null) { + client.setListener(listener); + try { + result = client.connectBlocking(); + } + catch (InterruptedException ex) {} + } + return result; + } + + @Override + public void disconnect() { + try { + client.closeBlocking(); + } + catch (InterruptedException ex) {} + } + + @Override + public void send(Operation operation) { + client.send(operation); + } + + @Override + public void send(String json) { + client.send(json); + } + + @Override + public void register(Class c, + String s, + Class m, + FullMessageHandler h) { + client.register(c, s, m, h); + } + + @Override + public void unregister(Class c, String s) { + client.unregister(c, s); + } + + @Override + public void setDebug(boolean debug) { + client.setDebug(debug); + } + + @Override + public String[] getNodes() throws InterruptedException { + Service nodeService = + new Service("/rosapi/nodes", Empty.class, Nodes.class, this); + return nodeService.callBlocking(new Empty()).nodes; + } + + @Override + public String[] getTopics() throws InterruptedException { + Service topicsService = + new Service("/rosapi/topics", Empty.class, Topics.class, this); + return topicsService.callBlocking(new Empty()).topics; + } + + @Override + public String[] getServices() throws InterruptedException { + Service servicesService = + new Service("/rosapi/services", Empty.class, Services.class, this); + return servicesService.callBlocking(new Empty()).services; + } + + @Override + public TypeDef getTopicMessageDetails(String topic) throws InterruptedException { + return getTypeDetails(getTopicType(topic)); + } + + @Override + public TypeDef[] getTopicMessageList(String topic) throws InterruptedException { + return getTypeList(getTopicType(topic)); + } + + @Override + public TypeDef getServiceRequestDetails(String service) throws InterruptedException { + return getTypeDetails(getServiceType(service), "Request", "/rosapi/service_request_details"); + } + + @Override + public TypeDef[] getServiceRequestList(String service) throws InterruptedException { + return getTypeList(getServiceType(service), "Request", "/rosapi/service_request_details"); + } + + @Override + public TypeDef getServiceResponseDetails(String service) throws InterruptedException { + return getTypeDetails(getServiceType(service), "Response", "/rosapi/service_response_details"); + } + + @Override + public TypeDef[] getServiceResponseList(String service) throws InterruptedException { + return getTypeList(getServiceType(service), "Response", "/rosapi/service_response_details"); + } + + @Override + public TypeDef[] getTypeList(String type) throws InterruptedException { + return getTypeList(type, "", "/rosapi/message_details"); + } + + @Override + public TypeDef getTypeDetails(String type) throws InterruptedException { + return getTypeDetails(type, "", "/rosapi/message_details"); + } + + private TypeDef[] getTypeList(String type, String suffix, String serviceName) throws InterruptedException { + Service messageDetailsService = + new Service(serviceName, + Type.class, MessageDetails.class, this); + return messageDetailsService.callBlocking(new Type(type)).typedefs; + } + + private TypeDef getTypeDetails(String type, String suffix, String serviceName) throws InterruptedException { + Service messageDetailsService = + new Service(serviceName, + Type.class, MessageDetails.class, this); + return findType(type + suffix, messageDetailsService.callBlocking(new Type(type)).typedefs); + } + + private String getTopicType(String topic) throws InterruptedException { + Service topicTypeService = + new Service("/rosapi/topic_type", + Topic.class, Type.class, this); + return topicTypeService.callBlocking(new Topic(topic)).type; + } + + private String getServiceType(String service) throws InterruptedException { + Service serviceTypeService = + new Service("/rosapi/service_type", + com.jilk.ros.rosapi.message.Service.class, Type.class, this); + return serviceTypeService.callBlocking(new com.jilk.ros.rosapi.message.Service(service)).type; + } + + private TypeDef findType(String type, TypeDef[] types) { + TypeDef result = null; + for (TypeDef t : types) { + if (t.type.equals(type)) { + result = t; + break; + } + } + //System.out.println("ROSBridgeClient.findType: "); + //result.print(); + return result; + } + + @Override + public void typeMatch(TypeDef t, Class c) throws InterruptedException { + if (c == null) + throw new RuntimeException("No registered message type found for: " + t.type); + Field[] fields = c.getFields(); + for (int i = 0; i < t.fieldnames.length; i++) { + + // Field names + String classFieldName = fields[i].getName(); + String typeFieldName = t.fieldnames[i]; + if (!classFieldName.equals(typeFieldName)) + typeMatchError(t, c, "field name", typeFieldName, classFieldName); + + // Array type of field + boolean typeIsArray = (t.fieldarraylen[i] >= 0); + boolean fieldIsArray = fields[i].getType().isArray(); + if (typeIsArray != fieldIsArray) + typeMatchError(t, c, "array mismatch", typeFieldName, classFieldName); + + // Get base type of field + Class fieldClass = fields[i].getType(); + if (fieldIsArray) + fieldClass = fields[i].getType().getComponentType(); + String type = t.fieldtypes[i]; + + // Field type for primitivesclient + if (Message.isPrimitive(fieldClass)) { + if (!TypeDef.match(type, fieldClass)) + typeMatchError(t, c, "type mismatch", type, fieldClass.getName()); + } + + // Field type for non-primitive classes, and recurse + else { + if (!Message.class.isAssignableFrom(fieldClass)) + throw new RuntimeException("Member " + classFieldName + + " of class " + fieldClass.getName() + " does not extend Message."); + String fieldClassString = ((MessageType) fieldClass.getAnnotation(MessageType.class)).string(); + if (!type.equals(fieldClassString)) + typeMatchError(t, c, "message type mismatch", type, fieldClassString); + typeMatch(getTypeDetails(type), fieldClass); + } + } + } + + private void typeMatchError(TypeDef t, Class c, + String error, String tString, String cString) { + throw new RuntimeException("Type match error between " + + t.type + " and " + c.getName() + ": " + + error + ": \'" + tString + "\' does not match \'" + cString + "\'."); + } + + @Override + public Object getUnderlyingClient() { + return client; + } + +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Base64.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Base64.java new file mode 100644 index 0000000..75eec18 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Base64.java @@ -0,0 +1,575 @@ +package com.jilk.ros.rosbridge.implementation; + +import java.util.Arrays; + +/** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance + * with RFC 2045.

+ * On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster + * on small arrays (10 - 1000 bytes) and 2-3 times as fast on larger arrays (10000 - 1000000 bytes) + * compared to sun.misc.Encoder()/Decoder().

+ * + * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and + * about 50% faster for decoding large arrays. This implementation is about twice as fast on very small + * arrays (< 30 bytes). If source/destination is a String this + * version is about three times as fast due to the fact that the Commons Codec result has to be recoded + * to a String from byte[], which is very expensive.

+ * + * This encode/decode algorithm doesn't create any temporary arrays as many other codecs do, it only + * allocates the resulting array. This produces less garbage and it is possible to handle arrays twice + * as large as algorithms that create a temporary array. (E.g. Jakarta Commons Codec). It is unknown + * whether Sun's sun.misc.Encoder()/Decoder() produce temporary arrays but since performance + * is quite low it probably does.

+ * + * The encoder produces the same output as the Sun one except that the Sun's encoder appends + * a trailing line separator if the last character isn't a pad. Unclear why but it only adds to the + * length and is probably a side effect. Both are in conformance with RFC 2045 though.
+ * Commons codec seem to always att a trailing line separator.

+ * + * Note! + * The encode/decode method pairs (types) come in three versions with the exact same algorithm and + * thus a lot of code redundancy. This is to not create any temporary arrays for transcoding to/from different + * format types. The methods not used can simply be commented out.

+ * + * There is also a "fast" version of all decode methods that works the same way as the normal ones, but + * har a few demands on the decoded input. Normally though, these fast verions should be used if the source if + * the input is known and it hasn't bee tampered with.

+ * + * If you find the code useful or you find a bug, please send me a note at base64 @ miginfocom . com. + * + * Licence (BSD): + * ============== + * + * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * Neither the name of the MiG InfoCom AB nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * @version 2.2 + * @author Mikael Grev + * Date: 2004-aug-02 + * Time: 11:31:11 + */ + +public class Base64 +{ + private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); + private static final int[] IA = new int[256]; + static { + Arrays.fill(IA, -1); + for (int i = 0, iS = CA.length; i < iS; i++) + IA[CA[i]] = i; + IA['='] = 0; + } + + // **************************************************************************************** + // * char[] version + // **************************************************************************************** + + /** Encodes a raw byte array into a BASE64 char[] representation i accordance with RFC 2045. + * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. + * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
+ * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a + * little faster. + * @return A BASE64 encoded array. Never null. + */ + public final static char[] encodeToChar(byte[] sArr, boolean lineSep) + { + // Check special case + int sLen = sArr != null ? sArr.length : 0; + if (sLen == 0) + return new char[0]; + + int eLen = (sLen / 3) * 3; // Length of even 24-bits. + int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count + int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array + char[] dArr = new char[dLen]; + + // Encode even 24-bits + for (int s = 0, d = 0, cc = 0; s < eLen;) { + // Copy next three bytes into lower 24 bits of int, paying attension to sign. + int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); + + // Encode the int into four chars + dArr[d++] = CA[(i >>> 18) & 0x3f]; + dArr[d++] = CA[(i >>> 12) & 0x3f]; + dArr[d++] = CA[(i >>> 6) & 0x3f]; + dArr[d++] = CA[i & 0x3f]; + + // Add optional line separator + if (lineSep && ++cc == 19 && d < dLen - 2) { + dArr[d++] = '\r'; + dArr[d++] = '\n'; + cc = 0; + } + } + + // Pad and encode last bits if source isn't even 24 bits. + int left = sLen - eLen; // 0 - 2. + if (left > 0) { + // Prepare the int + int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); + + // Set last four chars + dArr[dLen - 4] = CA[i >> 12]; + dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; + dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '='; + dArr[dLen - 1] = '='; + } + return dArr; + } + + /** Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with + * and without line separators. + * @param sArr The source array. null or length 0 will return an empty array. + * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters + * (including '=') isn't divideable by 4. (I.e. definitely corrupted). + */ + public final static byte[] decode(char[] sArr) + { + // Check special case + int sLen = sArr != null ? sArr.length : 0; + if (sLen == 0) + return new byte[0]; + + // Count illegal characters (including '\r', '\n') to know what size the returned array will be, + // so we don't have to reallocate & copy it later. + int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) + for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. + if (IA[sArr[i]] < 0) + sepCnt++; + + // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. + if ((sLen - sepCnt) % 4 != 0) + return null; + + int pad = 0; + for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) + if (sArr[i] == '=') + pad++; + + int len = ((sLen - sepCnt) * 6 >> 3) - pad; + + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + for (int s = 0, d = 0; d < len;) { + // Assemble three bytes into an int from four "valid" characters. + int i = 0; + for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. + int c = IA[sArr[s++]]; + if (c >= 0) + i |= c << (18 - j * 6); + else + j--; + } + // Add the bytes + dArr[d++] = (byte) (i >> 16); + if (d < len) { + dArr[d++]= (byte) (i >> 8); + if (d < len) + dArr[d++] = (byte) i; + } + } + return dArr; + } + + /** Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as + * fast as {@link #decode(char[])}. The preconditions are:
+ * + The array must have a line length of 76 chars OR no line separators at all (one line).
+ * + Line separator must be "\r\n", as specified in RFC 2045 + * + The array must not contain illegal characters within the encoded string
+ * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
+ * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. + * @return The decoded array of bytes. May be of length 0. + */ + public final static byte[] decodeFast(char[] sArr) + { + // Check special case + int sLen = sArr.length; + if (sLen == 0) + return new byte[0]; + + int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. + + // Trim illegal chars from start + while (sIx < eIx && IA[sArr[sIx]] < 0) + sIx++; + + // Trim illegal chars from end + while (eIx > 0 && IA[sArr[eIx]] < 0) + eIx--; + + // get the padding count (=) (0, 1 or 2) + int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end. + int cCnt = eIx - sIx + 1; // Content count including possible separators + int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; + + int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + // Decode all but the last 0 - 2 bytes. + int d = 0; + for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { + // Assemble three bytes into an int from four "valid" characters. + int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; + + // Add the bytes + dArr[d++] = (byte) (i >> 16); + dArr[d++] = (byte) (i >> 8); + dArr[d++] = (byte) i; + + // If line separator, jump over it. + if (sepCnt > 0 && ++cc == 19) { + sIx += 2; + cc = 0; + } + } + + if (d < len) { + // Decode last 1-3 bytes (incl '=') into 1-3 bytes + int i = 0; + for (int j = 0; sIx <= eIx - pad; j++) + i |= IA[sArr[sIx++]] << (18 - j * 6); + + for (int r = 16; d < len; r -= 8) + dArr[d++] = (byte) (i >> r); + } + + return dArr; + } + + // **************************************************************************************** + // * byte[] version + // **************************************************************************************** + + /** Encodes a raw byte array into a BASE64 byte[] representation i accordance with RFC 2045. + * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. + * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
+ * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a + * little faster. + * @return A BASE64 encoded array. Never null. + */ + public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) + { + // Check special case + int sLen = sArr != null ? sArr.length : 0; + if (sLen == 0) + return new byte[0]; + + int eLen = (sLen / 3) * 3; // Length of even 24-bits. + int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count + int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array + byte[] dArr = new byte[dLen]; + + // Encode even 24-bits + for (int s = 0, d = 0, cc = 0; s < eLen;) { + // Copy next three bytes into lower 24 bits of int, paying attension to sign. + int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); + + // Encode the int into four chars + dArr[d++] = (byte) CA[(i >>> 18) & 0x3f]; + dArr[d++] = (byte) CA[(i >>> 12) & 0x3f]; + dArr[d++] = (byte) CA[(i >>> 6) & 0x3f]; + dArr[d++] = (byte) CA[i & 0x3f]; + + // Add optional line separator + if (lineSep && ++cc == 19 && d < dLen - 2) { + dArr[d++] = '\r'; + dArr[d++] = '\n'; + cc = 0; + } + } + + // Pad and encode last bits if source isn't an even 24 bits. + int left = sLen - eLen; // 0 - 2. + if (left > 0) { + // Prepare the int + int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); + + // Set last four chars + dArr[dLen - 4] = (byte) CA[i >> 12]; + dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f]; + dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '='; + dArr[dLen - 1] = '='; + } + return dArr; + } + + /** Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with + * and without line separators. + * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. + * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters + * (including '=') isn't divideable by 4. (I.e. definitely corrupted). + */ + public final static byte[] decode(byte[] sArr) + { + // Check special case + int sLen = sArr.length; + + // Count illegal characters (including '\r', '\n') to know what size the returned array will be, + // so we don't have to reallocate & copy it later. + int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) + for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. + if (IA[sArr[i] & 0xff] < 0) + sepCnt++; + + // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. + if ((sLen - sepCnt) % 4 != 0) + return null; + + int pad = 0; + for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) + if (sArr[i] == '=') + pad++; + + int len = ((sLen - sepCnt) * 6 >> 3) - pad; + + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + for (int s = 0, d = 0; d < len;) { + // Assemble three bytes into an int from four "valid" characters. + int i = 0; + for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. + int c = IA[sArr[s++] & 0xff]; + if (c >= 0) + i |= c << (18 - j * 6); + else + j--; + } + + // Add the bytes + dArr[d++] = (byte) (i >> 16); + if (d < len) { + dArr[d++]= (byte) (i >> 8); + if (d < len) + dArr[d++] = (byte) i; + } + } + + return dArr; + } + + + /** Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as + * fast as {@link #decode(byte[])}. The preconditions are:
+ * + The array must have a line length of 76 chars OR no line separators at all (one line).
+ * + Line separator must be "\r\n", as specified in RFC 2045 + * + The array must not contain illegal characters within the encoded string
+ * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
+ * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. + * @return The decoded array of bytes. May be of length 0. + */ + public final static byte[] decodeFast(byte[] sArr) + { + // Check special case + int sLen = sArr.length; + if (sLen == 0) + return new byte[0]; + + int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. + + // Trim illegal chars from start + while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) + sIx++; + + // Trim illegal chars from end + while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) + eIx--; + + // get the padding count (=) (0, 1 or 2) + int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end. + int cCnt = eIx - sIx + 1; // Content count including possible separators + int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; + + int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + // Decode all but the last 0 - 2 bytes. + int d = 0; + for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { + // Assemble three bytes into an int from four "valid" characters. + int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; + + // Add the bytes + dArr[d++] = (byte) (i >> 16); + dArr[d++] = (byte) (i >> 8); + dArr[d++] = (byte) i; + + // If line separator, jump over it. + if (sepCnt > 0 && ++cc == 19) { + sIx += 2; + cc = 0; + } + } + + if (d < len) { + // Decode last 1-3 bytes (incl '=') into 1-3 bytes + int i = 0; + for (int j = 0; sIx <= eIx - pad; j++) + i |= IA[sArr[sIx++]] << (18 - j * 6); + + for (int r = 16; d < len; r -= 8) + dArr[d++] = (byte) (i >> r); + } + + return dArr; + } + + // **************************************************************************************** + // * String version + // **************************************************************************************** + + /** Encodes a raw byte array into a BASE64 String representation i accordance with RFC 2045. + * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. + * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
+ * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a + * little faster. + * @return A BASE64 encoded array. Never null. + */ + public final static String encodeToString(byte[] sArr, boolean lineSep) + { + // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. + return new String(encodeToChar(sArr, lineSep)); + } + + /** Decodes a BASE64 encoded String. All illegal characters will be ignored and can handle both strings with + * and without line separators.
+ * Note! It can be up to about 2x the speed to call decode(str.toCharArray()) instead. That + * will create a temporary array though. This version will use str.charAt(i) to iterate the string. + * @param str The source string. null or length 0 will return an empty array. + * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters + * (including '=') isn't divideable by 4. (I.e. definitely corrupted). + */ + public final static byte[] decode(String str) + { + // Check special case + int sLen = str != null ? str.length() : 0; + if (sLen == 0) + return new byte[0]; + + // Count illegal characters (including '\r', '\n') to know what size the returned array will be, + // so we don't have to reallocate & copy it later. + int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) + for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. + if (IA[str.charAt(i)] < 0) + sepCnt++; + + // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. + if ((sLen - sepCnt) % 4 != 0) + return null; + + // Count '=' at end + int pad = 0; + for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) + if (str.charAt(i) == '=') + pad++; + + int len = ((sLen - sepCnt) * 6 >> 3) - pad; + + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + for (int s = 0, d = 0; d < len;) { + // Assemble three bytes into an int from four "valid" characters. + int i = 0; + for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. + int c = IA[str.charAt(s++)]; + if (c >= 0) + i |= c << (18 - j * 6); + else + j--; + } + // Add the bytes + dArr[d++] = (byte) (i >> 16); + if (d < len) { + dArr[d++]= (byte) (i >> 8); + if (d < len) + dArr[d++] = (byte) i; + } + } + return dArr; + } + + /** Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as + * fast as {@link #decode(String)}. The preconditions are:
+ * + The array must have a line length of 76 chars OR no line separators at all (one line).
+ * + Line separator must be "\r\n", as specified in RFC 2045 + * + The array must not contain illegal characters within the encoded string
+ * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
+ * @param s The source string. Length 0 will return an empty array. null will throw an exception. + * @return The decoded array of bytes. May be of length 0. + */ + public final static byte[] decodeFast(String s) + { + // Check special case + int sLen = s.length(); + if (sLen == 0) + return new byte[0]; + + int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. + + // Trim illegal chars from start + while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) + sIx++; + + // Trim illegal chars from end + while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) + eIx--; + + // get the padding count (=) (0, 1 or 2) + int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end. + int cCnt = eIx - sIx + 1; // Content count including possible separators + int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0; + + int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes + byte[] dArr = new byte[len]; // Preallocate byte[] of exact length + + // Decode all but the last 0 - 2 bytes. + int d = 0; + for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { + // Assemble three bytes into an int from four "valid" characters. + int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)]; + + // Add the bytes + dArr[d++] = (byte) (i >> 16); + dArr[d++] = (byte) (i >> 8); + dArr[d++] = (byte) i; + + // If line separator, jump over it. + if (sepCnt > 0 && ++cc == 19) { + sIx += 2; + cc = 0; + } + } + + if (d < len) { + // Decode last 1-3 bytes (incl '=') into 1-3 bytes + int i = 0; + for (int j = 0; sIx <= eIx - pad; j++) + i |= IA[s.charAt(sIx++)] << (18 - j * 6); + + for (int r = 16; d < len; r -= 8) + dArr[d++] = (byte) (i >> r); + } + + return dArr; + } +} \ No newline at end of file diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/JSON.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/JSON.java new file mode 100644 index 0000000..acbe1d7 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/JSON.java @@ -0,0 +1,335 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.implementation; + +import com.jilk.ros.message.Message; +import com.jilk.ros.rosbridge.indication.Indication; +import com.jilk.ros.rosbridge.operation.Wrapper; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.StringReader; +import java.lang.reflect.Array; +import java.lang.reflect.Field; + + +// The slightly crazy abstractions here are designed to isolate knowledge of +// the JSON library and data types from the Operation details of rosbridge. +// Why is this important? A few reasons I can see. First, we might want +// to change JSON libraries and this encapsulates all use of JSON-simple. +// Second, as much as possible I would like the semantics of the rosbridge +// protocol to be encapsulated in the Operation and its subclasses rather +// than in a module that is essentially about serialization. +// +// Unfortunately the hierarchical Message abstraction is a bit broken +// at the top level. Beginning at the actual operation (e.g., Publish), the +// types of the fields are determined either by the fields themselves or by +// an indicator. However, the type of the operation itself is not determined +// this way, because the indicator is in the object itself, which means it +// would have to be created before its type is known. Rather than build in +// exceptions, I elected to create a "Wrapper" operation type that simply +// wraps the concrete operation and copies its "op" field. +// + +public class JSON { + + /** + * Translates a Message recursively into JSON. Normally the Message is also an + * Operation, but it does not have to be. The caller constructs a complete + * message using @Operation and @Message types. This includes situations + * where one or more fields are marked to be turned into arrays, using @AsArray. + * @param m the @Message object to be recursively translated. + * @return the complete JSON string. + */ + public static String toJSON(Message m) { + JSONObject jo = convertObjectToJSONObject(m); // Object to JSON-Simple + return jo.toJSONString(); // JSON-Simple to string + } + + /** + * Translates JSON into a hierarchical Operation/Message structure. + * This includes handling fields that are @Indicated and @AsArray. If the + * @Class parameter is a @Wrapper, this is a special case whereby the + * object is wrapped to create a consistent hierarchy. + * @param json the source JSON string + * @param c the top level class of the JSON. Normally @Wrapper + * @param r the @Registry containing topic registrations + * @return the fully instantiated message hierarchy represented + * by the JSON string. + */ + public static Message toMessage(String json, Class c, Registry r) { + JSONObject joUnwrapped = convertStringToJSONObject(json); // String to JSON-Simple + JSONObject jo = joUnwrapped; + if (Wrapper.class.isAssignableFrom(c)) + jo = wrap(joUnwrapped, c); // wrap: a hack to make the hierarchy homogeneous + return convertJSONObjectToMessage(jo, c, r); // JSON-Simple to Message + } + + // *** Create JSON from Messages *** // + + // Translate the object into a JSON-Simple object, field-by-field, + // recursively via convertElementToJSON. + // except for the case where AsArray is indicated + private static JSONObject convertObjectToJSONObject(Object o) { + JSONObject result = new JSONObject(); + for (Field f : o.getClass().getFields()) { + Object fieldObject = getFieldObject(f, o); + if (fieldObject != null) { + Object resultObject; + if (Indication.isBase64Encoded(f)) + resultObject = convertByteArrayToBase64JSONString(fieldObject); + else if (Indication.asArray(f)) + resultObject = convertObjectToJSONArray(fieldObject); + else resultObject = convertElementToJSON(fieldObject); + result.put(f.getName(), resultObject); + } + } + return result; + } + + // Convert an array type to a JSON-Simple array, element-by-element, + // recursively via convertElementToJSON. + private static JSONArray convertArrayToJSONArray(Object array) { + JSONArray result = new JSONArray(); + for (int i = 0; i < Array.getLength(array); i++) { + Object elementObject = Array.get(array, i); + if (elementObject != null) { + Object resultObject = convertElementToJSON(elementObject); + result.add(resultObject); + } + } + return result; + } + + // For AsArray objects, convert the object to a JSON-Simple array + // NOTE: This relies on later versions of the JDK providing + // the fields in order. + private static JSONArray convertObjectToJSONArray(Object o) { + JSONArray result = new JSONArray(); + for (Field f : o.getClass().getFields()) { + Object fieldObject = getFieldObject(f, o); + if (fieldObject != null) { + Object resultObject = convertElementToJSON(fieldObject); + result.add(resultObject); + } + } + return result; + } + + // Convert the individual field or array element items recursively + private static Object convertElementToJSON(Object elementObject) { + Class elementClass = elementObject.getClass(); + Object resultObject; + if (Message.isPrimitive(elementClass)) + resultObject = elementObject; + else if (elementClass.isArray()) + resultObject = convertArrayToJSONArray(elementObject); + else + resultObject = convertObjectToJSONObject(elementObject); + return resultObject; + } + + // Special case for Base 64-encoded fields + private static Object convertByteArrayToBase64JSONString(Object fieldObject) { + return Base64.encodeToString((byte[]) fieldObject, false); + } + + // This is just to buffer the code from the exception. Better error + // handling needed here. + private static Object getFieldObject(Field f, Object o) { + Object fo = null; + try { + fo = f.get(o); + } + catch (IllegalAccessException ex) { + ex.printStackTrace(); + } + return fo; + } + + // *** Create Messages from JSON *** // + + // Use the JSON-simple parser to create the JSON-Simple object + private static JSONObject convertStringToJSONObject(String json) { + JSONObject result = null; + StringReader r = new StringReader(json); + JSONParser jp = new JSONParser(); + try { + result = (JSONObject) jp.parse(r); + } + catch (Throwable t) { + System.out.println(t.getMessage()); + } + r.close(); + return result; + } + + // A bit of a hack to create a consistent hierarchy with jsonbridge operations + // At least it does not depend on any specific field names, it just copies the + // Indicator and Indicated fields. + private static JSONObject wrap(JSONObject jo, Class c) { + JSONObject result = new JSONObject(); + String indicatorName = Indication.getIndicatorName(c); + String indicatedName = Indication.getIndicatedName(c); + result.put(indicatorName, jo.get(indicatorName)); + result.put(indicatedName, jo); + return result; + } + + // Convert the JSON-Simple object to the indicated message, field-by-field + // recursively via convertElementToField. + private static Message convertJSONObjectToMessage(JSONObject jo, Class c, Registry r) { + //System.out.println("JSON.convertJSONObjectToMessage: " + jo.toJSONString()); + try { + Message result = (Message) c.newInstance(); + for (Field f : c.getFields()) { + Class fc = getFieldClass(result, jo, f, r); + Object lookup = jo.get(f.getName()); + if (lookup != null) { + Object value = convertElementToField(lookup, fc, f, r); + f.set(result, value); + } + } + return result; + } + catch (Exception ex) { + //ex.printStackTrace(); + return null; + } + } + + // Convert the JSON-Simple array to the indicated message, element-by-element + // recursively via convertElementToField. + private static Object convertJSONArrayToArray(JSONArray ja, Class c, Registry r) { + Object result = Array.newInstance(c, ja.size()); + for (int i = 0; i < ja.size(); i++) { + Object lookup = ja.get(i); + Object value = null; + if (lookup != null) { + if (lookup.getClass().equals(JSONObject.class)) + value = convertJSONObjectToMessage((JSONObject) lookup, c, r); + else if (lookup.getClass().equals(JSONArray.class)) // this is not actually allowed in ROS + value = convertJSONArrayToArray((JSONArray) lookup, c.getComponentType(), r); + else + value = convertJSONPrimitiveToPrimitive(lookup, c); + Array.set(result, i, value); + } + } + + return result; + } + + // Convert a JSON-Simple array to a Message, field-by-field of the Message, + // element-by-element of the array, recursively via convertElementToField. + // NOTE: This relies on later versions of the JDK providing + // the fields in order. + private static Message convertJSONArrayToMessage(JSONArray ja, Class c, Registry r) { + try { + Message result = (Message) c.newInstance(); + int arrayIndex = 0; + for (Field f : c.getFields()) { + Class fc = getFieldClass(result, null, f, r); + Object lookup = ja.get(arrayIndex++); // yes we are assuming that the fields are delivered in order + if (lookup != null) { + Object value = convertElementToField(lookup, fc, f, r); + f.set(result, value); + } + } + + return result; + } + catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } + + // Convert an individual array or object element to a field in the Message, + // recursively, and applying AsArray if needed. + private static Object convertElementToField(Object element, Class fc, Field f, Registry r) { + //System.out.println("JSON.convertElementToField: " + f.getName() + " " + fc.getName()); + Object value; + if (element.getClass().equals(JSONObject.class)) { + //System.out.println("JSON.convertElementToField: JSON Object " + ((JSONObject) element).toJSONString()); + value = convertJSONObjectToMessage((JSONObject) element, fc, r); + } + else if (element.getClass().equals(JSONArray.class)) { + //System.out.println("JSON.convertElementToField: JSON Array " + ((JSONArray) element).toJSONString()); + if (Indication.asArray(f)) + value = convertJSONArrayToMessage((JSONArray) element, fc, r); + else value = convertJSONArrayToArray((JSONArray) element, fc, r); + } + else { + //System.out.println("JSON.convertElementToField: Primitive " + element); + if (Indication.isBase64Encoded(f)) + value = convertBase64JSONStringToByteArray(element); + else value = convertJSONPrimitiveToPrimitive(element, fc); + } + + return value; + } + + // Note that this is not checking ranges + public static Object convertJSONPrimitiveToPrimitive(Object o, Class c) { + Object result = o; + if (c.isPrimitive() || Number.class.isAssignableFrom(c)) { + if (c.equals(double.class) || c.equals(Double.class)) + result = new Double(((Number) o).doubleValue()); + else if (c.equals(float.class) || c.equals(Float.class)) + result = new Float(((Number) o).floatValue()); + else if (c.equals(long.class) || c.equals(Long.class)) + result = new Long(((Number) o).longValue()); + else if (int.class.equals(c) || c.equals(Integer.class)) + result = new Integer(((Number) o).intValue()); + else if (c.equals(short.class) || c.equals(Short.class)) + result = new Short(((Number) o).shortValue()); + else if (c.equals(byte.class) || c.equals(Byte.class)) + result = new Byte(((Number) o).byteValue()); + } + return result; + } + + public static byte[] convertBase64JSONStringToByteArray(Object element) { + return Base64.decode((String) element); + } + + // Determine the target class of a field in the object or array, based + // directly on the field's type, or using the Indicator if applicable, + // The Indicator field only provides the topic/service, so we have to look + // up the Class in the registry. + public static Class getFieldClass(Message parent, JSONObject jo, Field f, Registry r) { + Class fc; + fc = f.getType(); + if (fc.isArray()) + fc = f.getType().getComponentType(); + if (Indication.isIndicated(f) && (jo != null)) { + //fc = Indication.getIndication(parent, + // (String) jo.get(Indication.getIndicatorName(parent.getClass()))); + fc = r.lookup(parent.getClass(), + (String) jo.get(Indication.getIndicatorName(parent.getClass()))); + //System.out.println("JSON.getFieldClass: parent class " + parent.getClass().getName() + + // " Indicator: " + Indication.getIndicatorName(parent.getClass()) + + // " result: " + fc.getName()); + } + return fc; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/PublishEvent.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/PublishEvent.java new file mode 100644 index 0000000..c7df197 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/PublishEvent.java @@ -0,0 +1,24 @@ +package com.jilk.ros.rosbridge.implementation; + +import com.jilk.ros.rosbridge.operation.Operation; + +/**EventBus event entity,describe ros server response info + * Created by xxhong on 16-11-22. + */ + +public class PublishEvent { + public String msg; + public String id; + public String name; + public String op; + + + public PublishEvent(Operation operation, String name, String content) { + if(operation != null) { + id = operation.id; + op = operation.op; + } + this.name = name; + msg = content; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/ROSBridgeWebSocketClient.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/ROSBridgeWebSocketClient.java new file mode 100644 index 0000000..c3958b6 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/ROSBridgeWebSocketClient.java @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + *

+ * This file is part of the Java ROSBridge Client. + *

+ * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + *

+ * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + */ +package com.jilk.ros.rosbridge.implementation; + +import com.jilk.ros.ROSClient; +import com.jilk.ros.message.Message; +import com.jilk.ros.rosbridge.FullMessageHandler; +import com.jilk.ros.rosbridge.operation.Operation; +import com.jilk.ros.rosbridge.operation.Publish; +import com.jilk.ros.rosbridge.operation.ServiceResponse; + +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.framing.CloseFrame; +import org.java_websocket.handshake.ServerHandshake; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.lang.reflect.Field; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.channels.SocketChannel; + +import de.greenrobot.event.EventBus; + +public class ROSBridgeWebSocketClient extends WebSocketClient { + private Registry classes; + private Registry handlers; + private boolean debug; + private ROSClient.ConnectionStatusListener listener; + + ROSBridgeWebSocketClient(URI serverURI) { + super(serverURI); + classes = new Registry(); + handlers = new Registry(); + Operation.initialize(classes); // note, this ensures that the Message Map is initialized too + listener = null; + } + + public static ROSBridgeWebSocketClient create(String URIString) { + ROSBridgeWebSocketClient client = null; + try { + URI uri = new URI(URIString); + client = new ROSBridgeWebSocketClient(uri); + } catch (URISyntaxException ex) { + ex.printStackTrace(); + } + return client; + } + + public void setListener(ROSClient.ConnectionStatusListener listener) { + this.listener = listener; + } + + @Override + public void onOpen(ServerHandshake handshakedata) { + if (listener != null) + listener.onConnect(); + } + + @Override + public void onMessage(String message) { + if (debug) System.out.println(" " + json); + send(json); + } + + public void register(Class c, + String s, + Class m, + FullMessageHandler h) { + Message.register(m, classes.get(Message.class)); + classes.register(c, s, m); + if (h != null) + handlers.register(c, s, h); + } + + public void unregister(Class c, String s) { + handlers.unregister(c, s); + // Note that there is no concept of unregistering a class - it can get replaced is all + } + + public Class getRegisteredMessage(String messageString) { + return classes.lookup(Message.class, messageString); + } + + public void setDebug(boolean debug) { + this.debug = debug; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Registry.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Registry.java new file mode 100644 index 0000000..4747e6d --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/implementation/Registry.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.implementation; + +import java.util.HashMap; +import java.util.Map; + +public class Registry extends HashMap> { + + public void register(Class c, String s, T t) { + Map table = get(c); + if (table == null) { + table = new HashMap(); + put(c, table); + } + table.put(s, t); + } + + public void unregister(Class c, String s) { + Map table = get(c); + if (table != null) + table.remove(s); + } + + public T lookup(Class c, String s) { + T result = null; + Map table = get(c); + if (table != null) + result = table.get(s); + return result; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/AsArray.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/AsArray.java new file mode 100644 index 0000000..f411ec4 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/AsArray.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface AsArray { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Base64Encoded.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Base64Encoded.java new file mode 100644 index 0000000..5e5e04d --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Base64Encoded.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Base64Encoded { +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicate.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicate.java new file mode 100644 index 0000000..3827ae4 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicate.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Indicate { + // if later we want multiple indicated fields, use an int here +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicated.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicated.java new file mode 100644 index 0000000..f0edc8e --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicated.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Indicated { + // if later we want multiple indicated fields, use an int here +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indication.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indication.java new file mode 100644 index 0000000..f7c69b7 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indication.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.reflect.Field; + +public class Indication { + public static boolean isIndicated(Field f) { + return (f.getAnnotation(Indicated.class) != null); + } + + public static boolean asArray(Field f) { + return (f.getAnnotation(AsArray.class) != null); + } + + public static boolean isBase64Encoded(Field f) { + return ((f.getAnnotation(Base64Encoded.class) != null) && + f.getType().isArray() && + f.getType().getComponentType().equals(byte.class)); + } + + public static String getIndicatorName(Class c) { + return getName(c, Indicator.class); + } + + public static String getIndicatedName(Class c) { + return getName(c, Indicated.class); + } + + private static String getName(Class c, Class annotation) { + String result = null; + for (Field f : c.getFields()) { + if (f.getAnnotation(annotation) != null) { + result = f.getName(); + break; + } + } + return result; + } + + /* + public static Class getIndication(Object o, String s) { + Class c = o.getClass(); + Class result = null; + try { + Method m = getIndicateMethod(c); + result = (Class) (m.invoke(o, s)); + } + catch (ReflectiveOperationException ex) { + ex.printStackTrace(); + } + return result; + } + + private static Method getIndicateMethod(Class c) { + Method result = null; + for (Method m : c.getMethods()) { + if (m.getAnnotation(Indicate.class) != null) { + result = m; + break; + } + } + return result; + } + */ +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicator.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicator.java new file mode 100644 index 0000000..d1d2ff9 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/indication/Indicator.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.indication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Indicator { + // if later we want multiple indicated fields, use an int here +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Advertise.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Advertise.java new file mode 100644 index 0000000..f41506e --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Advertise.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "advertise") +public class Advertise extends Operation { + public String topic; + public String type; + + public Advertise() {} + + public Advertise(String topic, String type) { + this.topic = topic; + this.type = type; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Authenticate.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Authenticate.java new file mode 100644 index 0000000..517e360 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Authenticate.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "auth") +public class Authenticate extends Operation { + public String mac; + public String client; + public String dest; + public String rand; + public int t; + public String level; + public int end; + + public Authenticate() {} + + public Authenticate( + String mac, + String client, + String dest, + String rand, + int t, + String level, + int end) + { + this.mac = mac; + this.client = client; + this.dest = dest; + this.rand = rand; + this.t = t; + this.level = level; + this.end = end; + + this.id = null; // even though id is on EVERY OTHER operation type + } + +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/CallService.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/CallService.java new file mode 100644 index 0000000..fb9d6fa --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/CallService.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosbridge.indication.AsArray; +import com.jilk.ros.rosbridge.indication.Indicated; +import com.jilk.ros.rosbridge.indication.Indicator; + +@MessageType(string = "call_service") +public class CallService extends Operation { + @Indicator public String service; + @Indicated @AsArray public Message args; + public Integer fragment_size; // use Integer for optional items + public String compression; + + public CallService() {} + + public CallService(String service, Message args) { + this.service = service; + this.args = args; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Fragment.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Fragment.java new file mode 100644 index 0000000..0093eae --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Fragment.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "fragment") +public class Fragment extends Operation { + public String data; + public int num; + public int total; + + public Fragment() {} + + public Fragment(String data, int num, int total) { + this.data = data; + this.num = num; + this.total = total; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Operation.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Operation.java new file mode 100644 index 0000000..98d4db3 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Operation.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosbridge.implementation.JSON; +import com.jilk.ros.rosbridge.implementation.Registry; + +@MessageType(string = "operation") +public class Operation extends Message { + private static Long uid = 0L; + + public String op; + public String id; + + public Operation() { + this.op = getMessageType(getClass()); + this.id = nextId(); + } + + private static synchronized String nextId() { + String result = uid.toString(); + uid++; + return result; + } + + public String toJSON() { + return JSON.toJSON(this); + } + + public static Operation toOperation(String json, Registry registry) { + return ((Wrapper) JSON.toMessage(json, Wrapper.class, registry)).msg; + } + + public static void initialize(Registry registry) { + initClass(registry, Advertise.class); + initClass(registry, Authenticate.class); + initClass(registry, CallService.class); + initClass(registry, Fragment.class); + initClass(registry, Operation.class); + initClass(registry, PNG.class); + initClass(registry, Publish.class); + initClass(registry, ServiceResponse.class); + initClass(registry, SetStatusLevel.class); + initClass(registry, Status.class); + initClass(registry, Subscribe.class); + initClass(registry, Unadvertise.class); + initClass(registry, Unsubscribe.class); + initClass(registry, Wrapper.class); + + registry.register(Wrapper.class, Message.getMessageType(Publish.class), Publish.class); + registry.register(Wrapper.class, Message.getMessageType(CallService.class), CallService.class); + registry.register(Wrapper.class, Message.getMessageType(ServiceResponse.class), ServiceResponse.class); + } + + private static void initClass(Registry registry, Class c) { + registry.register(Message.class, Message.getMessageType(c), c); + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/PNG.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/PNG.java new file mode 100644 index 0000000..7cbda69 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/PNG.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "png") +public class PNG extends Operation { + public String data; + public Integer num; // use Integer for optional items + public Integer total; // use Integer for optional items + + public PNG() {} + + public PNG(String data) { + this.data = data; + } + + public PNG(String data, int num, int total) { + this.data = data; + this.num = num; + this.total = total; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java new file mode 100644 index 0000000..8acf725 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Publish.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosbridge.indication.Indicated; +import com.jilk.ros.rosbridge.indication.Indicator; + +@MessageType(string = "publish") +public class Publish extends Operation { + + @Indicator public String topic; + @Indicated + public Message msg; + + public Publish() {} + + public Publish(String topic, Message msg) { + this.topic = topic; + this.msg = msg; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java new file mode 100644 index 0000000..2d7384b --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/ServiceResponse.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.Message; +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosbridge.indication.Indicated; +import com.jilk.ros.rosbridge.indication.Indicator; + +@MessageType(string = "service_response") +public class ServiceResponse extends Operation { + @Indicator public String service; + public boolean result; + @Indicated public Message values; + + public ServiceResponse() {} + + public ServiceResponse(String service) { + this.service = service; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/SetStatusLevel.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/SetStatusLevel.java new file mode 100644 index 0000000..bf7a16a --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/SetStatusLevel.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "set_level") +public class SetStatusLevel extends Operation { + public String level; + + public SetStatusLevel() {} + + public SetStatusLevel(String level) { + this.level = null; + if ("none".equals(level) || + "warning".equals(level) || + "error".equals(level) || + "info".equals(level)) + this.level = level; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Status.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Status.java new file mode 100644 index 0000000..051a48a --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Status.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "status") +public class Status extends Operation { + String level; + String msg; + + public Status() {} + + public Status(String level, String msg) { + this.level = level; + this.msg = msg; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Subscribe.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Subscribe.java new file mode 100644 index 0000000..a965ced --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Subscribe.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "subscribe") +public class Subscribe extends Operation { + public String topic; + public String type; + public Integer throttle_rate; // use Integer for optional items + public Integer queue_length; // use Integer for optional items + public Integer fragment_size; // use Integer for optional items + public String compression; + + public Subscribe() {} + + public Subscribe(String topic, String type) { + this.topic = topic; + this.type = type; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unadvertise.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unadvertise.java new file mode 100644 index 0000000..0c5d2f0 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unadvertise.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "unadvertise") +public class Unadvertise extends Operation { + public String topic; + + public Unadvertise() {} + + public Unadvertise(String topic) { + this.topic = topic; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unsubscribe.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unsubscribe.java new file mode 100644 index 0000000..94d2810 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Unsubscribe.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; + +@MessageType(string = "unsubscribe") +public class Unsubscribe extends Operation { + public String topic; + + public Unsubscribe() {} + + public Unsubscribe(String topic) { + this.topic = topic; + } +} diff --git a/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Wrapper.java b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Wrapper.java new file mode 100644 index 0000000..c14b3d2 --- /dev/null +++ b/src/Logistics/app/src/main/java/com/jilk/ros/rosbridge/operation/Wrapper.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014 Jilk Systems, Inc. + * + * This file is part of the Java ROSBridge Client. + * + * The Java ROSBridge Client is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Java ROSBridge Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Java ROSBridge Client. If not, see http://www.gnu.org/licenses/. + * + */ +package com.jilk.ros.rosbridge.operation; + +import com.jilk.ros.message.MessageType; +import com.jilk.ros.rosbridge.indication.Indicated; +import com.jilk.ros.rosbridge.indication.Indicator; + +@MessageType(string = "wrapper") +public class Wrapper extends Operation { + @Indicator public String op; + @Indicated + public Operation msg; + + public Wrapper() {} +} diff --git a/src/Logistics/app/src/main/res/layout/my_fragment2.xml b/src/Logistics/app/src/main/res/layout/my_fragment2.xml index d1f3fa6..00f578a 100644 --- a/src/Logistics/app/src/main/res/layout/my_fragment2.xml +++ b/src/Logistics/app/src/main/res/layout/my_fragment2.xml @@ -12,6 +12,10 @@ android:orientation="horizontal" android:gravity="center"> +