From 6369fe4b4697c577a1c190a03e26b0fd66da7cbc Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Mon, 2 Oct 2017 22:51:08 +0000 Subject: [PATCH] =?UTF-8?q?[NF]=20AUserBackend=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IoT.sln | 6 --- IoT/Connector/ADataBackend.cs | 20 ++------ IoT/Connector/AUserBackend.cs | 34 ++++++++++++++ IoT/Connector/{ => Data}/Mosquitto.cs | 2 +- IoT/Connector/{ => Data}/Mqtt.cs | 2 +- IoT/Connector/Helper.cs | 30 ++++++++++++ IoT/Connector/Telegram.cs | 65 -------------------------- IoT/Connector/User/Telegram.cs | 47 +++++++++++++++++++ IoT/Utils-IoT.csproj | 14 ++---- IoT/bin/Release/Utils-IoT.dll | Bin 21504 -> 22016 bytes 10 files changed, 122 insertions(+), 98 deletions(-) create mode 100644 IoT/Connector/AUserBackend.cs rename IoT/Connector/{ => Data}/Mosquitto.cs (96%) rename IoT/Connector/{ => Data}/Mqtt.cs (94%) create mode 100644 IoT/Connector/Helper.cs delete mode 100644 IoT/Connector/Telegram.cs create mode 100644 IoT/Connector/User/Telegram.cs diff --git a/IoT.sln b/IoT.sln index 234c4e4..d3796fa 100644 --- a/IoT.sln +++ b/IoT.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 15.0.26730.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,10 +15,6 @@ Global {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.Build.0 = Debug|Any CPU {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.ActiveCfg = Release|Any CPU {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.Build.0 = Release|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/IoT/Connector/ADataBackend.cs b/IoT/Connector/ADataBackend.cs index 44f6996..7a840fd 100644 --- a/IoT/Connector/ADataBackend.cs +++ b/IoT/Connector/ADataBackend.cs @@ -8,31 +8,19 @@ namespace BlubbFish.Utils.IoT.Connector { public abstract event MqttMessage MessageSending; public delegate void MqttMessage(Object sender, MqttEventArgs e); - public static ADataBackend GetInstance(Dictionary dictionary) { - String object_sensor = "BlubbFish.Utils.IoT.Connector." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower(); + public static ADataBackend GetInstance(Dictionary settings) { + String object_sensor = "BlubbFish.Utils.IoT.Connector.Data." + Char.ToUpper(settings["type"][0]) + settings["type"].Substring(1).ToLower(); Type t = null; try { t = Type.GetType(object_sensor, true); } catch (TypeLoadException) { - throw new ArgumentException("settings.ini: " + dictionary["type"] + " is not a Connector"); + throw new ArgumentException("settings.ini: " + settings["type"] + " is not a DataBackend"); } - return (ADataBackend)t.GetConstructor(new Type[] { typeof(Dictionary) }).Invoke(new Object[] { dictionary }); + return (ADataBackend)t.GetConstructor(new Type[] { typeof(Dictionary) }).Invoke(new Object[] { settings }); } public abstract void Send(String topic, String data); public abstract void Dispose(); } - public class MqttEventArgs : EventArgs { - public MqttEventArgs() : base() { } - public MqttEventArgs(String message, String topic) { - this.Topic = topic; - this.Message = message; - this.Date = DateTime.Now; - } - - public String Topic { get; private set; } - public String Message { get; private set; } - public DateTime Date { get; private set; } - } } diff --git a/IoT/Connector/AUserBackend.cs b/IoT/Connector/AUserBackend.cs new file mode 100644 index 0000000..a90a384 --- /dev/null +++ b/IoT/Connector/AUserBackend.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlubbFish.Utils.IoT.Connector { + public abstract class AUserBackend { + protected Dictionary settings; + + public abstract event TelegramMessage MessageIncomming; + public abstract event TelegramMessage MessageSending; + public delegate void TelegramMessage(Object sender, UserMessageEventArgs e); + + public AUserBackend(Dictionary settings) { + this.settings = settings; + } + + public static AUserBackend GetInstance(Dictionary settings) { + String object_sensor = "BlubbFish.Utils.IoT.Connector.User." + Char.ToUpper(settings["type"][0]) + settings["type"].Substring(1).ToLower(); + Type t = null; + try { + t = Type.GetType(object_sensor, true); + } catch (TypeLoadException) { + throw new ArgumentException("settings.ini: " + settings["type"] + " is not a UserBackend"); + } + return (AUserBackend)t.GetConstructor(new Type[] { typeof(Dictionary) }).Invoke(new Object[] { settings }); + } + + public abstract void Send(String message); + + public abstract void Dispose(); + } +} diff --git a/IoT/Connector/Mosquitto.cs b/IoT/Connector/Data/Mosquitto.cs similarity index 96% rename from IoT/Connector/Mosquitto.cs rename to IoT/Connector/Data/Mosquitto.cs index 6f856c5..2e13847 100644 --- a/IoT/Connector/Mosquitto.cs +++ b/IoT/Connector/Data/Mosquitto.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text.RegularExpressions; -namespace BlubbFish.Utils.IoT.Connector { +namespace BlubbFish.Utils.IoT.Connector.Data { class Mosquitto : ADataBackend, IDisposable { private Process p; private String message; diff --git a/IoT/Connector/Mqtt.cs b/IoT/Connector/Data/Mqtt.cs similarity index 94% rename from IoT/Connector/Mqtt.cs rename to IoT/Connector/Data/Mqtt.cs index c031382..309a0b9 100644 --- a/IoT/Connector/Mqtt.cs +++ b/IoT/Connector/Data/Mqtt.cs @@ -4,7 +4,7 @@ using System.Text; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; -namespace BlubbFish.Utils.IoT.Connector { +namespace BlubbFish.Utils.IoT.Connector.Data { class Mqtt : ADataBackend, IDisposable { private MqttClient client; diff --git a/IoT/Connector/Helper.cs b/IoT/Connector/Helper.cs new file mode 100644 index 0000000..41e3b27 --- /dev/null +++ b/IoT/Connector/Helper.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlubbFish.Utils.IoT.Connector { + public class UserMessageEventArgs : EventArgs { + public UserMessageEventArgs() : base() { } + public UserMessageEventArgs(String message, Int64 UserId, DateTime date) { + this.UserId = UserId; + this.Message = message; + this.Date = date; + } + public Int64 UserId { get; private set; } + public String Message { get; private set; } + public DateTime Date { get; private set; } + } + public class MqttEventArgs : EventArgs { + public MqttEventArgs() : base() { } + public MqttEventArgs(String message, String topic) { + this.Topic = topic; + this.Message = message; + this.Date = DateTime.Now; + } + public String Topic { get; private set; } + public String Message { get; private set; } + public DateTime Date { get; private set; } + } +} diff --git a/IoT/Connector/Telegram.cs b/IoT/Connector/Telegram.cs deleted file mode 100644 index 98a0531..0000000 --- a/IoT/Connector/Telegram.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using Telegram.Bot; -using Telegram.Bot.Args; -using Telegram.Bot.Exceptions; -using Telegram.Bot.Types; - -namespace BlubbFish.Utils.IoT.Connector { - public class Telegram { - private static Telegram instance; - private TelegramBotClient bot; - private ChatId chat; - - public delegate void TelegramMessage(Object sender, TelegramEventArgs e); - - public event TelegramMessage MessageIncomming; - public event TelegramMessage MessageSending; - - private Telegram() { - this.bot = new TelegramBotClient(InIReader.GetInstance("settings.ini").GetValue("general", "telegram-key")); - this.bot.OnMessage += this.Bot_OnMessage; - this.Connect(); - } - - private void Bot_OnMessage(Object sender, MessageEventArgs e) { - this.MessageIncomming?.Invoke(this, new TelegramEventArgs(e.Message.Text, e.Message.Chat.Id, e.Message.Date)); - } - - public static Telegram Instance { - get { - if(instance == null) { - instance = new Telegram(); - } - return instance; - } - } - - private void Connect() { - this.bot.StartReceiving(); - this.chat = new ChatId(InIReader.GetInstance("settings.ini").GetValue("general", "chatid")); - } - - public async void Send(String text) { - try { - Message x = await this.bot.SendTextMessageAsync(this.chat, text); - this.MessageSending?.Invoke(this, new TelegramEventArgs(x.Text, x.Chat.Id, x.Date)); - } catch(ApiRequestException e) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters); - Console.ForegroundColor = ConsoleColor.White; - } - } - } - public class TelegramEventArgs : EventArgs { - public TelegramEventArgs() : base() { } - public TelegramEventArgs(String message, Int64 UserId, DateTime date) { - this.UserId = UserId; - this.Message = message; - this.Date = date; - } - - public Int64 UserId { get; private set; } - public String Message { get; private set; } - public DateTime Date { get; private set; } - } -} diff --git a/IoT/Connector/User/Telegram.cs b/IoT/Connector/User/Telegram.cs new file mode 100644 index 0000000..251ca50 --- /dev/null +++ b/IoT/Connector/User/Telegram.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using Telegram.Bot; +using Telegram.Bot.Args; +using Telegram.Bot.Exceptions; +using Telegram.Bot.Types; + +namespace BlubbFish.Utils.IoT.Connector.User { + public class Telegram : AUserBackend { + private TelegramBotClient bot; + private ChatId chat; + + public override event TelegramMessage MessageIncomming; + public override event TelegramMessage MessageSending; + + public Telegram(Dictionary settings) : base(settings) { + this.bot = new TelegramBotClient(settings["telegram-key"]); + this.bot.OnMessage += this.Bot_OnMessage; + this.Connect(); + } + + private void Bot_OnMessage(Object sender, MessageEventArgs e) { + this.MessageIncomming?.Invoke(this, new UserMessageEventArgs(e.Message.Text, e.Message.Chat.Id, e.Message.Date)); + } + + private void Connect() { + this.bot.StartReceiving(); + this.chat = new ChatId(this.settings["chatid"]); + } + + public async override void Send(String message) { + try { + Message x = await this.bot.SendTextMessageAsync(this.chat, message); + this.MessageSending?.Invoke(this, new UserMessageEventArgs(x.Text, x.Chat.Id, x.Date)); + } catch(ApiRequestException e) { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters); + Console.ForegroundColor = ConsoleColor.White; + } + } + + public override void Dispose() { + this.bot.StopReceiving(); + this.bot = null; + } + } +} diff --git a/IoT/Utils-IoT.csproj b/IoT/Utils-IoT.csproj index 2e1426c..6b26fdf 100644 --- a/IoT/Utils-IoT.csproj +++ b/IoT/Utils-IoT.csproj @@ -109,9 +109,11 @@ - - - + + + + + @@ -126,11 +128,5 @@ - - - {fac8ce64-bf13-4ece-8097-aeb5dd060098} - Utils - - \ No newline at end of file diff --git a/IoT/bin/Release/Utils-IoT.dll b/IoT/bin/Release/Utils-IoT.dll index e0255a5a5d272b520b9c72b5ea4895bf8a795f97..3552837d0b70b4ffa316af74276d9372e28233e4 100644 GIT binary patch delta 10147 zcmb_i36vGpnf~vsdiCnn+h4Ch1Fu;hz0pJvkgZ#Gx`9S$geZXqT0nsZuR*{DtDgdj zHU?8hqhlNv6E`M?fEgTP4knx)J!&E`F_=*TMwy^lToV}+GT(ozdO=#xnVc!8um1J^ z_x^XSdfoD}%PkynGyz4aeO9n+H(JTlISNQmvyC0t)S+Is^HVayamS|3P zW^Rxu1U|W%sK_anWzIq|*!uoV7U7=d+#yOuo%2I6Sj=-yiGDp=Q37Ana7*%0)kvb# z!-<4*qIRTHC-;kW&PQ^GnCfiNMv65D4r$W)W8Ck&?<;g(@%0c1=Uv}s*eo+%5!0RF z{-2BKhjp`;1e3Ie0_&_S1T2Ye7IchD87i+XmW|k4HOBWJZnF&t6;QYQ< z$W$IUscp+4(o3jUrH>v!?F3OgbA#smr#0ge&%^K>IRkVdJcuH=U=H3<*rP_Vzgkk$bN{eh+8^5kRJA!!H-lDrKM^?mcRoM zTn|M+fTp+tML^J_U7(1ZN{xn~ettAZHWxu>89~36DyJY>8*=xC z+>F1t6&YAA2bD-YjnQJIG1e@P#0ay}b)EbikWJ&^nBK_V+@i_D&?Hkei38;(=t5q9 z*TTVE!duI8-tVX~Pqy#Rd1ucJG$7Fe17 zpky<9*_l$7s#!A{RB90PmaEH*W7St7C@VHHQ#*WId8f-YU0h~&by?KuqU7DU*yzml zU45E6eU!W#AGqAv)y3&_QSwV%I#OU{_Q5t)h6<;z1;}Q*LsyVqq$C}J{Pfo@78Ilx ze_pVpLm)30@Hd(oAW1LnDn=krj0FlIReH3OUL;$U*2);E?qj#pFzjj-Z*r7^x~ci zx~(tTjpaxT%=hmfSdjTOGO>SPp`JMdBJ&RC=xwquuHq0YozT3uyH%K-H7|tNUIJq(ksBoW}b-Nnx-|OR3p6}P%>XnuY|rVAHtdjE3vyt7I*msf+Yj0>kx6VpmeoaE*eOo0gAVC?usfTB z^_p9gIg40oim0`u1WPUl?5gB7!d0RLyyjw4QlcE(hG&g+Y3csIeX&+MqxT)&-@CkImcaB?t$>RbmeAg`#S5b z+?|G9*V%3i(Zp^_Wa;Nh>@@6JVu#_wiKN}RjFw5QbJ}X1>u9P68kL`$o8N?e(AqWt zVM_D6+BV(TE|;n6c4f7PirRR8XYH zvHB(eRv*?Ec(W_>F1mex!R~rB*9sm?H?vL24`nlF#~u8st&r*IZCu37isZ68M^H(d zTc+k2wyM4eY5m-ITE*iji0Rrso}Bmc`&aOJ!{5wj3E7NX>G`;F6S{l;z)aqOqSHG8 z;e?jD%^6!T)!qdzw)E%QvLj59Wy-#*m=r1RiESQ8%o^)VXxgd zU}9y9`_gxU<@JsCV61PDv_jI#=VxBqTyal`ce7#YE@0~GbU9glqpGM=bgD;=A^Tp~ zhRscvTg!oQBee&1r*bY9r|xz}6&8sSr@nB2_=a;+VaXL$ICAz!j~>Lc74xqD+zpvk zYgb^B5{<$c^L-y=^>ZnOw4ln=e`@{oNvs>{oGL7_vBOaw?n>NSa3fKq#{>cG@jM#A4e@kclD!qq7SBfW1gIWy^ z7WJ`wr^164(^U!=8%*zwFpiJe{CG9M7!O`;S@a(i2paScm`3Qf*i*3xjS{bhBh(a` z8Zl_H#Q{E60bUMrm@O*6c;6=2T&=$f$rNJx6RRX@&_w^_aDu)QWn37U9L}fvV<%$< zt(L>BeA*uQt{twShb*F=v|B%jz`3d&^N1_d7JJf6(2V$nNP-Ro7{435fJ)q;s(UoZ zHosGCdRXP4caZb9QnfFwGO^L%>TXe`m8<3r4{`IJSN1~?%TCZ;78flHF8Wy%+K0Br zcEM;Q+#>YzD7SvC?+w`02Du%d0uA~x0w<_&{vjMle9FNCTU$78n{ zoQbUkGZx(U1I#4|8yvW7oVgt8uedvuWeyEg+(wVXf&$COlwXc|{fd!&Mc8#LRRRA+ z3x}&wOu6D7^|%qJLX6UpaCj9uXq@66R9pc~R$M=8LZ}R#I8%jK6ugU4)JH9iG5T|i zxdGHb5|iRIn%Mw;wc^&|)jlkcSjE@Jm02k{VWq9Cb zC1*q|TPyYgJRG~_Qnh9nJ87aezooZzEpT&;@j~=k&7iC?5%_lSHsIrtR-hXoOnbDt zB$7ot3;p2-Q0Bs7=CWjA&CqG1$IZ|mLF4SBioKWK(!Pfx_TU6VbX@!$rU80Wac!cf zl?Tqfj{CNmKhi7;@JOSb=DX3KXhDiAZoB!{XdAemo=#dBybtvAbP<#iqEb(HT};=) zbeZib*T)3ToMS!Z+3<^6geG~qkHfEko9XG+1b-l+RPX7UgRf~(`kJTv(A2dUU8lIL zdBIe}*3&^?~x1mg`YhhFly8Q^kB zAHaUcMbyZ{?y=qF=pigN`E*2aXQ5;6r;2mCBAfZEOekD!6g< zEmaC<<{#R4dQ@>XhY#oz+D#EYMpYdghp(n3IEA_0#N5gbE?2Ln9WH0~6Waw1V-0ndc@V)W^dyMVhTO!DF+#^X;Ur=IF*jNrl|Kv+EjYo z<;)Y*O4I3#=l5S&pr_Njo{j^~pbtGA2b@8lc{+|)Ls}^}DQnssu!cg4Z8JHgwKU1& zIHfabtH*IlXVDRlDk;{48~cRVg? zBf<0NZ!U}QZ)w>3%ej~~lZQ|}t@bz`Li6cikK-Y9HNBxYH~a!Rf)gJ65aJ_kAvFwR zE=xZWL-cECv&WqUw}_UjQOncU&ZEV2)MeHDT|&QCTpMxUFQHFePE~CQRjL8*R;__n zdK_16Ded(*uG%s>sW`W4%c)9Dg)DI{8tD;_tC7QOy^(&UShwCQ$W-&hU0PPrYL`=0 zyPh6YoLjZ)xp_E_a)<@g&b5i1`e=Q%r)v{gy-Hu(!EMrO^o+;3es)ubawj%~jU8N8 zpQGb-43|c2f*tWvr8w6SuTzTSfY<6ce|ub3U#7P()8V(B4ytOO5mB6jc2K37>u1Cq zUy^q4`p0`Xe|NWVp4PCFv*d#yOTJ?=%@Rr1##zfYg33V)PrFOm{ByW9fcV{ocLQHq zEm!V_|03=GNpAlW;lHS@99ZCN#M%0(%IlX~vc1jc5_V&hGz_OKjppJdM$o0st_=t1 zPJ5}nD{-sUwL{&AN^5r$X7nZP=<3{+-ilMn7gy!dz+H3W`r2W<6H0pal0nxQMx!$b zqZ3;qPYVCvy!iavb+mUEtidO-VMKBB#*s(g#$n7K7C67~e%J$O;WY0@orWnKt*~0* zbcJ&iE>ze6%%fF`UQaf=ZBa~CEi(H+<9${5!#!!Vnz5tROkD^G4xLIHqGzHNbhr2< zas}Z;XVv1%Z-FtF9)ryS9Mb*auK{1eT6aIK2sY9oaUgI#JtyvuX6P{*8ov?00<4MN zLMKF-9l8yV#er6cGJ!p;2r+#;`b|1SxB4EW*HLH;^bhp|z|!y&bPh|-5oPmZ`aoRn zdzsFQ75eL-ziz&akn4^2fWJWafV|iIfX=Drouk*I7x25oA3`xm&iHh3jt=^4UEEKL zga!PWFABU5*hA{EJn;cq)=Ol`t=x)uu_%@W#$d>wiI$06`Xn+|JS~<+r;A~-)S4|u z%LQgD+P63`UvL8&1ZQQ1@=A*nDsuvj*&&KRFCZZ*^m}a)7lyuHREq)eR;m^+MjsUm zWiK2iss-=VLfjL0Rs>WIhKL3DeQ}6*DfSxVJ8>>-fShrB@Ds60{vG>#i0a~FRrt>! z`L}3{R>_fZ^tYT~GJYImd@_`W*B7pY-5@>_nrslSD10fFL2-pX1L^&Z7Ki*RNaHGT z2#1X=aEL+ve4t3aAexYm7sMlGu{?xI3mt`3}gz!VeZQ?ZOn%JlEguE;CcX^)pj5J5s zf6{bqj@T46HSV*Bc0!ion&g78_w;})uMxijN zuvlT0!fJ&}6gDVqQJ7V@SK&T|#}q!N@U+4+3Q2PLNuYhXR;8FF3R@Ir74B8IPvHTD z#}q!N@U+4+3Q1GdRhU#*tT3x^pF*LtO|im#3ZG-NwY@%898-8&AsH;$tMHh@(+bJY z^3w{*WICy^O5qZPEecO7q=2$fSfy}@!WM;l723zt^S{}t`ygZP2%6h^Wt~n17XPmSu6KQiKX7cZWF|A62bSO zD490abPF5m9Ag@Ac%T;e8vB+G#F2gnc0lB>F767TbBk$^bXUZUlZB zz6odtZD1_Gl6Um&z`;HrKZc3hfmbV0iNQv{C6;$coXO=i_6YpA9m9uP6K#kfm_Q2x z;6|beF&d@X7DMZJYYIX>6P1bK?=?cOPoQc7b0rM2)v@@K+ypA7%c@#yqM)dekIVPWpIzta-gJ%C`8aC zpronTEd_q@=>d8=rmVnwQ7_On_@*YP7AVoYzNpNPfie0eFpu8HceFhEkb;A0FpUtq z#c}y-=eCOec3Iwcm-A4FWdCzb2ixs7X= zk6*rc@vvde>Y>*-uMQpTRFCcLtC-ZVq2ciPp`S`$b$wG~#yR(u5&G1|4bu;gy6k}N zygl+CW_sOKjmsKW-FW!TQ5Dk38($n+z{u~xS@x8k6$XC?Nv(- zzf*Nm;;&|6)hXxf#9aR*^wAW9ndy}#-B+cm9k?wW1>>f~Cd zb;=;|ZRhZmeZFZ4{Bssg?JcG`o2Kru>k{~Tkz{0&kh6W_sjUac*{4@nLvLfcJNpq{7xt0^Gv^% zsO5hgt5)-ih$<|9grD>XUk0KjvZD>ZOtc(wDyQ|ft078cC$lEe@}?P08X{uKM0Ps< z$Fnn4^k-eSIV$3_dQ$izXotUdq_+>EM0O!63Nk5JkQBXrC{6lZ23CcBznK_?mgU7; zzJnZK(_D!ENdy;0v>op@WO&XSNBwDfzJ0PfI;t+^hCZ5&} z=$k{5B+NL!9Pu|fB%n9Jbie1t%8b;+~N3De-?LF`u`WBU12K# delta 9879 zcmb_i3zQVqnf~vs>gww1ch8G~Vd&x63^NE(gu&rG$N&Ql;2?-R24=(oq_GDhWEiVk zffybtlrJps>NFaL5V$7PvHBmQ`{r+1u4?sQcIa^JA z^}p_a|9k)Ysv5FSi0q@{&fEH5z5I=ZqHBseU z;y*5`4(Mhd2_|V>1gy7a1Akx@J8xMF<3$>+lbIDn>(af5tjs89a&UfCsZ31=SAL88 zlzM6mnklu^Sbn6E(50$DmY2%5JR-fkztq~9a5jeq49Xj!(NF~MCyL89xYaEq=+{z} zD7HR7zUs|qMmFw2^EXTS6=Va8dO|Ch0iHfS`}!vW+o~R9KnC=!i73X=OHYm$Y%IOpb-BU+w^v8Vt4NsT@|#f}od8B8V1Knkmyt|s7MPBY%4APOM0Dub5cCN8d{Rp%zo{?g0^FU*|({LG!#J)K2*B+j4t z`owV&o5xO%%=t54pSjLzRD#?w<j7Mu}6c- zT*e)P70cQ;s5mo8>3VDX2KC8Y!F1|!XjGnEPi~4`+RbjKoD!nC%x&`ew%IE9pMKGucxzE;XzNU|lk^kYip9 zZPi`~WgAaeHFZ-<*w;;-yAkxD!t`=H(vty2X^b-~ zjWK9hJ;c4b#c3>o7V?1Uf!1h)hlQoz@S20xNH4x>pEpC)Qc^D63VSMfjj&xUT97wF zs&yPBTGJcOD<^0b!@aTH1Y3`623d*v)s(xoTfUOXe0Q}fYG()Kec&_B4sprC^i+g* z(l1j{SpJ%4iikP47bSu$m#J?-TJE%kOGU!DKRnv>mfyZ=87+mo3zz27^K?CzSk@Id zZx6}L02uEKQbo$$F4cwgcO>C5}x= zI0g%KXW9{kyAk8~fsGhF)ic}Ju6ZM7sp(JY&S77^-!pV36cm^}6$4$xz%TW{((^nF zWDjpsRRlx1a)bOO*05Y=#RAwz8y%B7F>vw?dW$-WC6rMG( z9T=@`5T`c*WD0ALQT`XVab6PWU=$oh;3z?| zeK^Dk(%Lb#@JwxntM*Do7qnO4X|ypHOb94_=)Uqy*FkJ4V#GnLksrR)3XUI#ut6|a zhcHDzfMuxEm4MROWJsrpB8Z&Fiv|qmHu>8)O4-K26ynNH=x!UaK5s>2>F)x<2`zP- z^S7dD_BL=Ke;X%PEtLKJCOVreGu_qAW;zE!cMqRz$n*6JrM5%ZXJ<^!#keoM11xV_ ze6+&01<6iGcHq<|c*kMN=hoZRQg^w&s$2>Y& z$yhFM3;u&ut9#4@c|=iBFlO`PV1V(@))>p8d+7tvr(hbP?a^>JLS>O~I6-#o`Ite|WdRoJ+Q`~)AzdGP zAXZ2P;sMa3BhiRKgDtN9ZB_jwF-AnkZoR4ZQ7>Vde-8;oUPhd zr+Q+M!2xYl-XcM6UcV4G?-CSjvM_5Y0jq^CH8sN66a(QGARjdrV1&65$H)wC7!aS-(r7_Ax z-VC*X<8?1aePNt&m)WvbjDx`res!=q?eBc-TGaq}@< znyG@CY{gb##xZ-H;&hK&Lz;-GbHtO-t;5tiLen&zcEx6Bf{e&4&|9#22*QtftgC-;%r5?D?BQ>@b+LD zI92Du0|M)Tub7NnwoC;iXj^Q^s3 zH?#=Vc*>uK{{!4CPd7Vwt&CEGr@JQjjuxdQp6;|6)M9k4;&SF6OdgDBPxmu@2WHDn zUb&a`7`UvbdtJA8VDj9i*jvrFp-j+So^p`!u9inX_qY+@@<|`4`a*o-E1&|}>~gdd z9b8BU756@L%pFynn~FmEPtTJ3u$b=R8R@3U)_T)3ihYS#*_RGupGPW)Q&CEFJYDG+ zaVkpbkBW1h_M<-7-Pn@L^`|Puxw-)~vxjalrF-ax(EUAhcKJC4hn-V!_&EhHI;SAs zN7QvJ><^sLF7Dz=z+vb2bU!lBXuNLlbu4@Y+@jiZLTj`>=(&$TgK z9CzYaTF0vsZN_+JZiC{uh0JBUxX-n*)ZudGQ?!Gs=`qFS%x5qTs_AJ@_o21}%hq$A z?o*7IabzF$l$vp^98a%$%8>DnHlBW|xML=_Z~}$+*h|MuZsA0#@i=bbB--S0+``Fp zP;ne6=~HM24uYIQZeR^n;mF97a*wd|%c*rQ-;shUp}n1(#OX3(83r-s)|I;^;3 z#62^UUUNAW+DtO}^x}n9M-x4cLz_h#JdQ(~O+Qwg8`>4rYozM`9DR=6xSs5h>?TJk znb7O$NyWKw&!tm}b3?n5YE=4PQlT}_dd0b+HPB|oZAECk^#=N>$CZGaPyg+4KQepk zS5d{qI9u~#as=!GYEq*pr}Ddyo^?6uuP60|^jF2*V?M2=^hFd?Bg_qZ5iL;MR&+4$ z7ClGFHMGao!Dpp@4gJLB%)irexs;v>19vJ!(gg_y3$}WkTjBaH-5Pzdj#o`w>}93iq~lG@^T6}_oTsy71l(qJ0 zG1`|@r(WJt@hVAw)Y-)rjSnEd#`#9lT_)2kku)vNTDB3?3$*aG84=Y{54x&~5)!ZRH*kII3`O?FI6QfoYZqIvdTzC25hMk+r?%;6#`TD{=tI1O>b6XP;JPxYxx^qFBAo)1TE#7&-80z+> z(GetFx0NZnD8`Pyak2l0Qqz2rrji{3gmLH7ew=lVhXjrXyulO$E&TQ4cqm3A6;>&n zq;R^zISLmlYy=iii=uB(xKUwFt&ts|@%AK+hk8?^nt+XJ-sNnF3@o{fA?k<@r(NP# zk+GmdRvo^Rf8m=)kHKaE?Sah_;M17Bd#EcR zC<=WSI6JTdlE%QDz)>Nle;B`ShzuwRl$4MyHFBGGtvLs^oZc z2ii9~Fkf&B8U^>tN>wT?UROOQR4)qAFZew%UA~KBT!=1R|xT>!lz>yNY3g8_lNcfxUKI#}=9A7Y`Dr*V9kRX}1U~zJprC{^&Jwzx)&%V~gNj zZm761aDyDFf}1188=K`E@pNn(PAV9vS<)JR#?YbnP?Z zJ#?e^r54mSip9~W#)&J?PRN9>k2XjAla&Nsh7jl2Y8sgI4>U$I=}{U7e1axx!}0BS zw>})Noeu!}&~v~6bQCy@eh$1?;bjV^DEUl!1M+!FvPj_y`T&yEl73LJ) zDsQ!6x>qqB3J)thrI0igsluefGKC!qUsTwrvrSH6hr$;Xo>sWm$J)aRPbnmWC8rdU zAKx|+DIVjri3*n~%qrZg@UX&D3dv+k3NR)WPE@$eMT_NGg?kkqR=6ykE6 zz^7OoA@CAk0~`>j1-@c3el=aEZ0g`ckR8OTAAz$doDrRlrmYXOpjA^%wU@%+V_AFar-%PlX{`L7ns8=J?`OWZ= z_BcrJWd$e^O8~kk(4+}yXpAPR=Eg7~cy9_qUW<6KpaCV`SHqC!0ZqIzL?E9Dl-SRr zkQV?=Oo|wOSK^jUg=Kwk!9fw!n4&#S_+gn8uta=2$VSd_5-~FDDic-AHv%K4AVYfKApmMsC@b@4Z&}em?U47C#9a{ zUEfKLD6t1?kD&kg!m*(1`oLlmUD?xyw54^ydF@pbIab~V=deG zVC!Cw<9I|N*NTpWuEvm zyg8qaSQMA0k__sZt=OQ)}GUEjENMKeunUf)Hx z9C+iBhjk621L-QCIB?6@l=QEiKDW8CsoD9*>dgmcj|)p@>4c%?mCb9KS7sWocW$0g z6`8!|#^uW|Z)v@5c*FXZH3tq&Xp&;RQ!u&dz=p{uq!{PCH?`WiZ)!g=WcQT(_!LUh zTKt-kpY@d|^Lc{hMWOt3zaCv!x=<4)8zgqm> z^ONs>@r(QJAHU;sXG85^vETVYZO4F`1b#u1iR@?YzfeqQrGzh{{L?LwsBu}LqtrO$W`HA zJU7ng7x64UjB~L`NG%vWDSQ!sQu_Nw`uZSB=cFW&-QqoWsRDH# zhyNl#i7|cz6S3kAT#@DMuj@CeB5^~B8&$QH)Dzd2B&s3NQWV0Czp|03rw|WA1GtEe zZ{}lm&pNG-7W6G=*tpVZopWngj|uFp2A%(33{#v+ute13-Mt>0$lQ4~^M