diff --git a/Birdmap.API/Birdmap.API.csproj b/Birdmap.API/Birdmap.API.csproj index 0510550..cc32bdd 100644 --- a/Birdmap.API/Birdmap.API.csproj +++ b/Birdmap.API/Birdmap.API.csproj @@ -35,8 +35,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/Birdmap.API/Controllers/DevicesController.cs b/Birdmap.API/Controllers/DevicesController.cs index c1cec49..0b345be 100644 --- a/Birdmap.API/Controllers/DevicesController.cs +++ b/Birdmap.API/Controllers/DevicesController.cs @@ -1,15 +1,14 @@ using Birdmap.BLL.Interfaces; +using Birdmap.BLL.Services.CommunicationServices.Hubs; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using System; -using System.Threading.Tasks; using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.ModelBinding; using System.Linq; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.SignalR; -using Birdmap.API.Services.Hubs; -using Birdmap.API.Services; +using System.Threading.Tasks; namespace Birdmap.API.Controllers { diff --git a/Birdmap.API/Controllers/ServicesController.cs b/Birdmap.API/Controllers/ServicesController.cs index 79aa554..90d77a9 100644 --- a/Birdmap.API/Controllers/ServicesController.cs +++ b/Birdmap.API/Controllers/ServicesController.cs @@ -1,9 +1,8 @@ using AutoMapper; using Birdmap.API.DTOs; -using Birdmap.API.Services; -using Birdmap.API.Services.Hubs; -using Birdmap.API.Services.Mqtt; using Birdmap.BLL.Interfaces; +using Birdmap.BLL.Services.CommunicationServices.Hubs; +using Birdmap.BLL.Services.CommunicationServices.Mqtt; using Birdmap.DAL.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; diff --git a/Birdmap.API/Extensions/ServiceCollectionExtensions.cs b/Birdmap.API/Extensions/ServiceCollectionExtensions.cs deleted file mode 100644 index a765a80..0000000 --- a/Birdmap.API/Extensions/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Birdmap.API.Options; -using Birdmap.API.Services.Mqtt; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; - -namespace Birdmap.API.Extensions -{ - public static class ServiceCollectionExtensions - { - public static IServiceCollection AddMqttClientServiceWithConfig(this IServiceCollection services, Action configureOptions) - { - services.AddSingleton(serviceProvider => - { - var optionBuilder = new AspCoreMqttClientOptions(serviceProvider); - configureOptions(optionBuilder); - return optionBuilder.Build(); - }); - services.AddSingleton(); - services.AddSingleton(serviceProvider => - { - return serviceProvider.GetService(); - }); - services.AddSingleton(serviceProvider => - { - var mqttClientService = serviceProvider.GetService(); - var mqttClientServiceProvider = new MqttClientServiceProvider(mqttClientService); - return mqttClientServiceProvider; - }); - return services; - } - } -} diff --git a/Birdmap.API/Startup.cs b/Birdmap.API/Startup.cs index fa906fd..3db4a85 100644 --- a/Birdmap.API/Startup.cs +++ b/Birdmap.API/Startup.cs @@ -1,8 +1,7 @@ using AutoMapper; -using Birdmap.API.Extensions; using Birdmap.API.Middlewares; -using Birdmap.API.Services.Hubs; using Birdmap.BLL; +using Birdmap.BLL.Services.CommunicationServices.Hubs; using Birdmap.DAL; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; @@ -42,8 +41,6 @@ namespace Birdmap.API services.AddAutoMapper(typeof(Startup)); - services.AddSignalR(); - var key = Encoding.ASCII.GetBytes(Configuration["Secret"]); services.AddAuthentication(opt => { @@ -64,33 +61,6 @@ namespace Birdmap.API }; }); - services.AddMqttClientServiceWithConfig(opt => - { - var mqtt = Configuration.GetSection("Mqtt"); - - var mqttClient = mqtt.GetSection("ClientSettings"); - var clientSettings = new - { - Id = mqttClient.GetValue("Id"), - Username = mqttClient.GetValue("Username"), - Password = mqttClient.GetValue("Password"), - Topic = mqttClient.GetValue("Topic"), - }; - - var mqttBrokerHost = mqtt.GetSection("BrokerHostSettings"); - var brokerHostSettings = new - { - Host = mqttBrokerHost.GetValue("Host"), - Port = mqttBrokerHost.GetValue("Port"), - }; - - opt - .WithTopic(clientSettings.Topic) - .WithCredentials(clientSettings.Username, clientSettings.Password) - .WithClientId(clientSettings.Id) - .WithTcpServer(brokerHostSettings.Host, brokerHostSettings.Port); - }); - // In production, the React files will be served from this directory services.AddSpaStaticFiles(configuration => { diff --git a/Birdmap.BLL/Birdmap.BLL.csproj b/Birdmap.BLL/Birdmap.BLL.csproj index c604365..59e5e5c 100644 --- a/Birdmap.BLL/Birdmap.BLL.csproj +++ b/Birdmap.BLL/Birdmap.BLL.csproj @@ -5,6 +5,9 @@ + + + diff --git a/Birdmap.API/Services/IMqttClientService.cs b/Birdmap.BLL/Interfaces/IMqttClientService.cs similarity index 93% rename from Birdmap.API/Services/IMqttClientService.cs rename to Birdmap.BLL/Interfaces/IMqttClientService.cs index 8316d9a..e55d726 100644 --- a/Birdmap.API/Services/IMqttClientService.cs +++ b/Birdmap.BLL/Interfaces/IMqttClientService.cs @@ -3,7 +3,7 @@ using MQTTnet.Client.Connecting; using MQTTnet.Client.Disconnecting; using MQTTnet.Client.Receiving; -namespace Birdmap.API.Services +namespace Birdmap.BLL.Interfaces { public interface IMqttClientService : IHostedService, IMqttClientConnectedHandler, diff --git a/Birdmap.API/Options/AspCoreMqttClientOptions.cs b/Birdmap.BLL/Options/AspCoreMqttClientOptions.cs similarity index 94% rename from Birdmap.API/Options/AspCoreMqttClientOptions.cs rename to Birdmap.BLL/Options/AspCoreMqttClientOptions.cs index 02ae31e..f0e1191 100644 --- a/Birdmap.API/Options/AspCoreMqttClientOptions.cs +++ b/Birdmap.BLL/Options/AspCoreMqttClientOptions.cs @@ -1,7 +1,7 @@ using MQTTnet.Client.Options; using System; -namespace Birdmap.API.Options +namespace Birdmap.BLL.Options { public class AspCoreMqttClientOptions : MqttClientOptionsBuilder { diff --git a/Birdmap.API/Services/Hubs/DevicesHub.cs b/Birdmap.BLL/Services/CommunationServices/Hubs/DevicesHub.cs similarity index 92% rename from Birdmap.API/Services/Hubs/DevicesHub.cs rename to Birdmap.BLL/Services/CommunationServices/Hubs/DevicesHub.cs index 9938b42..56130c4 100644 --- a/Birdmap.API/Services/Hubs/DevicesHub.cs +++ b/Birdmap.BLL/Services/CommunationServices/Hubs/DevicesHub.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; -namespace Birdmap.API.Services.Hubs +namespace Birdmap.BLL.Services.CommunicationServices.Hubs { public class DevicesHub : Hub { diff --git a/Birdmap.API/Services/Hubs/IDevicesHubClient.cs b/Birdmap.BLL/Services/CommunationServices/Hubs/IDevicesHubClient.cs similarity index 86% rename from Birdmap.API/Services/Hubs/IDevicesHubClient.cs rename to Birdmap.BLL/Services/CommunationServices/Hubs/IDevicesHubClient.cs index aa4fef1..35de290 100644 --- a/Birdmap.API/Services/Hubs/IDevicesHubClient.cs +++ b/Birdmap.BLL/Services/CommunationServices/Hubs/IDevicesHubClient.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Birdmap.API.Services +namespace Birdmap.BLL.Services.CommunicationServices.Hubs { public record Message(Guid DeviceId, DateTime Date, double Probability); diff --git a/Birdmap.API/Services/Hubs/IServicesHubClient.cs b/Birdmap.BLL/Services/CommunationServices/Hubs/IServicesHubClient.cs similarity index 68% rename from Birdmap.API/Services/Hubs/IServicesHubClient.cs rename to Birdmap.BLL/Services/CommunationServices/Hubs/IServicesHubClient.cs index 6891865..a03d125 100644 --- a/Birdmap.API/Services/Hubs/IServicesHubClient.cs +++ b/Birdmap.BLL/Services/CommunationServices/Hubs/IServicesHubClient.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; -namespace Birdmap.API.Services.Hubs +namespace Birdmap.BLL.Services.CommunicationServices.Hubs { public interface IServicesHubClient { diff --git a/Birdmap.API/Services/Hubs/ServicesHub.cs b/Birdmap.BLL/Services/CommunationServices/Hubs/ServicesHub.cs similarity index 92% rename from Birdmap.API/Services/Hubs/ServicesHub.cs rename to Birdmap.BLL/Services/CommunationServices/Hubs/ServicesHub.cs index 17f3ae2..c4881ec 100644 --- a/Birdmap.API/Services/Hubs/ServicesHub.cs +++ b/Birdmap.BLL/Services/CommunationServices/Hubs/ServicesHub.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; -namespace Birdmap.API.Services.Hubs +namespace Birdmap.BLL.Services.CommunicationServices.Hubs { public class ServicesHub : Hub { diff --git a/Birdmap.API/Services/Mqtt/MqttClientService.cs b/Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientService.cs similarity index 97% rename from Birdmap.API/Services/Mqtt/MqttClientService.cs rename to Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientService.cs index 5acb8f2..6143bde 100644 --- a/Birdmap.API/Services/Mqtt/MqttClientService.cs +++ b/Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientService.cs @@ -1,5 +1,5 @@ -using Birdmap.API.Services.Hubs; -using Birdmap.BLL.Interfaces; +using Birdmap.BLL.Interfaces; +using Birdmap.BLL.Services.CommunicationServices.Hubs; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using MQTTnet; @@ -15,7 +15,7 @@ using System.Threading; using System.Threading.Tasks; using Timer = System.Timers.Timer; -namespace Birdmap.API.Services.Mqtt +namespace Birdmap.BLL.Services.CommunicationServices.Mqtt { public class MqttClientService : IMqttClientService { diff --git a/Birdmap.API/Services/Mqtt/MqttClientServiceProvider.cs b/Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientServiceProvider.cs similarity index 74% rename from Birdmap.API/Services/Mqtt/MqttClientServiceProvider.cs rename to Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientServiceProvider.cs index a1f9aea..f6288ad 100644 --- a/Birdmap.API/Services/Mqtt/MqttClientServiceProvider.cs +++ b/Birdmap.BLL/Services/CommunationServices/Mqtt/MqttClientServiceProvider.cs @@ -1,4 +1,6 @@ -namespace Birdmap.API.Services.Mqtt +using Birdmap.BLL.Interfaces; + +namespace Birdmap.BLL.Services.CommunicationServices.Mqtt { public class MqttClientServiceProvider { diff --git a/Birdmap.BLL/Startup.cs b/Birdmap.BLL/Startup.cs index 2544875..4df6d2a 100644 --- a/Birdmap.BLL/Startup.cs +++ b/Birdmap.BLL/Startup.cs @@ -1,7 +1,11 @@ using Birdmap.BLL.Interfaces; +using Birdmap.BLL.Options; using Birdmap.BLL.Services; +using Birdmap.BLL.Services.CommunicationServices.Mqtt; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; using System.Net.Http; namespace Birdmap.BLL @@ -37,6 +41,57 @@ namespace Birdmap.BLL }); } + services.AddSignalR(); + + services.AddMqttClientServiceWithConfig(opt => + { + var mqtt = configuration.GetSection("Mqtt"); + + var mqttClient = mqtt.GetSection("ClientSettings"); + var clientSettings = new + { + Id = mqttClient.GetValue("Id"), + Username = mqttClient.GetValue("Username"), + Password = mqttClient.GetValue("Password"), + Topic = mqttClient.GetValue("Topic"), + }; + + var mqttBrokerHost = mqtt.GetSection("BrokerHostSettings"); + var brokerHostSettings = new + { + Host = mqttBrokerHost.GetValue("Host"), + Port = mqttBrokerHost.GetValue("Port"), + }; + + opt + .WithTopic(clientSettings.Topic) + .WithCredentials(clientSettings.Username, clientSettings.Password) + .WithClientId(clientSettings.Id) + .WithTcpServer(brokerHostSettings.Host, brokerHostSettings.Port); + }); + + return services; + } + + private static IServiceCollection AddMqttClientServiceWithConfig(this IServiceCollection services, Action configureOptions) + { + services.AddSingleton(serviceProvider => + { + var optionBuilder = new AspCoreMqttClientOptions(serviceProvider); + configureOptions(optionBuilder); + return optionBuilder.Build(); + }); + services.AddSingleton(); + services.AddSingleton(serviceProvider => + { + return serviceProvider.GetService(); + }); + services.AddSingleton(serviceProvider => + { + var mqttClientService = serviceProvider.GetService(); + var mqttClientServiceProvider = new MqttClientServiceProvider(mqttClientService); + return mqttClientServiceProvider; + }); return services; } } diff --git a/docs/thesis/content/birdmap-backend.tex b/docs/thesis/content/birdmap-backend.tex index 48e9e30..da1b288 100644 --- a/docs/thesis/content/birdmap-backend.tex +++ b/docs/thesis/content/birdmap-backend.tex @@ -138,12 +138,12 @@ Egy másik megoldás a SignalR használata, amellyel a klienseket eseményvezér Így a kliensek csak akkor indítanak kéréseket amikor az adat tényleg változott. Ezzel a technológiával oldottam meg például, hogy az eszközök állapotainak változására frissüljön a felület. -Egy másik szolgáltatás a Birdnetes MQTT kommunikációért felelős szolgáltatás, +Egy másik szerveroldalon használt szolgáltatás a Birdnetes MQTT kommunikációért felelős szolgáltatás, mely felregisztrál a \ref{subsect:birdnetes-ai-service}-as alfejezetben bemutatott AI Service által publikált üzenetekre. Ezekben az üzenetekben található a hanganyagok egyedi azonosítója, illetve azok seregélytől való származásának valószínüsége. Ha a szolgáltatás kap egy ilyen üzenetet akkor lekérdezi a \ref{subsect:birdnetes-input-service}-es alfejezetben bemutatott Input Service-től a hanganyag azonosítójához tartozó metaadatokat. -Ezekből felhasználva a kihelyezett eszköz azonosítóját, a hanganyag beérkezésének dátumát és az említett valószínüséget új üzeneteket készítek, melyeket egy pufferben tárolok. +Ezekből felhasználva a kihelyezett eszköz azonosítóját, a hanganyag beérkezésének dátumát és az említett valószínüséget új üzenetek készülnek, melyeket egy pufferben tárolódnak. Ezt a folyamatot a \ref{fig:birdmap-mqtt-service}-es ábra szemlélteti. \begin{figure}[!ht] @@ -163,7 +163,7 @@ Míg a szerver képes is az üzeneteket feldolgozni, ha ezeket rögtön tovább A kontrollerek határozzák meg, hogy a szerveroldalon milyen végpontokat, milyen paraméterekkel lehet meghívni, ahhoz milyen jogosultságok kellenek. A jogosultságok kezelését a JSON Web Token-ekkel oldottam meg. A fejlasználó bejelentkezéskor kap egy ilyen token-t, amelyben tárolom a hozzá tartozó szerepet. A \ref{lst:devices-controller}-as listában látszik, hogy hogyan használom ezeket a szerepeket. -A kontroller végpontjait alapértelmezetten \verb+User+ és \verb+Admin+ jogosultságú felhasználó hívhatja, az online végpontot azonban csak \verb+Admin+ jogosultságú. +A \verb+DevicesController+ végpontjait alapértelmezetten \verb+User+ és \verb+Admin+ jogosultságú felhasználó hívhatja, az "online" végpontot azonban csak \verb+Admin+ jogosultságú. Hasonló képpen oldottam meg ezt a többi kontrollernél is. A \verb+User+ felhasználók csak olyan végpontokat hívhat, mely kizárolag az állapotok olvasásával jár. Az \verb+Admin+ felhasználók hívhatnak bármilyen végpontot. diff --git a/docs/thesis/thesis.pdf b/docs/thesis/thesis.pdf index fc71468..249b6c0 100644 --- a/docs/thesis/thesis.pdf +++ b/docs/thesis/thesis.pdf @@ -5866,15 +5866,11 @@ endobj /Filter /FlateDecode >> stream -xڍWnF+xíIAd }ж![̯Om\$q@HV]jiοz;ya9*(:/w^SaJ WZ -اmO_kѿt(ryzuB?GE*/Vh([z ùR^K E. ]VGɮ­̴j}ƥU߸l)'R!j-&]NUm -:/Kr̐ZZmywұ|g&C(sSwMy%^WmUv#@ --hn1r$,U tu&s(eM/ -S~ykD:?CHBk=UY/ $^ ֆC^ [gVe>Бu#!v5ӻ޴hBP9kwPB A~t#m -pهIpr+Y8cպ9R&8hLӕ)Kr)!Ļ >25553b(&l}*.9k Ml`Z(PǹiykcqH/ut0Dǔ*?K1 \Nۦ6CcIyAcݐ3BJ0@ 6Wf;džfz|^DrX:mԨ\`uNNw}&.`\6)MN(XB:;amp -g*R\PCeoOO,7A+ֲEIܚ\NHf5Y%a{}o}7yՒѝdzc) H/N@cE0#Գ0QN x;?itxH$*)fXjj7&9X:$ȏ3=aE%h,A&Hi%A<5VY ;Ӛ2Q}X=X &tSqn\2#R5W4~4Ry ibs@.fr*y)֬ӕf*xȿ# )PH^#.|* N=c@B: AVaj=bM$ʇ,; .X9̭yȏ(2WT^DG[Iot*ŭZ5A6Tʾ=SL"&~4ƫ[yB,t2WU2 O1#XYj%hb]H NvQd a?(=ڦlpDCohN]!+#qMn, Sy Kܲ`ގ5nb#*:7vm2_*LaUS9-h^ DFGuR;VF!Z<ϥ$qleԼN%y]@I^c@Ǡ -OQ?>CwբqS>N<4ms}8W^ZSc$LpWt[(ޖS*( ӏ p[MYh:@iz΁r]pCPl3Ιg& L{F:-Erŷڈ\l j=F& `_\Ae ;co0+tÈ$M+GAr@@-NkY <ɏxK -4 I_}b Y/WB!oR=cB/BS)o "$ҁ֙P_}D$JaJK*CT8R?}Sފ_LO?k0؆[?zQKBdH8x$Pj3t V$ 6 =77Ui ok$?(Mێmi\YgQ;S*&I*ɂ$ctlxΘNl"V~[85ET7Uǧ+ +5+7uE~Y`*&<{|w:I@lMu@Ȩ} n6=m2H;*P/R~bht+8dS" gxe֭n4TmM6C^;B+1[dH}~ jPgj4gz슾8;}Hp[HsaJ~ъzǒʘM>:F ң847csɭ V GK:GL``.[W,!7%( j'Yi4d2NICxT36?+ 5+>nj7X p:n 9^\JaVKD`@p +9q'\os]Kwᕙ/2}1RDy\뵈c:7^(lэxgGgCuQAC9j^oL: se0]TJs_m9K =5{(R.ۿJjj8S'x|\v!rr7m@q4L\3dP.EJO.υC*+3ief*r8_4^/. RCςt .n ;($yaDEVv2o8B\ӔK˘f#w\u2c~ Vl:prKF Bp~!!pT9 ;RE4bF "*!,Ga8&A(qQտ! endstream endobj 490 0 obj @@ -6026,7 +6022,7 @@ endobj /Type /Annot /Subtype /Link /Border[0 0 0]/H/I/C[1 0 0] -/Rect [169.102 327.298 202.004 338.927] +/Rect [306.747 327.298 339.649 338.927] /A << /S /GoTo /D (subsubsection.2.2.1.3) >> >> endobj @@ -6035,7 +6031,7 @@ endobj /Type /Annot /Subtype /Link /Border[0 0 0]/H/I/C[1 0 0] -/Rect [149.934 277.993 182.835 289.621] +/Rect [270.561 277.993 303.463 289.621] /A << /S /GoTo /D (subsubsection.2.2.1.2) >> >> endobj @@ -6044,7 +6040,7 @@ endobj /Type /Annot /Subtype /Link /Border[0 0 0]/H/I/C[1 0 0] -/Rect [280.246 228.687 296.178 240.316] +/Rect [414.846 228.687 430.778 240.316] /A << /S /GoTo /D (figure.caption.10) >> >> endobj @@ -6072,18 +6068,18 @@ endobj endobj 496 0 obj << -/Length 1869 +/Length 1878 /Filter /FlateDecode >> stream -xڽsFW0yf™:mgi6N< XT1ݻCreIx{53gHcQ ܒ!3"L}S2Gs(U&=҄a-uԚ|RKג@tm]$adlspA뀌N>lR)3\^Ee'bۧYs,΃\3/ Uu3w&H׌m8 G>lesA|}P(ix$Fa,œ'FJ(2<x2_[xY|ኣ4kc:0r^eZ8ÆT/OQSb/`EƵ4Ne<ܤEQzU7 -yZ`98 W*'ZG| -2oGv8ʌvAP(ZgZZY(%\A$zveHwXMYOa0>8\ܤts -VATوy/yA;MD,Smݦ4s2  tB0( -}%q(~pW`A fM}# fV5{<$3M4wA=/0tW 738,r,xDWj:6)Ѫc2]cgLxFPUQh8ǃNI)|'Oo`,xz"*ʩ&D>.Uz24K5 -z׶@uMnF'DZ sV'<\MSӭeyO>)G#[UV0\Pӕm e+~MP1aqB%\=ߢ`fVc9LnXPS1g}7-1[݁z۝-W & %  -d0csb-%@up]3.IQ~qs!l$BO{/l~>Pj(cݢtޣPj M]PRV(iR3zAD(pP4ƺE`G!vU : !"U\wYi^jߺ%X(hڮABSvױ9Aq{`YMhەٟ Z p<|G0k,F*>$pP\6ƺ`GqvU\cs}h{1?}0Aa &c2qޣh& M]O2zZ%?qBJ5?n9XQ]??Ncs8@|G3  kBgXt\;:Äcs⽷I%B7JA̞4 ŏ/fy&agA2c .]PG ec[.{mW :6'(޷1.F)EXT(*ڮꟊABS'oױ9AT3;w,  ->n8XQ\]?N߮cs⽫`cX>V*'J EEc[*{mWO ؜3$LNceyc,?XQYvUY>Hhd:6'(;s ,=s Ec[.{mW ӷ؜xR-Q6ś3!^~&G,C!Al/ 0+ʗ*{=zo ^~aIbv~!m^v7߫alƈ[FMVAz!>qGk5?k% +xڽ]sF+_ovI&i8J&2ΘN{"\E]޳{yvfv~=[[C0D0Gp8'HpzT~07Ky|m ^i۰j|r1`81;)8W@<0q2Y)42S@2`̜s'0澊W7 uۧgE̴X\o3oh8-yppg>tNީ,]|2Ö#v'*r`!dobm[gev-?UY<3`3o0 +J]B֧sU>c=EYy\:)Ƥ0cs]*e&I3wuߦiBPd7z;ShGCTu[tU( *㻎PQm/p  +X +GdTulއ[#r>JsiKnXMm[hmMUC3Hh:6G7Yx@o ;$~wegDeYC`vSRYem[.meUs9Hh*|.f b`P@Lƺe`VL4]?JݮcsL0d%|3LCS떟u[tU *ͻ{kit˨7th" ΆN9\ :[aBcsۤ!27J*{ZNFi/y./#ΏI$P f\_1X\ۊ˦rTt#]h@`wDDEEm[*mEEUS1Hh:6GH7S9cIB}@Duh. M]W °|oTpXTۊbTul^ߙtx&'Ё6m*˛? M]s?{]Q|<n8XMW ҷ!F[Xeh`GMF+?Jb!@GTT_%(+,ߡMZVUo`"p> >> endobj @@ -10063,8 +10059,8 @@ endobj 650 0 obj << /Author(\376\377\000K\000u\000n\000k\000l\000i\000\040\000R\000i\000c\000h\000\341\000r\000d)/Title(\376\377\000V\000i\000z\000u\000a\000l\000i\000z\000\341\000c\000i\000\363\000s\000\040\000m\000e\000g\000o\000l\000d\000\341\000s\000\040\000I\000o\000T\000\040\000a\000d\000a\000t\000\040\000e\000l\000e\000m\000z\001\121\000\040\000r\000e\000n\000d\000s\000z\000e\000r\000h\000e\000z)/Subject(\376\377\000S\000z\000a\000k\000d\000o\000l\000g\000o\000z\000a\000t)/Creator(\376\377\000K\000u\000n\000k\000l\000i\000\040\000R\000i\000c\000h\000\341\000r\000d)/Producer()/Keywords() -/CreationDate (D:20201203163633+01'00') -/ModDate (D:20201203163633+01'00') +/CreationDate (D:20201203182139+01'00') +/ModDate (D:20201203182139+01'00') /Trapped /False /PTEX.Fullbanner (This is MiKTeX-pdfTeX 4.1.0 (1.40.21)) >> @@ -10074,235 +10070,235 @@ xref 0000000369 65535 f 0000000015 00000 n 0000044142 00000 n -0001574454 00000 n +0001574463 00000 n 0000000061 00000 n 0000000122 00000 n 0000045864 00000 n -0001574370 00000 n +0001574379 00000 n 0000000168 00000 n 0000000234 00000 n 0000047842 00000 n -0001574247 00000 n +0001574256 00000 n 0000000279 00000 n 0000000354 00000 n 0000047902 00000 n -0001574173 00000 n +0001574182 00000 n 0000000402 00000 n 0000000485 00000 n 0000047962 00000 n -0001574086 00000 n +0001574095 00000 n 0000000533 00000 n 0000000616 00000 n 0000049299 00000 n -0001574012 00000 n +0001574021 00000 n 0000000664 00000 n 0000000831 00000 n 0000051755 00000 n -0001573887 00000 n +0001573896 00000 n 0000000877 00000 n 0000001023 00000 n 0000051815 00000 n -0001573776 00000 n +0001573785 00000 n 0000001071 00000 n 0000001248 00000 n 0000051875 00000 n -0001573665 00000 n +0001573674 00000 n 0000001301 00000 n 0000001394 00000 n 0000055148 00000 n -0001573591 00000 n +0001573600 00000 n 0000001452 00000 n 0000001580 00000 n 0000055208 00000 n -0001573504 00000 n +0001573513 00000 n 0000001638 00000 n 0000001718 00000 n 0000055268 00000 n -0001573430 00000 n +0001573439 00000 n 0000001776 00000 n 0000001853 00000 n 0000055328 00000 n -0001573343 00000 n +0001573352 00000 n 0000001906 00000 n 0000001953 00000 n 0000055388 00000 n -0001573269 00000 n +0001573278 00000 n 0000002006 00000 n 0000002076 00000 n 0000088515 00000 n -0001573158 00000 n +0001573167 00000 n 0000002124 00000 n 0000002295 00000 n 0000088575 00000 n -0001573060 00000 n +0001573069 00000 n 0000002348 00000 n 0000002461 00000 n 0000088695 00000 n -0001572986 00000 n +0001572995 00000 n 0000002519 00000 n 0000002615 00000 n 0000090572 00000 n -0001572899 00000 n +0001572908 00000 n 0000002673 00000 n 0000002768 00000 n 0000090632 00000 n -0001572812 00000 n +0001572821 00000 n 0000002826 00000 n 0000002906 00000 n 0000090692 00000 n -0001572725 00000 n +0001572734 00000 n 0000002964 00000 n 0000003059 00000 n 0000090752 00000 n -0001572651 00000 n +0001572660 00000 n 0000003117 00000 n 0000003288 00000 n 0000093444 00000 n -0001572525 00000 n +0001572534 00000 n 0000003334 00000 n 0000003486 00000 n 0000093504 00000 n -0001572451 00000 n +0001572460 00000 n 0000003534 00000 n 0000003604 00000 n 0000286496 00000 n -0001572339 00000 n +0001572348 00000 n 0000003652 00000 n 0000003745 00000 n 0000286556 00000 n -0001572263 00000 n +0001572272 00000 n 0000003798 00000 n 0000003861 00000 n 0000286676 00000 n -0001572172 00000 n +0001572181 00000 n 0000003915 00000 n 0000003973 00000 n 0000286736 00000 n -0001572094 00000 n +0001572103 00000 n 0000004027 00000 n 0000004215 00000 n 0000918275 00000 n -0001571963 00000 n +0001571972 00000 n 0000004262 00000 n 0000004407 00000 n 0000918336 00000 n -0001571845 00000 n +0001571854 00000 n 0000004456 00000 n 0000004677 00000 n 0000918396 00000 n -0001571766 00000 n +0001571775 00000 n 0000004731 00000 n 0000004774 00000 n 0000918457 00000 n -0001571673 00000 n +0001571682 00000 n 0000004828 00000 n 0000004886 00000 n 0000918518 00000 n -0001571580 00000 n +0001571589 00000 n 0000004940 00000 n 0000005036 00000 n 0000918575 00000 n -0001571501 00000 n +0001571510 00000 n 0000005090 00000 n 0000005214 00000 n 0000957685 00000 n -0001571369 00000 n +0001571378 00000 n 0000005263 00000 n 0000005400 00000 n 0000957746 00000 n -0001571290 00000 n +0001571299 00000 n 0000005454 00000 n 0000005545 00000 n 0000957807 00000 n -0001571197 00000 n +0001571206 00000 n 0000005599 00000 n 0000005738 00000 n 0000960943 00000 n -0001571104 00000 n +0001571113 00000 n 0000005792 00000 n 0000005896 00000 n 0000961004 00000 n -0001571011 00000 n +0001571020 00000 n 0000005950 00000 n 0000006013 00000 n 0000961065 00000 n -0001570918 00000 n +0001570927 00000 n 0000006067 00000 n 0000006135 00000 n 0000961126 00000 n -0001570839 00000 n +0001570848 00000 n 0000006189 00000 n 0000006237 00000 n 0000961187 00000 n -0001570721 00000 n +0001570730 00000 n 0000006286 00000 n 0000006428 00000 n 0000961248 00000 n -0001570642 00000 n +0001570651 00000 n 0000006482 00000 n 0000006550 00000 n 0000961309 00000 n -0001570549 00000 n +0001570558 00000 n 0000006604 00000 n 0000006690 00000 n 0000963493 00000 n -0001570456 00000 n +0001570465 00000 n 0000006744 00000 n 0000006822 00000 n 0000963554 00000 n -0001570377 00000 n +0001570386 00000 n 0000006876 00000 n 0000006985 00000 n 0000965638 00000 n -0001570245 00000 n +0001570254 00000 n 0000007032 00000 n 0000007128 00000 n 0000965699 00000 n -0001570166 00000 n +0001570175 00000 n 0000007177 00000 n 0000007268 00000 n 0000965760 00000 n -0001570034 00000 n +0001570043 00000 n 0000007317 00000 n 0000007450 00000 n 0000969412 00000 n -0001569955 00000 n +0001569964 00000 n 0000007504 00000 n 0000007580 00000 n 0000970753 00000 n -0001569876 00000 n +0001569885 00000 n 0000007634 00000 n 0000007705 00000 n 0000970813 00000 n -0001569783 00000 n +0001569792 00000 n 0000007754 00000 n 0000007894 00000 n 0000975505 00000 n -0001569665 00000 n +0001569674 00000 n 0000007943 00000 n 0000008078 00000 n 0001032339 00000 n -0001569586 00000 n +0001569595 00000 n 0000008132 00000 n 0000008315 00000 n 0001032400 00000 n -0001569507 00000 n +0001569516 00000 n 0000008369 00000 n 0000008457 00000 n -0001066966 00000 n -0001569414 00000 n +0001066975 00000 n +0001569423 00000 n 0000008511 00000 n 0000008617 00000 n -0001247385 00000 n -0001569296 00000 n +0001247394 00000 n +0001569305 00000 n 0000008667 00000 n 0000008741 00000 n -0001247446 00000 n -0001569217 00000 n +0001247455 00000 n +0001569226 00000 n 0000008790 00000 n 0000008927 00000 n -0001248630 00000 n -0001569138 00000 n +0001248639 00000 n +0001569147 00000 n 0000008976 00000 n 0000009336 00000 n 0000010004 00000 n @@ -10310,13 +10306,13 @@ xref 0000028490 00000 n 0000009386 00000 n 0000028429 00000 n -0001564938 00000 n -0001565455 00000 n -0001565108 00000 n -0001565278 00000 n -0001566315 00000 n -0001565628 00000 n -0001568400 00000 n +0001564947 00000 n +0001565464 00000 n +0001565117 00000 n +0001565287 00000 n +0001566324 00000 n +0001565637 00000 n +0001568409 00000 n 0000028133 00000 n 0000028382 00000 n 0000030158 00000 n @@ -10397,7 +10393,7 @@ xref 0000048022 00000 n 0000047723 00000 n 0000046008 00000 n -0001568517 00000 n +0001568526 00000 n 0000049359 00000 n 0000049008 00000 n 0000048107 00000 n @@ -10406,19 +10402,19 @@ xref 0000051995 00000 n 0000051293 00000 n 0000049444 00000 n -0001565972 00000 n -0001568226 00000 n -0001565801 00000 n +0001565981 00000 n +0001568235 00000 n +0001565810 00000 n 0000051935 00000 n -0001566143 00000 n -0001073430 00000 n +0001566152 00000 n +0001073439 00000 n 0000054837 00000 n 0000054991 00000 n 0000055448 00000 n 0000054690 00000 n 0000052145 00000 n -0001072448 00000 n -0001072943 00000 n +0001072457 00000 n +0001072952 00000 n 0000088356 00000 n 0000057216 00000 n 0000088285 00000 n @@ -10436,7 +10432,7 @@ xref 0000092985 00000 n 0000090897 00000 n 0000093564 00000 n -0001568634 00000 n +0001568643 00000 n 0000285517 00000 n 0000285671 00000 n 0000095623 00000 n @@ -10450,11 +10446,11 @@ xref 0000095444 00000 n 0000093773 00000 n 0000286615 00000 n -0001566658 00000 n +0001566667 00000 n 0000286002 00000 n -0001072633 00000 n -0001072819 00000 n -0001072881 00000 n +0001072642 00000 n +0001072828 00000 n +0001072890 00000 n 0000915808 00000 n 0000287463 00000 n 0000286969 00000 n @@ -10470,10 +10466,10 @@ xref 0000918636 00000 n 0000917503 00000 n 0000915950 00000 n -0001072509 00000 n -0001074482 00000 n -0001073186 00000 n -0001073125 00000 n +0001072518 00000 n +0001074491 00000 n +0001073195 00000 n +0001073134 00000 n 0000960176 00000 n 0000957868 00000 n 0000920532 00000 n @@ -10488,19 +10484,19 @@ xref 0000961370 00000 n 0000960005 00000 n 0000958002 00000 n -0001072757 00000 n -0001073247 00000 n -0001073369 00000 n -0001073004 00000 n +0001072766 00000 n +0001073256 00000 n +0001073378 00000 n +0001073013 00000 n 0000963171 00000 n 0000963329 00000 n 0000963615 00000 n 0000962858 00000 n 0000961455 00000 n -0001568751 00000 n -0001073065 00000 n -0001072386 00000 n -0001072571 00000 n +0001568760 00000 n +0001073074 00000 n +0001072395 00000 n +0001072580 00000 n 0000965821 00000 n 0000965519 00000 n 0000963700 00000 n @@ -10510,7 +10506,7 @@ xref 0000965945 00000 n 0000969473 00000 n 0000969534 00000 n -0001566487 00000 n +0001566496 00000 n 0000969594 00000 n 0000969655 00000 n 0000969716 00000 n @@ -10530,7 +10526,7 @@ xref 0000970570 00000 n 0000970631 00000 n 0000970692 00000 n -0001073308 00000 n +0001073317 00000 n 0000974724 00000 n 0000974880 00000 n 0000975038 00000 n @@ -10553,180 +10549,180 @@ xref 0000976176 00000 n 0000976237 00000 n 0000976298 00000 n -0001072695 00000 n -0001074421 00000 n +0001072704 00000 n +0001074430 00000 n 0001031790 00000 n 0001031954 00000 n 0001032118 00000 n -0001034699 00000 n -0001065897 00000 n +0001034708 00000 n +0001065906 00000 n 0001032461 00000 n 0000978391 00000 n 0000976483 00000 n 0001032278 00000 n -0001066054 00000 n -0001067027 00000 n -0001034545 00000 n +0001066063 00000 n +0001067036 00000 n +0001034554 00000 n 0001032595 00000 n -0001066115 00000 n -0001066176 00000 n -0001066237 00000 n -0001066298 00000 n -0001066359 00000 n -0001066420 00000 n -0001066480 00000 n -0001066540 00000 n -0001066600 00000 n -0001066661 00000 n -0001066722 00000 n -0001066783 00000 n -0001066844 00000 n -0001066905 00000 n -0001061466 00000 n -0001068785 00000 n -0001068955 00000 n -0001069125 00000 n -0001069292 00000 n -0001069486 00000 n -0001069653 00000 n -0001070122 00000 n -0001070298 00000 n -0001070475 00000 n -0001070933 00000 n -0001071102 00000 n -0001071270 00000 n -0001071442 00000 n -0001071620 00000 n -0001071802 00000 n -0001071975 00000 n -0001072157 00000 n -0001074073 00000 n -0001074256 00000 n -0001073490 00000 n -0001068502 00000 n -0001067174 00000 n -0001072325 00000 n -0001069887 00000 n -0001070704 00000 n -0001568868 00000 n -0001074543 00000 n -0001073926 00000 n -0001073588 00000 n -0001075154 00000 n -0001247568 00000 n -0001075035 00000 n -0001074628 00000 n -0001247507 00000 n -0001248815 00000 n -0001248511 00000 n -0001247715 00000 n -0001567012 00000 n -0001568055 00000 n -0001567882 00000 n -0001248691 00000 n -0001567367 00000 n -0001567190 00000 n -0001566832 00000 n -0001567714 00000 n -0001567544 00000 n -0001248753 00000 n -0001564737 00000 n -0001249004 00000 n -0001249267 00000 n -0001564461 00000 n -0001249292 00000 n -0001564557 00000 n -0001249428 00000 n -0001564661 00000 n -0001249691 00000 n -0001249901 00000 n -0001250317 00000 n -0001250342 00000 n -0001563851 00000 n -0001250701 00000 n -0001250896 00000 n -0001251283 00000 n -0001252479 00000 n -0001564873 00000 n -0001252504 00000 n -0001252529 00000 n -0001252650 00000 n -0001253030 00000 n -0001253978 00000 n -0001254234 00000 n -0001255555 00000 n -0001256838 00000 n -0001257994 00000 n -0001287777 00000 n -0001288215 00000 n -0001320287 00000 n -0001320821 00000 n -0001335429 00000 n -0001335659 00000 n -0001355829 00000 n -0001356079 00000 n -0001359190 00000 n -0001359461 00000 n -0001364059 00000 n -0001364318 00000 n -0001367093 00000 n -0001367332 00000 n -0001403987 00000 n -0001404635 00000 n -0001425427 00000 n -0001425692 00000 n -0001440485 00000 n -0001440719 00000 n -0001462276 00000 n -0001462516 00000 n -0001489860 00000 n -0001490228 00000 n -0001505478 00000 n -0001505763 00000 n -0001508664 00000 n -0001508918 00000 n -0001534451 00000 n -0001534725 00000 n -0001563367 00000 n -0001568969 00000 n -0001569063 00000 n -0001574525 00000 n -0001574723 00000 n -0001574905 00000 n -0001575131 00000 n -0001575368 00000 n -0001575583 00000 n -0001575800 00000 n -0001576044 00000 n -0001576279 00000 n -0001576521 00000 n -0001576760 00000 n -0001576994 00000 n -0001577231 00000 n -0001577465 00000 n -0001577705 00000 n -0001577939 00000 n -0001578149 00000 n -0001578348 00000 n -0001578550 00000 n -0001578787 00000 n -0001579029 00000 n -0001579271 00000 n -0001579513 00000 n -0001579780 00000 n -0001579963 00000 n -0001580084 00000 n -0001580211 00000 n -0001580332 00000 n -0001580464 00000 n -0001580573 00000 n -0001580611 00000 n -0001580806 00000 n +0001066124 00000 n +0001066185 00000 n +0001066246 00000 n +0001066307 00000 n +0001066368 00000 n +0001066429 00000 n +0001066489 00000 n +0001066549 00000 n +0001066609 00000 n +0001066670 00000 n +0001066731 00000 n +0001066792 00000 n +0001066853 00000 n +0001066914 00000 n +0001061475 00000 n +0001068794 00000 n +0001068964 00000 n +0001069134 00000 n +0001069301 00000 n +0001069495 00000 n +0001069662 00000 n +0001070131 00000 n +0001070307 00000 n +0001070484 00000 n +0001070942 00000 n +0001071111 00000 n +0001071279 00000 n +0001071451 00000 n +0001071629 00000 n +0001071811 00000 n +0001071984 00000 n +0001072166 00000 n +0001074082 00000 n +0001074265 00000 n +0001073499 00000 n +0001068511 00000 n +0001067183 00000 n +0001072334 00000 n +0001069896 00000 n +0001070713 00000 n +0001568877 00000 n +0001074552 00000 n +0001073935 00000 n +0001073597 00000 n +0001075163 00000 n +0001247577 00000 n +0001075044 00000 n +0001074637 00000 n +0001247516 00000 n +0001248824 00000 n +0001248520 00000 n +0001247724 00000 n +0001567021 00000 n +0001568064 00000 n +0001567891 00000 n +0001248700 00000 n +0001567376 00000 n +0001567199 00000 n +0001566841 00000 n +0001567723 00000 n +0001567553 00000 n +0001248762 00000 n +0001564746 00000 n +0001249013 00000 n +0001249276 00000 n +0001564470 00000 n +0001249301 00000 n +0001564566 00000 n +0001249437 00000 n +0001564670 00000 n +0001249700 00000 n +0001249910 00000 n +0001250326 00000 n +0001250351 00000 n +0001563860 00000 n +0001250710 00000 n +0001250905 00000 n +0001251292 00000 n +0001252488 00000 n +0001564882 00000 n +0001252513 00000 n +0001252538 00000 n +0001252659 00000 n +0001253039 00000 n +0001253987 00000 n +0001254243 00000 n +0001255564 00000 n +0001256847 00000 n +0001258003 00000 n +0001287786 00000 n +0001288224 00000 n +0001320296 00000 n +0001320830 00000 n +0001335438 00000 n +0001335668 00000 n +0001355838 00000 n +0001356088 00000 n +0001359199 00000 n +0001359470 00000 n +0001364068 00000 n +0001364327 00000 n +0001367102 00000 n +0001367341 00000 n +0001403996 00000 n +0001404644 00000 n +0001425436 00000 n +0001425701 00000 n +0001440494 00000 n +0001440728 00000 n +0001462285 00000 n +0001462525 00000 n +0001489869 00000 n +0001490237 00000 n +0001505487 00000 n +0001505772 00000 n +0001508673 00000 n +0001508927 00000 n +0001534460 00000 n +0001534734 00000 n +0001563376 00000 n +0001568978 00000 n +0001569072 00000 n +0001574534 00000 n +0001574732 00000 n +0001574914 00000 n +0001575140 00000 n +0001575377 00000 n +0001575592 00000 n +0001575809 00000 n +0001576053 00000 n +0001576288 00000 n +0001576530 00000 n +0001576769 00000 n +0001577003 00000 n +0001577240 00000 n +0001577474 00000 n +0001577714 00000 n +0001577948 00000 n +0001578158 00000 n +0001578357 00000 n +0001578559 00000 n +0001578796 00000 n +0001579038 00000 n +0001579280 00000 n +0001579522 00000 n +0001579789 00000 n +0001579972 00000 n +0001580093 00000 n +0001580220 00000 n +0001580341 00000 n +0001580473 00000 n +0001580582 00000 n +0001580620 00000 n +0001580815 00000 n trailer << /Size 651 /Root 649 0 R /Info 650 0 R -/ID [ ] >> +/ID [ ] >> startxref -1581558 +1581567 %%EOF