From bf90d0ee855a3fab8da2e4004f8e4b61fa43218e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 14:22:18 -0400 Subject: [PATCH 01/10] Bump Pomelo.EntityFrameworkCore.MySql from 6.0.1 to 6.0.2 (#369) Bumps [Pomelo.EntityFrameworkCore.MySql](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/releases) - [Commits](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/compare/6.0.1...6.0.2) --- updated-dependencies: - dependency-name: Pomelo.EntityFrameworkCore.MySql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ProjectLighthouse/ProjectLighthouse.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index 39d794fd..70269b12 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -20,7 +20,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 3c8f1957405a6c419a9e28b2a7cf64f463bf3926 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 25 Jul 2022 16:53:43 -0500 Subject: [PATCH 02/10] Added login redirection, level icon background and fixed bugs (#371) --- .../ClientConfigurationController.cs | 2 +- .../Controllers/ResourcesController.cs | 1 - .../Pages/LoginForm.cshtml | 8 +++++++- .../Pages/LoginForm.cshtml.cs | 8 ++++++-- .../Pages/Partials/CommentsPartial.cshtml | 9 ++++++++- .../Pages/Partials/SlotCardPartial.cshtml | 6 ++++-- .../StaticFiles/assets/slotCardBackground.png | Bin 0 -> 46624 bytes .../StaticFiles/assets/slotCardOverlay.png | Bin 12877 -> 26067 bytes 8 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 ProjectLighthouse/StaticFiles/assets/slotCardBackground.png diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs index 7e9dd31d..ad1652c4 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs @@ -29,7 +29,7 @@ public class ClientConfigurationController : ControllerBase HostString hostname = this.Request.Host; return this.Ok ( - "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels false\nAllowModeratedPoppetItems false\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 240.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 60.0\nTIMEOUT_DIVE_IN_TOTAL 300.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\nAllowOnlineCreate true" + + "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels false\nAllowModeratedPoppetItems false\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 240.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 60.0\nTIMEOUT_DIVE_IN_TOTAL 300.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\nAllowOnlineCreate true\n" + $"TelemetryServer {hostname}\n" + $"CDNHostName {hostname}\n" + $"ShowLevelBoos {ServerConfiguration.Instance.UserGeneratedContentLimits.BooingEnabled.ToString().ToLower()}\n" diff --git a/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs b/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs index 61158233..3edafd84 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs @@ -1,5 +1,4 @@ using LBPUnion.ProjectLighthouse.Files; -using LBPUnion.ProjectLighthouse.Helpers; using Microsoft.AspNetCore.Mvc; using IOFile = System.IO.File; diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml index f518939f..37aeb5c4 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml @@ -11,11 +11,16 @@ @@ -32,6 +37,7 @@
@Html.AntiForgeryToken() +
diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs index 656a0bf7..9b1b5b99 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs @@ -22,7 +22,7 @@ public class LoginForm : BaseLayout public string? Error { get; private set; } [UsedImplicitly] - public async Task OnPost(string username, string password) + public async Task OnPost(string username, string password, string redirect) { if (string.IsNullOrWhiteSpace(username)) { @@ -105,7 +105,11 @@ public class LoginForm : BaseLayout if (user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired"); if (ServerConfiguration.Instance.Mail.MailEnabled && !user.EmailAddressVerified) return this.Redirect("~/login/sendVerificationEmail"); - return this.RedirectToPage(nameof(LandingPage)); + if (string.IsNullOrWhiteSpace(redirect)) + { + return this.RedirectToPage(nameof(LandingPage)); + } + return this.Redirect(redirect); } [UsedImplicitly] diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml index 7a0430cf..c1b9b962 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml @@ -48,7 +48,14 @@ int rating = comment.ThumbsUp - comment.ThumbsDown;
-
+ @{ + string style = ""; + if (Model.User?.UserId == comment.PosterUserId) + { + style = "visibility: hidden"; + } + } +
diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml index 8a1766fb..d43ddcd3 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml @@ -37,7 +37,9 @@ }
- + +
@if (!mini) @@ -80,7 +82,7 @@ @if (Model.GameVersion == GameVersion.LittleBigPlanet1) { - @Model.RatingLBP1 + @(Math.Round(Model.RatingLBP1 * 10) / 10) }

diff --git a/ProjectLighthouse/StaticFiles/assets/slotCardBackground.png b/ProjectLighthouse/StaticFiles/assets/slotCardBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0174cbb323582f5d156f1ab5ce50b15277ceed GIT binary patch literal 46624 zcmeAS@N?(olHy`uVBq!ia0y~yU}6Aa4mJh`hA$OYelajGa29w(7BevL9Ry*<9TT(P zGB8-a%M6JqiSYHYO3u&KOH9d6O4X~#Enolv8~cia#N_PM5{0DH^vpb4rT4q{D=B2A z*eZpa`WpBaIHzW0dQ=sq23ProBv)l8Tc#-4+i}@cSXJZ}s@C{IK&M!(;Fx4~DO*S;PP%yXDGc>idFf!3mFfuSS z(>JixH#E^TFtjqTv@$SMfC42uE(HYzo1&C7s~{IQsC7jtX|_rkB_#z``ugSN<$C4D zdih1^`i7R4mih)p`bI{&MJZ{z#g%y_i50qe#mW#vVCJ}_7AF^F7L;V>=P7{9O-#x! zEwNQn0$BvLRRL;IMQ#DyqP${g*d^!Z>Q^Kd=o{)8=ws8Ak_^{VP+F7&c3MiZerir? zZfaghvA&_6Ay$0_8Tlpo#TofHtb|MBw74R-z}FXUH&*xN=3=$FxWu)r1i#MWkjjEo z{h-w1{L-T2RM)c9yb@(>zAwp4LqraW8$dER-JV*Ji9;Jm2BHm|6d*BVQ;}O>XKNJYG-6%WTb0g zu4`l(VrXJzY+_|#rfXnoWnh402t*~C8NT@`nQ4_6W|)D}w2>jQ8AvM8%}6atOi3(B zB+3+IwMgcqBwMBB7v(0F*k$G>rl;x`Kk#BxVs-3ZoJ~m+_ zUEq{v<(XGpl9-pA>gi%vkz1gbnVDjhm}qF6oSbN>YhYq%rkiSDlBAnxk!Gr!YG#>e zY?xwcoR(w+4n$vHWbGJ6yW}UAf^v(eiyfq3Ny$&nOtC^Z%OJ(V#3a$oRM#NcG*#Eo zFf~OtF)`6dHznC9DJ?NM$iIwn|I}m2Gy(pzM*FVxx~Dif|T056CKr zf=tZlBrXUrwBxp;JR>y^U-p6+1y+UIkmCHblJdl&RLAtxyb@w^KEza1ZRp0^=!5El zoJ<--L~&vnWzj%fu7dayDHhSah=^)%03(-jXeAWHD6lHrhMBR8(!ajZe-< z%u7#AvD1eoV3+{97VI$x5k<{eu-uB76Kz11la+r_W@=tZA~^RL+UR45A#8@Ij{xPy zoKmoQOH)f@Qwx1V0|QVs0oIBvjjlBkzgA>vbgc-Tp?R4lc1BQ#q6s7E0@a|9;yt(^ zF*()F%+%D_)J7j&7+ps|W<_dFgiB^_YF=?>ex9AFp%GLQx(rsGkvMfC$v|~NA`7Wu z2F`^L(I6K$J1!f2aC;KewggMT%Pv|mpbn#z@ep%IErEmsk>qG_5gAYrWuw6b2?rv{ z(cmI7pdiXdg9{Q4M3SSyMPxuhl#K=#Bpiq&M}v#VfPyF+4K7GH5J`>(7m)!4Q8pS} zkZ>T991Sia0}7&SG`Jw)KqNUDTto&GMA>L?LBfGZax}Pz3@C`Q(cprF1Ciuta1j|$ z5M`sm1qlZt$NOCl|hzux*veDpz zgaeV}XmAl3P!MIK!37BiBFWLYGM7!;B{f_xbms#F;m8k!jxe*R}*Xn4uMP-?)y@G60U!D4s+aD6kM94my#ALu6N8Li(5d<_A$f~ik$hj2{fQVcr(+3e|C`$PHs4Tn_^^fNT9RzCl^UZX21M&#%c zkspD9BFUPmA^)TW10%Y2sJ95XsI1z4^=c1wW%BXza7qE$C(HWkA zOsigf?ibv)@2xVd5VPI(2`Lh4i zrkq)+H+9Z`j-2;=bI^zknMXn&Dl_^y>!l#O1o2^_aq8=Ie+*+eObcG-~Ws_nod*ZI%W_Pzgq{gQ}IlR`vG;*Kvi@7XI#nHZQE4g^g6 zdpmR1yyclz`mFzT&VSy#$?W~gz&%c zL;1Vb&SvoUe1F^Lz_#=Szixc`FZwk3_9f?^5num%YCg5`y&O4f+3h-J#UsbQ|NVdc z`(Nv&iV-b|6^boCIOC2o9AIF$;5G00dlk>3dCOi_&U>C7Ic=_}tD(C0t2oix$vdQ5 z=EwLPaF|%1&AFiJP7srV?V;@{Og63?ma6@D^|oo>%!Gi;|5pi4m?d~YUN}|r;Q38C zb5d`fwdh+dbV!M#>HnkO|K=L-=r7XP^`Z8^hKMSAl?6c~=#)sVVfl`dUkJfAM-S|4*pCQ9-K^W5tmK$MwE9~}E#bv5> z?9>%e4%oexW1o&Y|4I|iMMlD>u7^#r|EwkaKy%q4?XE{|lT^}ORIa}+Rcz^KR`{Xs zC=k<a&ssC5*GTWYY2&_DKN?=K5lw^~u0L%Yy5!daDHGWxjEs}q{ zp8Ws=LqSa7KkeCPpUqS8eCK=l%RQab?=<6IM_(-O`EqsEz84C=rcS(Ybgqn#qwkZQ zzh^vuqw+`0_`p=gD?AL^f3gnWH(MI8jcr2E>Giw*eLWF>Qf0->CMR~7Oi*XNtfuAZ#2Q~&g)>d!Xz zi>qYstNpr~>~hx4?$RcPP~Z8Ym9bZ59{26P$`b$E=E}y$_ci{s9d*2&5wFQC(c3VO zH-NWslHrP48_nLDSG8GU4*mb8KKFY1`s!w;=;8%mctVyX%oeYhdMvzC4L z)LcI6#qXXM*I)fUa{guU+~2W_YbJAMbnFv*`}+Ljd-=k@+kRxvU#=fy&a~>lZYf6J z3)%C-h3n7p+&D7dl%vN|W6F2m=i)0C`Oh+3k@x&najU>;1D^dlXAg)cO6+Uc9|S5v z98w~`ol4uhGk^2VJM)*l{2O#?rt^~bh7OnRC`17AR=)KU-+) z_r>?(KZQg0mvaVW-@E+Ze&zM=u~Mun?W9)J*DYMb7`C5%Pe^t%FbCdC1Verm|vuqmYA6BtvEoHjPvn7SCNLPD;w`R8j$G)CLFRoSC>@$_> zop&_evVoCdfy(Jk)3q=9PkOR!N>RwQPp+EZs|gz% z+?2J=sA008!~vc!W-PL^IYXNhv_*H!YMi4f_~hyFXHFfyBCgxDj0IQ@p8oNg-GJdi zl+f{yw+m(LCoFr(969ao1*soeh0hn&)-znpm%XTb`pw_IruSN(te5`W+1#+JqQT7g zz@7WEL<>azFXVB2Tzgkw$2TsES&ef}a|P^;Uoau)nWMlRzQZ3rf2{cPv%=<>RT2X; zgWvo`8gUV8!}#;eX3x%?Wv8*UXGTW6Xl=Z8iTm9<=~i>vqq2Uxyj8CLE%rz6`&ZF_ z3$qxD!j&&LzR*7{aAO&_)MS=3x#xJUR56<{FPO%0WsQSS+r#w57hhZ}vHE-F^PcMk zQyB~x9xU;g^yI5WpZu*HGyWG_YgIpe=hdvUy%hfXM{ndmzU=Z&9^;?Cg=&IR_N{&~ zd*1y|F+g3y{&7&nQ%%qTswM)P2 z{y3&_U+vLum*2IsnWB9hudiviY7^m77vHu(*ZROzu3fVjgF6?5i3OB#iv*oI^m&h~ zi0k~`Pxvs}Q6m`#@=h~mebz;J!=PvR6FQS9~9!X)0 zar@SWD1+OW^>MBeh-a$ZPdvr1!);ca=7Eh59)sA-*`E4pP0XNYlvmY~Qi#s@tI zw%HiS_1n+&TRxvl@!pZEtOpnxnpMt!77t&2)p_>WX9rDu<#k%)d_QmJ+JEov`LiF& zZ3@?$o_eqO!%g^tc~ZXc+ie;3@sI0e&oq=6aPO9A(tGqiiz8|?GhZ#!vfEYr9RlUN zb4;01mpSP2KS`Z`ApP>oFTwY}#~;1Q2C_-v^rq?F59=*XZ~8s;*FL$ouQlsy*PNGl z8|_lB{iAQudAFa_bZcrC|8sPy_PBVzQ20UWEXL*i_m}1*+%P+l%AS*UAVO`!6i^b# zyP-3~II?k-|AX#}8DCD8Sp5}AZed_!h>^^kwQpD4dhLh%r+a?>9kpeB*>7%L<^|n* z)4Se%?X8n_sh=MCXD;h~*M{~rFZrhm7MQZ^{=)NSmZE_qQ}d7Qd-bblF-A{Yupx!@ zN+;t=Nd{Bp1$}~brc%9jGkw(NwTg_S^S` zcYfHueddb&WxM-dY+v$iZrbNuCo7kdcUGIqZ!X%OZfww^nDJMpZz;p;ovbODVkL&m z(}Wxkrm%kTX~<%@(sQ7!>%jNFw-;Z0@%UxQFU}r@21bT(%|9_m&gZ@tj#@lFyLbMV z+p>O_ihDmDwR`nFmUVx7;|`%Rkq>cg3-YHeI3J{RT$uN35JTX0xkjg%3J;8^);gvNW7w^x0P=5DFxklhW#uRo7 z!F#(EB`)wpT<5W#!X9JH#H%d8a_~CHRVPzEc}lcd^a?~A%xpN|F)dYpZP;peuZR1? zITmv54gDdh95DM~dCwouy=RyHl@xq0`!wF|@4odDF+XZYDbrQW_EWj<;=dZkX?~H@v}JPYSmnP!z)9rR=Rc=7 zI28BToPQs$H~o8#+3a@r#TW1UEx+8~tWd!kZrs4bP_Rg&>-qH4PZ!TV`)s0#Z@!h= zpWb73we#k${%q~?`L={gt)kOg>pYcbv+%NIy*ZZ?9 z_}7kG`!t{K?|$+9=9cm+7yqXAGrs$^b?aaISTFY6ROV$d7k})C^=eDcZT zlPRB)W4#q(55@LT;t zKC5K^`TvXiBlti5FEM3l>kn+5t1CI<7yGUmjK?H4s5QP8Rj7`4xXPVi#N@=G$m6!4 zDo=0emyQ$ulb&>%_~z%C&HisP*RNjQ_2TCpT!$DMvfbuA*VmhV+WoObosaBGW0ya- zZ`OJD?pORHd-;#G`)})xe+fG_+6vpg>z#qaY!^EN7M!LI$M zxFV!jTbl(nyp$EDq&Xf;VQHE2DQ9n-|74Y&mU8|7%gkoiwtPKg!0=$!h8Vs2jdAPc zSAY8&{(nZt{_YReZ5sQ_GWg9;ujj66f40wWQGJegIiK&B*!|mTXEg3xw&3aOEM4&( zGa9D}IX>R@&G0rSlXK;Q0H4MLAI5Z+RcVg?v!!mNv2>i!?s|0ZX;I}om6K;rrhMZ5 z!hV3EL0GNt@%C%4zb4N<`z%nYOXOm{$xp$}XY<`3=6iqM?e?#^+m7Y`k4?GtvKulG-X`EP;G^Ua6+zn=SdENK2Tsr|Z- zwlDpe?Q~w`*W5*a8^3>Ye&c^aWQPRP^m~nF#t$ZmDmWJ_+|}hTsAbx^i9zsZ+ogs) zmR0A&|IW>mW`CKd=@8=9(BTp(X5l^Q$-k2+pFZEr`KBD>n#gcq;zX5`*{iR<`e@N7 zue@mEq(|3V>u-O}7pOb9=dJdi-(BDM!@ekfYftBj`6a4ze&x(Yxk$##ERK(VhZ%8P znk2YEk}

(yVzxUH4}=1fm-EYLX3^nFR@uldU^zhn;-+1n7V!NXv|B-VX&{k7L$ zA4g8RyZ+kG)hqV<{wQTW(D~o4rM@HMzm}_fQhm*`gmB{x*VR4b>^&l#xs5DOy{59-yg2R!(b6$Hv8=C)mL9_wCIx; zcWPPM!5(t|$?>y4i%aXu()T~i_5HEi?Au$ZxA9Y7IDgO)dExI+RaR6$^o@jlLa?SWn0zi zkbcJZa8nmzb;G^tSe^rp`*OMahEXBFXC_Oc+qactQW~RTkyiax|k}KZQH-L zI-Qbhc=cIi+NJ|#r3INxESjl}TG|4~KMF@qo7;c<@qRmN>)*zE4ka)gP@Sl9Qu_4M zPaiG%{x4Ybb#-9<;%oW0UZqFA*qr;}vem!eT>H0f%s+m(O5w)?uT9Km#urqz6S5?x zoaJ+xEg0~fW5sON)ysd}Vsy?@b1=Hukd<3t>bangom*A9U|#CY`gv#5yqv?zGSLed5Hfa`|lHc5=!;U*EHm@ zOv#8VF<|;7$9Pqwptorir@>TKu3fjK6}CKIakF9hsYwU)(>LGb|IpRM$iO@~^`>|C z(MO#Yeg7Le)V$jFYrYE4{#$pvWdFv4=NDegFL>DgqB+@+Sue8DOnHI*bYrGzY>vt6 z8BBjOUwLkRifQTx?RK7-n;1jB>#WXy{#jyGn{G7Ira4@Yhv7zJcX#*x&c{DG7ipaHRt$gst9f4F{_Bc& z-*4LYU7P|S44^@rlG2UpHEynMV% zim~06>GuD&8UGl(BOUBbFPKU@lx$ab@X&M(6fvK6`sx1}&wu{6nt%R2|KSg=dx{bm z8kkpKeFciY$yXWeQapZ2U;CA}xbC)@{o398x1KwH<*VW!hO`5h{#^h1c$XRXHVMX+ zU$|bhIn?rHUS^s%i#Om5!*pH+O;ycm<}B65O^zRKr+PlnUw-*z`~y*DW(FOJpnqFg z?UyY5Gn21=`HK0{A2%=gyFLcw;E>Hs)doy=jxb1`V#=y_)RkVKE4gYWV`=S%qUiVh z3v^D)Md^r5);S#@)WFCf6FF_~o(P?JG3&4UO9lPweKCK_EBf498i!0pntug`=WmB z_rCJ}%H4eL@9%@bUhZ`eH{P&X&|oSn&&`HeKeDx3V>dG{k<(kUMo8_fM!>9P_jeUP zKc{kf)BaiKpV#+=bMPG4>g@IN&e5YsgI|CB<*77lqUzK2J>Ns$cYm@=y#4Ap$G+1! z_0LP}TjU%5rm$K`HD24)V5j>aiDOGngO$>XJ}#lVxdL})@dkS?h*7pV_xaEJ^XJds zKYFssfZ=+ZiEn(Qj+p;T<+?j|^=qH4U;bzJwO{PM-<^LjT4*R=*s0^7>)YgGc0f6I zYQavQjurP5B3>Nw|H{eY=<@k$*4O;5MH1(qe-1xnP{X;NN1|aes68<4^wZ#JRrSiB z(x3fleaR6Y++KgWBi{GU?Mr_J>KOXYbCl?ETljEID0;_mUEze=|6jF*GWL-oM>EW3 z?=_X{pMP{U6Waq7a4ozx%s-Uy?1zWh)2#Qlk@2!z*ne;I>eJfmUr&*5k#Bfx#>6~@wdZETE5qAI8kBxzH7i65DJ+VK zlyQlvR5<^6_UWfaT3wH>r>CdacZD)tRd>6eqpPx?w=Us z_W9=@RT*6#=7JIx&ri3KHvTx5wz<+L|J!OFhL2zW&3ci|<}mmB@@cd72VVg>Cn}9u z$}OQi=fF0{3A0ogm2xvDEY)97cE4)xzp_A)i#2xjx?PLJKX^4TT5z56`=393?!TPP z@yDy|r+?bs`+Z~a-`YiW9QF*$lUZbDv-rMl@wH{lYF-d06tJ0V$xNob`VQvYTW;pa zO%Gz5ApkPt+Uu{@-A5n2)H$7}^+-OeNxo#|_uWhW+&=dEo8(te5{ps3U@pDjJ#WCP ze^>u5%1w7TzK>zAjf0De=OmjT5m$|+HIOouf#-nZCQ#EhYVE$YYrgWH&bYtw=K8hw z?i)V6U%gH~(4OIVBFnd#yc==^r+A&ZA0o8kUhZq|2j`S7@G?HF{C6N}xj_du zxo#*eUa-q;#*}>wX+0BiF78j#a+&x1yYBSU4qlzcENq7k_a~IUyR-B2>!(FO?=I5F zo8ly|wX#0%-u)Cdn`Xg+m*2K8`?GbTbca2IdIrlcoAC8#wYgot9+$o@^(^=Ctfl^@ znKS+4Gkd;mwOjetbjzt_(~_I+?=60QZvDsTcE%k=dU|^Q%67)og?m*V>)7vK!+F5? z?Kky(H`j;pUbwGS-+1-!wH5OX+0Tjdb=WhsXEXi!r)w;)&C|bH)x#)e@{Me9Q{%b2 z3;L_=VXNN@U33wxU-vn__g60a?~1s! zU*d&peP6VS-Bo_Y&Jg2ec0izpCgVQsy;nGm0`~AKRZt_1llv4V4LCN5N+nL z|9%*gg56}zFE8e6^M+gxILi^Dmar#k?Y`>Y-`@W3xL;v^f#t@;qOI@C!&YCt?9|~= zo%rf(UE|uz@$z4l57+EZJaT^JX;9o>zs8-`ug^@ay{S z{jaXH`}_p?`6k1&+J&+0CklL%ycv&}vvYa-hlJ`~W!CvSOL}eCYWqF4zrS4$I`#a6 zbUWjX*+14_f4zL_&pOk$@3Xf{KU)7M_;P&jmwl<{?nk^|&M5ttfnj+j%P$GG>ysK3 zJuWg!TyAN&uzvC^&JR1Y*H-Dqt-tPnnB@RN%(5T9Z*gzh_QpN;*JZ1}w$0jVr!UQ4 zd*Z$F)BY9m3@OZ3Y0Nv0`z(^gcG~Zf zdr$k_>=_zP->w6Jb!)N;`R)M>k2nCg*Qa4op-E5 zfyd$giU04t#3f_feiYa1=smixKCAr$Geg^svNxAxDmc{?qSjycPmUDeaR~qT|8~)~ z5|>jPUh`+|-}m#B>mSaqbqohMXEHoGJ!=l9L7cVqtcHetnuYygtFOu@TJd_%KfKScA z*80Ki?xT;^f4JSsm;vr?N3ETA&HwA={tvPdf3gMl?Yr5}mi3L9q2aU<F?$%hK&-#n?&>8MkJar*d^IvWQ>%Ix17p)>E? z=RbBvb6zdCJQaInzIP+HGxVIaXIqTk{<*0)egC>1cKLU2V~0HhLyW800|%dm<>^dc67)`Qntl4|r`w*B z_OLM*@SfcCX6ezSk8@Q#?h;>BY9glv)CwUy_mh3 znJYEr*5&gY0d_kI_c^R&Jy~jF{@_+B1GohLTJ?ACCPkO`pZLGH*{_oKe<^u};fOp# zgO9`M&)?>7X2h&sc~e0mV=rS}Wz&Q5b&nS<$WCRLcKYdgP>aIFWZAPF@o(>BzHMdx z$j;E9Y|QAT@VxkXRciEuioJ36J7e_f`Irlujuig6mbJC&l)>x#s=^n3n>JqCUNuoF zZi7HQ1B1_j0<{L~m=%T78q!#9t^53{uVMMR%M}l{8Zcze+P5i2Z~m!GZ|WYU|7Bi! z?Y%VLA^{f_oAb&3>n_FhK(v2QbMR;7cz5fJtk#m)$Ju8auJ$$PoPHOtH{E|}<}WUu z1DpY+f3zRhZHuh8eHG4n&sg>)_eXYy11vG?I28^D9x5p}KfO&eK$}ydoJHet`jVr+pBCP7hzfpCwYTomqeqYO6BzhrT+RAAJ@mN!R`b6*bG}~={^ulG z{>%*Q#0;h_CHw25x9D(fTFbZ1jP+RIpCegYe|bwZFst}p4i8^_b+Yd4e_xi_pEvoQ zAMxdK#YM+Ij0_K6`7o5{K3n(jP8`Fk`Qiz=Tsr2gb~Bf~Ty4O>ek^HYg_7@O_Lb3> z=YQO@62EPS9aNN zHTiqfiy=1sFDU2>EY%$L?|gTgx^!hwC35iY&ZtT;F^+OF3}Gd5!lvb}x#hKL8> zUk1-fHZ^blGPq}ha<2Yki+{{(->vWeS6KQ#&bQvA;J7^~3U=pZu=BGtJy(JpFRUjkD!Y(G7^@{t3#n%G{vn1pjG9l2LF17+r{68Da$mOoZ&C^S z@?BQJvMY)&-@l-r!N9;^9dA5$7E`X(g0$|Hbr}riD@9$Y3w)g!h%v`8A>mLIHgG^WXhVRT1Zf7ir;`$Kn#W+tuDQ5lkes#}JQald+ zr`FY%KI~8T{ChoSR@U7U2A|q@*)uTADG_VfJ1u$^o>#x5){@JEpknMo&um54QmhlJe-RLA*KVS0e=4Jn4!~X{L?*eBBzT+%2 z?0o)LoL-fXt=TY(w`rGI?r)|`Cbb1SW9qos4m4Wy-G7w!Z{@z%_m{r@f5{CTGRqt# zvP>r2TF!K3Gn3SA#zz))+-wV4zgGQ?nD_kom3u#)TQ2$6%Uj~t-IP>{W&E7cqJ9!PwMxYQ82Td`2?TDZKBe?q2{mk3(_b1weGL6hSPJ?=h z)r@}8Of!QVW^;aM6*!o-xw2$u%s(c!hJ`tQs(U(=g3|t-yz^CGM(m%((tj(Dp8zL5 zzS}G%61*nUm{!y}2ILwwWU}y_I=;y0aIFDvBYQHaY*-xicz)FT^z?r_CF^q^`YZ2s zX72sN$iQHs*ZjapYK1i8>81s<#4`6X_UbU)&E=>OVRKOQoMgUgX8kJjf060`cIq&c zM*K+j`n&iYKLf+^iL4uJ@^o1(bU0SYTE3sa`eF552G2=*7?}e$MXlX8_4!X;y1n;A7{;4@|CF~Moi)SXX({f zUnv}8T7QRO&GpywbIoSEe-WO#V(-U(ZB_~Ke-{{5f=d>e<(xM*iX4z+_P_0%oWr5= zR^|5Dw9hB1_WqOPIZ*YtV@i=*`D?XTiS~NE^{@1gT>Ei-*9Ueceg=l?=M*HwStiz+ zJG`|Ec2>B`&;6VLae`(tyUP=G&!VTvjp1nwU5hI0`X0M?YJ@EMzbf$1>x)0qXZ^fi zc^#b4{0_5xvCuw{YVHv2oZ$QT)bT?Wee$|pkA7ySgQLWAl8wvPWA?Qzhqip|@5uaP z%=u^C?thF740HD7U+8U2ZCT~qIN>DIir#miv;$g^vaT0gge=Ldn*8ebKWRTt z@6A{4sXITOfBFpAnF&lYZqF@amYBx;a&Oi$9R~-OxLM20!&hIOYQhq?i_zoqm#JBA z`e%6yec57f{!P8Z@@T*1!-a2a85kHEc4f4uv79jIye7eI@`WkqIH=Nn`UG5gTAbcg zy>g$z!fU#oe985*UayKY4;Ev%XwSf)z08*Z9*T z%lL)=ZuYJ>F~4f|E#2#SNgpT}W9*AJI6E&0UEdMUw9bgOm@r>Z|8@QD zluw7trG7gShbm9dKyF6>Z^yJHrmI0(ckf6{+;Rn zHe9q<{L0V3u;9OG+?xrkAGR=ron_+C;|`D$Danj%@HS+ycKiQ||LzRl4Hl+LKn}2& z-8`+$A^FOA9d@f1ItP}5hv+A${(8UZ)Ap=i$}ayI7#R3exE>-6pJlLn(@TvKd#seUIB$g|J=CmbO0oR~fAAMI^(k?cxsar+$8HVW-EuA#VMBL)ZT)FMg>X zKlfj85x9J4m>2bM3Twd(jt9#g+yIB@^9&vbndAIkn#yWt7tZTHW9k;;^@X2-f#HiO z=k7Gdj!5Y>DTlHdH%&3>di>+yVgpb?Hc#bbbLx}z?*I3x{kW#;&;g3gIT2z9rtk_Z z(K)$#6N3|nz2_wM$tsn9AMk=q2d#=-_HF$R>C5Kp^M4xW{dERe@t|Q7LzR=mS*8hc ze^)yeRNfBmaa=3DK%?uYT@@pnDT8a^o((s1> z=rsJ=muQ{f`&i=b<;(wjH5<>SeRc>G(U*ZF`n1S0`I-EG1(%rq3*76c^kqu@{JEe6 zbs#mBG3p$LLhPT;^L49l7UtQ0s9k+E>q1c)IZgxi8X+_6h9uJt=QyDhtR9pI9X4hF4~`yI$Zg zGXsOgBOQk6oCbX?LA6?bXP1Oqm;O=lWyHDSfy2kEhR?TJ`@kd@amg47%Xy zz&z8IX#P6_^+x?Ht87cQ{%cV2%*!*Iy?xysh9iYF!Csb1+k^kJ7~ebI_b;-JlW8XC zPN;T~pObG_CFH4Wn8=x7ts3BEDYb}a!(_$@LI1XR{WoU+^Fq2;DwU!8#`bl8SwR`y zGC4t-^GfUdGiMuqJ&Red#q6P3UzN(H(D(TFsk8ORp4mIka`x{p$@*8^`7cq7fq{WX z_tm;chRJD}i~Lh8R0DROHD$ghe*9x?cqT($(M!&y+w{NOe)apv^}o^Xponj9HsfiV z=&(-yz>0~p;>=FH**%T1O1eSkbe!kqFKU|Ve^+|fcijB7+*0b>iumryub!R(mEg7M zj5+do73%_gnl=hfcr}~x>OTg1-^;Tjr|m6z$(FGB=AG%!e@cG6|7UygXL$w&hJpmO zg~i4SpJ!Z7J79DEyxDBu_eKZw*dElK-nc*K?0%u@gVBnMPm~MRO0Y06FifAyT2Pr6 zZJc21r*?Uf!ezsQ-{V(-iukQ2zVFpPzp1~yKW_Ga15oaM5YX#*J6ravuVZqrxdx}P5)nh>km7qp*q>{#V*MSyWX?R_)ziSD4_Xh=T6w8Q55!x;}|#TlhCTx0RjTt55kvwM4`8>W5PpZit6Q0>5z z89o>7TjUrR4k$`D_nmDp&CStd-mtoHWxC{o$&4p9z4;32n#hLzpY-?*MBPdW=Hqi2 ze%;nv-T40OrZ->rf`cGGP^8#s`Ty3s6NZwP{-5Gcc`jvthKYfpVRgs1@*fe2r&(^8 zOf_b74Lq}Z8l#mYgX-V+(wF}KdKGW9eg=jIDZP&8=Q2dEP5H)bQWAD>xm+qk zI&*-?QEk4L^+i7ai|s|0fC6F88p91!7*A~Eakvu1rqOliXAVO;^M;!_?=;K*EB^(R zoQwATKF$}#rg5HaM|uG$8}7Zb_V@e?Ah`#-q?#L-F<$X$IBn8UEZ?x1(c|)#t-s^_ zBVVlKIsDRHPg972f#Jc6-o}+Y2Ut$kPG{oHW|*Y%Gjdw$_W-tvyRDRx^!1h2+iEGLi`#|Hr>*vR$E=8<+mqzWQ&# z!N9=K=kTESylF;!G_&pYob!*X7|YBUD(CH=`}`-b+TZi*)ZT3R%MY@c;n)Jbe{H{6 z7H>Y1Srp24;`1N3dC&8|n=yD!nj`LNcrBRwjF`jSnKSmyjCE52W&C7w=5x2wZ*qAo z$z@hq8xk*a)WUPp=X-1ptN(AF{a=Rf|G^)i{Qh8F?XI#Yes-lg&46tAhN}!Ik!5kq z{)c|QxZ>~Y*siv!`sE+(FBd0(3M`p|miv*Ld7>G1e$T$ikY<#>`nVH^{^?D1k_|TJ z@1NY{lgl7-ME;lY5wOV&@)z@ECS1$qPj6L6br#k3cDgHG=T*?s;*!H0%teruNh&%D_%_Z6tLJfJDXe3&cY@4j0v z8?NN+%a^$jp0#r~Ki|4M;>9Ch<~9F8#r(R><_S%S(eez2Rc~IVHZ0P3w#=yEB*U3b z`#0`0{Qem)(T+Ii{ufm9cDnyKcYdp^Ov-C!gBOL5H!KLcd>7RAE3RGH@Nn|v+`sGp z`7Zni%5KL%BSy6hZ3|H1CdW0_k8(Z>$E#`@TP2}D}iFi}K z6|c+ZJx_NH{IlsQ!;(y^$w7Tn{2vu=t;^+aIJuK22ox6#ewNY~mh&H2aJWj+!9&wM zbJn>iUWZ8S4>P{l@8&)bpeC{9AOB`h_P*h=w}0BsZ;S>rf863@cv~rVo&ACVL*=~l zo%jE*@0T`t#oLz8@`{&%fuZD^;Gr`6@c-ADzpXXY*t+*B!i&(K|0eG|G3|WZUz01U|?ZjcrdH0^7?Zw zZ+V94ybsQO_}H~*Mrx$lR>_8$+itXb|1V$nKbcX0fq}u`#6btQkLFVtw{737Gh33k zA?km++5eUQR|o&S|Lw2i7f?mR6QKUqUs{`20wTK!#%cm0;#8eN|Ao(ErJ5D5Oi zeU5QXkIOHV%-%W&u8 zfkTs61(sejH)i;9_Dn)3o5C~UNoDq5JO2pY1tpHTrhyWEoGIJCYJJb&x_2U|zazh7 zO7h!go5Sj6U3T05%X2q?{FIm0aPizVqlSYV6{|ES1oeHk`QN^lQ6rdXo?@#*Tbjf3 zRFKyhBrd66DZL@^vv?`vdM)MW1c@6<3c{cqULPJmzL6B%43_$&M^Jg z^MA>S-hp34s~|3Nd{J$8f62x*VXv1mtnz2-vC&LjVbSvH0E1Df@GG?jnOUI1nqkB4 z$^;{p-dct$bM7fWU9dk(+#zBrgVe@N_qwP}42PDz4LWsU z@g~L#7fe^wE1CVeAG`|We~ZY4@(+F<(`neZZT`$x+_svj4u9^|Cv9T5w#22e}xR{ll5#FI=L+P@ht z{@19!lqc%Qea%=6g~X*Dv`4%3+DUOy$w9Su9Tji98@*u$8EE}k>_;Y&H2|J2+DDZ+wFhHE08-+pBLM~_VP@w|JwhP zUzXjj&+`VC*9ji>50;z^i(PNTki)#-smUV0m-Q(ihc`T2T=%xpY;Bq}<4!q-4ogsf zqG_4qd&Z0<+y=Kn;XkKM^1|saSCi##W`AGwv^Iqk6k^OB@2s=7efW?JDm&K68-QF3 z+C9j?z_6~Hal*9Ysi%LR<)0vA9}4O?JIHL^+MQNk%-8U(bLlTTaH_V5I~;It+OOnL zHiumtwxEs=L&2U%rlUL_TUi#&YPglFxAZ|4TY?nGwueV!s^|HxR-Mc_p^BfOdiPuI zi zuB*S^z9j4Z_{BClP*ljrm*Po#Wr|*(9_~R}B8g_dy>5PMSf?g=^^-T;# zx0w}MPQ1*MZ!moIegf-@7*I*T&|v%bzTz+QsSGJgzdLo@QC<||&F!(uoNd;g9huuU09#JQECDwv3%e&B0$iVl#sVDAE}I8Z+zO zI_dV`XXZT7|DX1q5q3&xQxBOR@#@ij=Vk>^cv}5ny8a^ma#rT$Z(7U~yq0P#un+v5 zl5&zsVy;j4bC4}_s;1Z<`0Ts4x>u)R)yJoAuLwIWS<=h6YBIx>H@~Kd!GeXuVg)FkkoW`pgpN52d~9y%_3UQk50Hb6(MD_;$45DabU2 zH+PLUs5$iilV+^B%AnEmL%F}hgJWajyaT1Y+tL^_jvIkhwLZW6KlkGP)K&Svw_T}O z#p94vz**(iaF(ece$L^UN7vm4Rf+{!P4B+Unbv8YX}}ext8e;$9b>{Q7N5HzWigk1-lXFK5t2|Wq)g%)@_`2>{ry+ zc^AJdy7DKNEg{%8A&V`;#v^lK;8cf3hFNr!kmiu{qpj4Y?HmlL@B}nmuU0rqUC*t?_Urzt}Z|%15m-TlUt{5>ai(^PLxnQPt1ME!( zhRtcSj{P}d@ag!Jx7*)`zx?mU=8*mCGCzO8Esh&o)fsw0&4+c-CHDg#M_vA(68A57 z#rK&;46i?RwrX-G+^~D{r`P!ks5Crive~dNzw_T&RfhZDukU(ctQ7xy$-0a7Eugl* z4bAKWX^awg&C*zwOu6*E_8P;QDLf8|1p=1@ewM#uZqNh;=f?L-rY^f!9rk8r+$H^v z6&hRjWip(yV<`O{@A$`&`Hr|n1;{9d0$-(?)0ca{)+hgpzxu&zx9$1p&1?=FAJykQ zUwh?6e5qKQ?BTUe`@44>mSA9D*rDch|7-Hj$^Sbv*>g5C%zM7JMWFtY0fWnJHwV+& zfQ-cY#|jJ9)iMZxQvZUyNxJUjA?^XG0s~huV5iA9;qW?wmJV9j>eemC+0g zZ1x9cFed+v=e}h5cHOK0r_GoXtT|3hiF*C( zu}9>Nfht=~uDy?oZ@>EA%T}9o>Hoavy3Gm^lDrK9kAClaufMbQ|CJnr2QK%lBpD1r z$<|7marLvJ;Hp`H6ZXB=Zxy(2F2%5@N}fUUILE8k|4(e>XW(uGh4tbayR#N={O5lq z;^OYPObX6_@24<`h4}w}UCk)<==~*-Q49@watHVRJO5(ys)w#C-OPAep<^NZmJ^PNu*Tw~A?Y_&}Dd&p+iL-x; zs~dGQyN;PN2Z9XVoDk2j#OByF775v~%l}ygJr$3r@f`jp)bPC0{zL75zN^9iui8Cy zl4iehSzt*j&zF3jRiJ>E_`@Lnb@I-C>whtP{WEV?-S2(%$3O3p-y+4JwCEDUj7z^` zKF8m;V=!T2Vqn-YEpWfDbne&swUYZ6p01j?;7Uo65rdX!?L%<^#q5Rmch-aYObk2nB$;mhbygKm@NRY!|8n-neObjL{&RR4F5Y!>*z|^B z!7mY}+w2RL8(aVd+JjkL`z9N1$YBg&&dW4l+WKklO2!LW45y|z9-OPQq?dWtoE}r{ z2C$c|`@WDh-JrXA-TME!9hL{D?_2plzQl|nP$ZT^F)3>rV~#ri*SE|LpwjR_sUe4+ zRL1K6x79vvo2A>*u~_3(9z)IjdNq!w+ehYeFYxCOm^|&lzCsNfP~+kY$FZJs9{!^#+9`VwZ|F1if|lb1kFe8y0ASXe)&iHRr&u{zbuLVwZEG& zqeMI_xz4$l+35kOOC;XB;q{OBuX~Pdxu?LEU?No;JC8fSK(;-H`2pYK2B9=iKJM(Q zoBy~z_i=r1&YmfoKG@`gjtsbWlc8eX_sa?#`>x5dZ5N%e(*KH#-~7S@ia~lHJ*w{C zW9`Fy|G!@5V6=j_;n$!4*XKR|TLKPr*T7_%07FKXKN1U81|Iz3+^_;P5LmkTLXgk| z*{xeI{5u)6Il9o4AznCenagjNwr2JdA4?ACDGM5a+6;Y$+8YkPurB{4U+oYdTBg65 zDRSk_X2}Nm?9_%^K?-bFPhQzqcvoTpsHA#uqqVNR|7!4mm$u9QzXVxNXXI#l@LHp* z&SnOqf)dx^586i48GAIjF3n;-8NdZeS1V_;dKW8Pf0KSGB-88v^r*Kjn;AP6y;vRe zVP_`8y9o+;+6zo97i_!20h)_zNIu2&#pA#C>2LepHp^$;{qGVoCCYXUqeQP;{O^7B z?NO%~x;|Lvv$}wj>_)D?eDb$bf6H%O`oH%6{>MiDu7g7{NPs0bm0|kf#-6i{8ld)* zMd;>)nO~Q0`?7yu)%+P>>IGQhE9ZT`^nk6QL!)bvzW2fNyr~SeS_eYd3T|?BfLbCA zi_dVC`24@V>FKmD^}gw%MZeVk{!g90e*0vwTPo*mSC|57^*X#L|9Qjl^8csb_OIVn zqdS+!L4d`+RD;>$xDmrLkb)TQ%@+!U@s|bfX3n)%Q7QX*=M|S#uk!3s$ z0!dd*|K2~%(31G0MxrhL(mU_Q9m&l*^R760{UL?6erb?z*SB?TB54s4vw+B|J$-#^p2>o;Ew3oU**`^*0#6RFz5 zOg06c!{Ubw{xqFr66vXa_-`XzOB!p{xqro(_3v8lu06JDnF7yY{X+&d4=?dJOl4iM zk71J!gMjhBbcs5XzZ1X>)dvYJ`(77Er~U8Dob{Zi(T+2~L$iC|#sBNr9-RJ^!|<1T zQi?wFi+9UQ)fhS>2ee+23c)I7e0z?EhN#|FN_F>umm?qA~ZnQf=0<|DO$b@>v}}1l@ms`u5Xy zBf0+kLSN1^Sr6RQ9QuEK^GQ_hv zUf3mkV4KtoZGN7MJRFBX9SNgF|JR+ZpC$Za_pk4#KUVyCs(1gkAE>=jCE~jM)Mduq z>)5tk{ac>L1{yh9cS&c9>3_qj7h8UXd(CtYEb->}_-m?UgAsRuH^;_>@2nX+qN_b@ zXE7#%GGs1snL};u~MDkHiyU8TkenBk1ug&^S%qJ z^sBE4Y(2A9no((=P2A}Pv(x@B*4PC)z+-O_vx7^>RK^uIc_IXY&tI4&ofTL+{cM9k z1p@;^`xMR>yMCVEU|3$gL(X*b>q^Oz_h%H?5^Ut|b2U9Mi=4%{`V9l`4#^8gR~`g4 zcO|rbnJ@j$dvSl={L;_yw^!DG@%?=Nt>UHs&5{iY9C4t7H#SLb$l?f@+r3rtf`QPD zABsxgs-k02{pF4O_0HDc_Nlu1Lw)I)!v=qBIGU#OA7hvj*>Jv9fb;8p9*-1zHHk=& zXO4^g-Ml;B!uZ0rpZ**ZdyYRo-~P+4-GsrO^Y8~_t!$Aju?CQLjD<3+5ju)z9dr3# z^>WXJ#r40^KHpD&{PBl6dpbi$huh+dx_)oI+BHl|Zd#hDt*{AXMW5y`^PYb<`~IfB z{{Qr#{r0v$aqOlHmtTI_Tx6WEFqLuDUWR3tnbs;do&e=Ni$^c+mwxeIHEX5Ie^&vP zc)#VB&+}blsF?TtR))#1J4HSP3wO&L_E=zI$^`MS$D;a2i|XBe@7QZu_2vK0=auVa z*Dxw5N%bF}Uo~&LLYnb{PrP2L$_IK`COxcuU6sIL!@$sRy64}_@2Zy>BC6-Vy7_+X zgVpMPHUD#+|19?S7b>mcH4-@E9A@oA5Q$FsMu<$Bh~lUDZw?8F^kUfkdG zZMsa@-&bu7vVXf5z1XbLRafo zkNkrBxtAxLVtDo9e){hp^S&i9s7*d;ylkR_Q4jO0n+z$Sd^jiK%X;^}cdo=Ff5|tR zX;W+hHZ`hLKj^n+W9v4R#P^X5GeE%_`!(tMi}uy{V z$?&w@E&^mX!;1`_Ig9Gw{=N3%{z%`iphK=_gM>}lt%)sA;IC~jj0rGRx8_lwQBwy3`ST>ZN_GI?*`hyU*T zr+<`z#qq-?RqlX*(?$xLd{_dG8#5V*aWF6(aOJLg^C$oHpXYpkHGMAD3$W(_qYv0z(Ln@aNeT&=;!<8{?^O1J?vIbX6WcxcKN0HG@S;O?|T`7GMQXJ z>JEgu{r}~;O|SU>C6T}W%P;%uy?$Pp$(C?jhe7(QbsA&JbR7mC1_p*0{g37^noD~A z-OM?#(Eb1PEQVD&4gxIklcV(=lGPpN>o9nM5`a~g{c^$BMfJ7c_HX?r&vNkkbjiQ* zyBJ?gX1#EC%A+k`<}zG*aAk+dxeJ+~DL8kDzq9RJ{zo)_SbecR`Qdp*_y5!L7&U72gCI*HFTaNB`ek{MeZr{YIYWvs^q`tl%KKbO6 z$*2F_jM>G=arlF(8ux@u&52HiY(a+1y95<bWwnVfuZA{wfVou zuz#;+HaOMCU*GmA-p$2TqHX)K%P)_IfBd{t2vo^vr-~^oPSag7QB85_#HQO~JI=Q` zfRg$Su}Al}eq5i%GNrKWD#wecW#9LuF24BUu>wcjPBXTKjtsNewIZ$;mxpp4nZg?I zPm-TY>G(zm=PFQxKO_6kWt*0-2j(wwy>iimks_m+H8of5`<)FK?AIM*T3uhVJ?_#A)&|Y4);@x}m zZg1RwGUe0b?0iUCeSf;S=}OyyI}_|QuYBqH#+_}U^rnzAv}_w;Gz`nq}!`_0V;41prH_HzC9A&dUsn$#l4+c>wJxujC@APWP-fsY;g zHNW0ZeKvoW`M<)`?>>F3_>(B&dj2qj#+kIu{f7+x^qgi2sBKxaRxv=d&TQ^wV_nch zS;tw&{ww?KL?2xFu{>d7acI4gObl23>hYsluf;?20M z&0%>E!!Je#h6fdk>ra2(qx*He-TH;PxxMv1U*ZJA9KCawsJ(a1<*P4-mVTaVm?e#M(zpl4AUU5ZVxWi29e+aL(`M=noH|{%v zQtlLo$OHva6N^J$yqWnZ1Y zZ2ctuTZz?Q1&${D6?+vo1Wq@c%5);pae`(ni!cKN!*SJrPp194zPQ%xYre&s_S`?* zO%J+Xmi#)X_}_>B7K2ORmqRH=KOMXxWhM8VWzfiv^=7=bnJH%}s5(3TO4@4qzpo7! zr~O(ln-HEAqPWyYeey}raUBfI8<;=;{PX+q#~;k8<_EUzOVVNmts0hO>|tYKIB?SS zf39-H$7PWvgFr8!#_FwhZuU?7C+x{m!U1lA<;@<#rbIt zw#Ez~U$*Q1yAt&MddqwrtA+Z1HZJ|Q-T43Fi!UrC8W?Aue=h$;hgIa(O@_76Ot*hQ z%G-jY``5n9zxB=itaIJ3CI9R#rp^C&QG!A7$n2*f4QoXv7^ky(teVcWV@m%<`Gk&T zkTP#d_Og^sJC^OTU(MY0Vzv9Z)tmoqyYe4&CPyN}H-|{B70Z}%mNp!#WSq6yxR0%9 z`&RMP=Mb$Det&kG{Jr_=pU;u|Cm0NN|J!+`-b$|D-eTI7|AC-kp3R##+e`N!{~tAt zY11e1iGhFDFnry^U^_KgmN(}%|Ay0*;FPdI{9}54blBfjeGc+JwPz&P73W^B5A8a4 z>dOE9^XAU|dvoL8J$sXDCZ0(%u63NSOKr!t?wQdNF4HbLWZmRnuxtvrs(E#E{*Pt$ znI{Fd^!-^WwTNx{E5ZFCdVgk~O_P^-eEyFHsF`)%fBEI_of*DS%5G1ut$3cHaGl>E zC0GGeW%6kM)Ag<2wrl_86Z02o?%eje-gd6v{r*KSDkU0DpJn>vpvxNY_eR3yjD+cR z4Sv3j;1vAzk-yL7`C?ypU;A5nG2Aq5_OJP8)9fv-&EH#oMt{!Fntyd7uJb1p{b;(i zerWAFEn=&vs{IRw@zVqe!rxSK;+f|=@r@!NqMwi{p^UvSQe?I?z z1+Rku%X**Xm%rPd-)%61p;o?Ot^9$ql7idI9M<_Ws4*}wu!+Yo_x%Q|4p# zir=ea|Ff$9oA*2xqz!b2725-@nLcXgdyYT;e)XcmUd@1?tX5x{1@^0~_?&WJLOllq zL&4l5_rDqD%Kq>Aw7Tu!)_3!>Zw0PUZ76#3{_n|@PiHp%m)jFuVK{gG{QC7Kj9K;# zR;vf`*;74=4mw1{d4i& ztDE<%>0b z?YQ+MC4=jVIy2W>*3byP$r-UCEuffuWZ&~c`~35DCtEY$-52Ze)X~~vr1g9YWm_IA`J>P#}-N&lq|KFcGckbVpU4QwSU;j8{Yj0m4?j^bQ`s;jQ z!IiQ9Q@_`(y&6}!=hct(aRqXMqEDwZWNJAiSurp$e3Xy*b2U!)9M6i0`=oxRyG+r_ zuDidNPxk)_hC8BP%%6Y$xqI=&7tUKHC%l^{IpL)>(~8Qf1$)-`G@O=~HezIGa2Blp zyKC$76Y;Ya)dd~Bf4JXGkk7r?U&j%%D(>~^!u|JI9Y35Z{aagg{pV2`*Nfbn zZ@!6dQrO}8t+~1A*$0l-rxHMoq$Bm~ADz$rxmx#^q3j1?mV;|==6ur+6xmxaw|@D( z()z&u#_s>y zQmOCFj2jGQ`plc@xBP$74Z#E(mlex7A53FCxzLwk6C*>z>5gC3UHeUReo8w1k-nan zd+mQbs0R(+KtA(qn*AKV<@-gQ?p!ot+_m`5Rh9y2X3xsLi!2E~0t^Kw9-U9&&bn@? z#=UBGqvDbHvp4dT>lKg8eOdDB_RXAc&VR}h8KllU|7<_sZ~1>Gm+Y)*%->R(mgxPs zCEug+hKqqgrtwGiA^n-kmwcoDw2A$Xx;4M!+U1vD;{E=X*h@6XT3TEGzWlP}SG3Zt z4E-hh)D|ez)hxXza$qJyu-Sn}J9_I^7%(w3D6SK(J@%*Lef_OC?wworS$EZMeVT7P z*RQ@>R{ZY)hA$8P{P|<=v;1*y5m>7Kz&l#PielC zV$uIGH{Wgog;h;m-9Pyc(rt_{l9>MeO)>hpc8bx$-A^0VsU6s+b0UlBo2eqG>9WJ; zV>;h^!)3o$rk?Cy{A2l3Q|p;NYWr>N?f-xO!F!mYHm3FbN_`^I=;QivLb)x znud!kU*2*z2r@7nvM<>@U+-U5z~b1)-!%WdEV26gwpZHxpKRUfG^RfsQO1n>CkJ(X zt@^vADvcrVF%RSI<50Y}r||Ky{L@7T^kz2Xx-HP) ziVj|2(tB!03Uk{JW_AXLKi^gV#axzG{&!UGQT^j%z4zm;|NUnG+Ms-;eivtfrOS#^ zpMnfw24#i=FS-A#n*ZLZ^JC(zts4W*#~aRh#{RLL(Sk#GK|e>>cIill!x7!y!3ocw z9k5&6bb^hcVa5H2zb>x4>0iCZ@Uj1`8z$m^jjvz7HOKylJllgyJ_kyy{-&o|DHzX@ zov^is{hAcZ$;9x6g&W&UiW_nm7!u+G?YG}NFS6uD+8^KEx;a16+wT6mT51N0GMLwm_4BX2HMlJCBD~(_R&h(xp|1RQVvBPA31TZ8#Tk+josZRGmVDSG*mW5Zh+}_{yXS;XZg}41Y2bKo)ar|rR zNHUtE6d}_3>(N@%%?8oTxyen-np?IVTjcG@aFc;S;Op&0|74Hs|0=btdw-d4$oi?b zvo#Et{}K$end?{2{IQ*JhtRq6=l|DcGD)SgXQ(#b;%sg!2@fniY!q=`z~Cz@PpHs~ zUoi{^9=iYKyWSFYD!z7(rl(i%tNPjR_gCi{$NrbP?&bUA>)n6*4^EPoXjpB=_&?EX z_Fp%9*9jd#Z&}y$b8f0<33=aR`i)g$8k^_gqy-11SQ1$nEP7Y$&t5EF-n0JUtRr!| zPuM&QmpJxk)$6oX^Iw_IK3muPb)NwP`$15td@gPC{fc?zvke)y`Y>EQ9{%N$gR-*2 zGa-lNwT$2hte?JO{;%u5OBd!Z`L$KKW_#mgy?^tb-<@|hZU4c8cA(R5YV7`l&K{J$ z|9$_GG|L6kPAz)2j^P~d>$@BE{xbGX0%bgfSN9EHZD0DwH$V6KrekyLuO9z%C2jxO zAE2Tu$Lu$6-n zq!-L$2zF`M%g8Xt?aKQbEIHl3ZoB>I$WBRH^#6|0D907<@8c)Nw;!#;8-|c z`huBO#9#X+OYH@P(;U8TT_w(Vz0mP*G9yE{_8+z4eBrvUmYd!&UDM@;9DmBv8PtEperG$t!B9|f=)Ur+e4CRW!ruSW zUlGZc(eo$JmN_bWTG**2FEdPj71+)HuLnA0iAzH6|NVcr>$~S4va8#$?|=MZgFo|^ zOqsImWu@k^t@|B9HAIyYoD1Yv+g_`Pwhiz7@wGo(e)AvsxkqH(7#a?X*G>L$yL5h* z`cK2pe<$%Qu3KXAKU9(->zl{Y$tR!O-Mo48{kFs(LUF7o7-a7An{&kNEPQ;d*r_9B zZ(MzQ$FWa&8TzMB#ArQbjQ2gix_*k+6a5Z-&MQIxW6T_W-|5X^i0qRvOXaww=Vrjj zAk*{1nsa~h75^j4|1912YR-?U{d)g)Zn~>K&u{sDYkT{8@zu4741Ke*N;f>O+z&d- zM$ENvo#~^OY6n*8J7{xyq;4%xeK4tdwG`W>YaH5(Vxv{pxPR8*W@uQkUnlvMX8rXl zd-G4zE9aFP&h)u=c!oUB0nfs+vTw`hJ^x#?HOh8s>dn7w56!=_dMurIA=ss^y3av% z)3kXFs~k6!n=!b72080|pN4KUzxt`)u8l-~XadKmD{a%c)_?vjag2tL?So1^=Gns5o`}iWigDv4z(ZB3%DRX&#ut zd!g4Mdh&vob`p#X-<1E<9=#vJcR{SfwD0}Ww8itiPwiiOFFyO5w)NlpuFLIt4tN^N z_0RuW`+w@uq>Y`Ae{d?gtVm_-sbzc;CM3}HWAZic1^wJ+n;4JG(X%K4yZW^7zrH|w z@xR5&b-9}Vw^jWQ`*Zy9$KRiS{)sjD9cwp(X-Aj*uJ`}zAAkH&uhFG+ep61Al;L&G zMy*BR%ek)f=em4aw*80?*NgWt$F?x^Ff@F4ANyl%@!ws)COa>l|83i}Ps_hm)%&@e zep&Ksx3qcQpUv-ouYVZY$a7%p!YsZowf{j!fljWRcmKG{|Eze1>+B1@G2ht4nA5yq z66=NUd{;Ixu5y@tis=LgLqY1H^RD0CB(oiSz6eyfy#BPl^p9}xd-X+kzW>z+wHzZ} zb2AsLoq7Iwy&TKI+ozv?^7M{(2=rqMQDrp!6zV#FkFaU9@j zc&+toH^=^OHrGq+HJkj+9;$!tu@8T*eQd~P;Ot7Y7(<`{I1^YzV!T1mzfR)&`S z+dpi6Sr_(o_w`>pXVvE(o6n>9zi8+A>d!y_>{Z~1JEqOT#t^cwBzzs+KXw)4`B+tNoq6n+?a7G-yf(#46;ZGD92)QXj7$ zx&L`j_s5Dq|3IC$4_u9m3~cAlpWiReaxi{f*lP95Cbb)WSzmM6r^PJt^sScg0=w&% zpZ(vv&6Dx(+9Zyi)W+2YOa{ykL|pzGweHWq;{VlfzfNs5MeGi`dq%`s&~oEC4>D#;Hqn;35uFG=I^ zNo~|NWIDmcz_CB@M{bjUNdBkd-d{_raxAYt|Fha-|AU}^Pdo1aPL$Z!5q|oi;=h;k z|8d&4GCzCtC@ETKLH?zGjz6!dFIrIZnp1JrZ=0uovqCq7cWqyOXZu-}jC}2j_wI!q zWA{yNj$XLEhlT6#-zQb|ue&AF7-VL?C>N}IyHoE_eD(Ahe)Y$r_Dg-e9`x^3PQB!WhyRWV&9&Z~E}MDc|dRxb>f#vH$u4_ZvQycfF{7`Q;bTNC8ir zr2#{NJE+=7l-L(CjpbiMhgy}VgDFdBn}hFHO{R5R`vQ8L0_Uoon8F(2oM6awXwtj; zy9FC08NzjcRSVQbr|bf|tEC6;iS(J46UwwvQqyXTh<2qf_t zGpuv^(k@izd&lyjdXe|{&C!2n@YP3O+3)*%I{VK(_Os8{HG~TqF(mk(N!u*nlKA6T z(asv1zQ^_fQY_rwW(R`RSf#9)SKQNCF^%=hUB=MP23__EL3siCURiDqq7TFOW+wm{p(D^;@mHupPpK<%ujQNIl{cm;1U-kd+c+tOCe@krS{=d#K`>oKm==sO2 zCPs#8wXQ|a7i%m6ofc9mbG$!2vTVK58&^xk1>e|yJk?5!zb$g(~@1wu)I^9p>`Nd&h>iIpmc-{Vjj$iww`j5-cnLGEd zWL&5L!-GknzQSgWu6r?S!}>wT-U=vP*u)sRIbo~U4kOk$%@1-{#W`|~8Lz%;(9&M; zl|6?wcz48B$;PN7`36jTH#6<-ve?8d@Hf`p|Gvq8zC-uJp68$WGFkEN`tJRkPHn%i z=pSgL*q)IM0#kHcHGxUA2 zo5KsWhF5q8!!5QOV2NRmn;0t416Zi22#Bl8zcT??TxdamwNNBmsvuzSU@=E<-2N*!I1}2 zm~4(3Y;aq!ZtC6M0|AkZ3(qoaVp*>KV|UlSHXv4K| z-|x>I1!@du`q<4l|NQ>()%G8Ul0<3N$UVc*zn++32M^4qV_WAK{1AYGHYW0k#w zHv0)P1dW-4S~*!Qj12BhBCh%_fi9q9OKTVnF^%P{d$g1Tq?l`C zHVFNV?P*x)bK#c3i&>&OvWyvm3o4TAr@Z*y`|YcB)UzMuf_2ez_rH1mhZ0ZVk#?)!|JwE=)#y5~@>ZYXOfm@ume?prg(&gbCM&c6&z`J#Un7uCKslm46i^?#F$^xqY6 z&-HJ$-2eU;RKP#XG5fvu{qOaUxT~j1+Z@0x4-6x-Xav0P&T{rCnLxXU#jhwx;Tz}@yn14xo!}T)`(@*^0H2YuQ){`GRSnCTeUY~zp z>CcmOQStf@)enc+@3OueAN?+P*>C$fXVdJDgbJ}S%(2*f^G$nd?cOZ#T~^@XN&%qn{NJ>^U&d~=;=f?r|a2& zE(QJot!L_WTil<%`KJ54=X)DhOE)kw_(6~8NrdUJ1|Tf%Lf6_Sm!I5(uSudp=B zcq{s1BB#V1fs(UAC89r*jagz@_8%@@`ucOZ=pVg__FJ!iyRG#9(3V5fe>~e4_7F7n zwCUXcLIIZb53<-27##F3nbfB4jkAxDYOLNR!FZNIqMW1T3|GM;eHq?{;If1SXM>Ds z4+72}Xn0&PchPUVruPz0Z{M4~?7Oww?>8RuSNT7@RQeO&@3y#Keey~5M2USZtHn1o zsySTnl4#R!P4ocWof5TH?p}^r|C7qP#W@^jR>o+!lz-=_I3?HU^=CV8%c;*xvUsjM zZsYy0a#vRM%69Ho?}b15Hf{T!-FCpt>_+nD1v$o|wci9|wn|DQoQ`|`qE6$We8iW| zS+oBvNq!QqG4a3I(e*PL?-W$s5BpJje}AmopZP7IOI4y6BpEiW?`g)dAyDDL>0EDIljtd%Tl_X z#Fulk;a=MT*Cp*Ij7n z&EojsXoktJ6sx&)QY;5g@A$OH`m8T5Gas5HnsHZg zLC4Z=$&B6S)&99TCkWqebmK2KW3E2M@kZ&_+{-_g{gw^>f2nM~>zC;CpS)}i^Y353 z{AU+qz-GouiMIK@Zi~+^yZmx_#BJ^bh64wcme%BLjj|Ov{?QqFQPZb}s~j1N&Zn`8 zEG;u+US+}Utk!UrZ$fpx!}Cp!@y-XS!|Rv+ zS9vbbV*SzeVf9|7Wvx#0Ks${%vliu_=ChDudR!~p+Z1?1|M8B;>lVG2*k~=;8hh!d zEX#d~r^bu&eco&PKXa*<{;0k6uT$r7kp!Rv6m^Ub3wnP!rI0OTXGt8tvBd9C+J9ivAM9~ zy3iuM(-mws9_`(?zN`MInsVP_V!w{@A6b|9`Oo!NSl*hheQ1B~FYcxXr!QuF`B`D} z&!lV7{70)86BrJ728tZzUVZh|!Lw<_!P@*Ghu&wh9k}i?Usq5dUdmu9XNQaz>lGbY zo;(h#Jk1g#=2&x~T^)7DGvdG9-L{?m;C9!adS7dUSmvyVy#74s&(_MivkW1>e=nW& zOup9*v{EL0-t)a}t63Tt8Pxq{j^`gQ{Npfd8R#ZD=hwm?B$yu*sxoy;ZZP9Dde$)G z&4E-&CUxTrmpQ%|GOwNeBc^5l`A>6gIrm9D-7ILo)%akIgOqv>{{ zM4g>nzrB3_ar=W;84fTsWP46a)jwWXW9&Hzbn)4gpuQPv7|hLHWX^2dm(~!qi7{tq zf`jvgY;{KCQyKr9-``-rpmY!V;A#3-5%0WVv*e2; zma>JuKiF@rz3=&9rp7&$4|6y*wmc6v1tq#&j2c^d90XYoPM`Xs-)(XF$8f#`28IpY zXZ;^r?9=aiJUesNy)&Qx^h9f~k!El=UXae1qui?Z==@jyEs{;^(iUtMlsLrm#q;y+ zu-8@{`??=oKeDHpb3@;|iHXJW-7hx3uCBemU%2hz+K&}A**0?Znk^Nw^;bbRb@pN0 zf+uO{+bDaMLGye0OVI~BjN5YqB)0M1I@54^C+prG2XW&ER)?Nz{gDlO`zk38+~`~fNql1!v(C0Q8#9y1#-Fz~p}TDCsdZ1!)^)rP*8 ze=nI5?E9d$SyG`{^1{(LT~Pr`AE6AbGq&#Lyj#Cp%jDa12)>xdBH{AGm$zzHMR93O z@b-NtS*|Sl^J!yL*8ExQ-(D>8XS;ab^kRH#;*V4j*Z4lS#h`V>jP*+&L>wqQ@L&bU z;Sa3_Jle(|j-_qhY3@1c_a>d)+cml>D;KVRD-hrsFBrGpX4Vd?xE)n{G|qFZv-5ZS zbMc62aRAq`us>VBul!XXvN6nM)i!Pi`*+)a#hki$^w(Rj|5<7agzm^CHy+z)FTOGT z+KWwY2NKopYkau%T#twCKuJXZykGiTey^Fh?|CKYQaml!|Empn<{yt&YhYw}P;~ad z=c$q>HoYmm%JZbME{t=}L7ppKOiznHf7*7zn{{c$^_F-+okXGfXCG%t2F!~WF1X8M zA;oxCT7}VVZMb_t-&90uLveVr6a`k4N-OEjOFPq0$Rugbqf@59hgfr;^CSL5ne)qMD zZ+)loB1r5-m-nvw(_V#NdgF3;+WQ$U_oSW%8*g2|{QJ_yFVYG>yAGbTU!=y0+&@B2-9V&i)mdjG1km!(=-)B^Xk16yiN z%u?K7+kTSGWErc@nDFVC!+x9p|O z=}n+}X`i+n?3hx-n9gRh@tcm@0gZn?-wviQb-bx%yuD(-H|K$+_wohmLwllq8xk$~ z&6l6=tW#{c@nc{8@;BGwTM~D09RA?M(a0eWx_Py2A><}sZQg@6kQ;*+X{6mzX$+GK zIL$b(Tk*oX&t+#=a(Wq_Gy2SI;G4KV^I~7%hpYX8a+fdviFSTidGFHqzpw5u68W?A zd8Pe<)xr$r7g#tP+-=VPKA2&$=wil_uBYoa>C8@xGz;cAxJ08XGf+fWmuda1zuOMQ znu)GD+Zx(@|68u=j?l*oK1Ez*$;jfk(%X=8vg*brhPjviiG9?+<#+qDP5#@;d#66{ zDOLU9D4^4<5W%UquRmOg!GM7w#?qQSD!@ zT7vc$Ssw<&_wr3Y#GN{Ji2Qo>_SW~mTi^fIzW+Vksl)!@YHm)yhN4dGks*Ae=dKvHfz75}QJ+ookl-8S?hF9PcEpO>BXXTT{{I9t+?l<$*t(3*mC0K?5QVr3MeTrT2nK7S`%p1xMu!; h!Mei?GJ5}O8KUA;=IQF^vd$@?2>_KwwW9z4 literal 0 HcmV?d00001 diff --git a/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png b/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png index f1a6adb0e7e2593083c5242414672a660049e2ed..a2f1f3e263461e19c69808f90e94f18bb7e7e125 100644 GIT binary patch literal 26067 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 literal 12877 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 Date: Mon, 25 Jul 2022 21:58:11 +0000 Subject: [PATCH 03/10] Bump YamlDotNet from 11.2.1 to 12.0.0 (#370) Bumps [YamlDotNet](https://github.com/aaubry/YamlDotNet) from 11.2.1 to 12.0.0. - [Release notes](https://github.com/aaubry/YamlDotNet/releases) - [Commits](https://github.com/aaubry/YamlDotNet/compare/v11.2.1...v12.0.0) --- updated-dependencies: - dependency-name: YamlDotNet dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: jvyden --- ProjectLighthouse/ProjectLighthouse.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index 70269b12..9c2affc2 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -24,7 +24,7 @@ - + From 9c5c5b5798a633839b92520e15f484b09cfd2cdc Mon Sep 17 00:00:00 2001 From: Jayden Date: Mon, 25 Jul 2022 18:38:10 -0400 Subject: [PATCH 04/10] Add support for ReCaptcha in addition to HCaptcha (#372) * Bump YamlDotNet from 11.2.1 to 12.0.0 Bumps [YamlDotNet](https://github.com/aaubry/YamlDotNet) from 11.2.1 to 12.0.0. - [Release notes](https://github.com/aaubry/YamlDotNet/releases) - [Commits](https://github.com/aaubry/YamlDotNet/compare/v11.2.1...v12.0.0) --- updated-dependencies: - dependency-name: YamlDotNet dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Add support for ReCaptcha in addition to HCaptcha Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Pages/Partials/CaptchaPartial.cshtml | 15 +++++++-- .../Configuration/CaptchaType.cs | 16 ++++++++++ .../CaptchaConfiguration.cs | 5 ++- .../Configuration/ServerConfiguration.cs | 2 +- .../Extensions/RequestExtensions.cs | 32 +++++++++++++++---- 5 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 ProjectLighthouse/Configuration/CaptchaType.cs diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml index d54cebce..3a202ba9 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml @@ -1,6 +1,17 @@ @using LBPUnion.ProjectLighthouse.Configuration @if (ServerConfiguration.Instance.Captcha.CaptchaEnabled) { -
- + @switch (ServerConfiguration.Instance.Captcha.Type) + { + case CaptchaType.HCaptcha: +
+ + break; + case CaptchaType.ReCaptcha: +
+ + break; + default: + throw new ArgumentOutOfRangeException(); + } } \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/CaptchaType.cs b/ProjectLighthouse/Configuration/CaptchaType.cs new file mode 100644 index 00000000..564d99c9 --- /dev/null +++ b/ProjectLighthouse/Configuration/CaptchaType.cs @@ -0,0 +1,16 @@ +namespace LBPUnion.ProjectLighthouse.Configuration; + +/// +/// The service to be used for presenting captchas to the user. +/// +public enum CaptchaType +{ + /// + /// A privacy-first captcha. https://www.hcaptcha.com/ + /// + HCaptcha, + /// + /// A captcha service by Google. https://developers.google.com/recaptcha/ + /// + ReCaptcha, +} \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs b/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs index fad16ae6..fd4ea31d 100644 --- a/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs +++ b/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs @@ -2,11 +2,10 @@ namespace LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories; public class CaptchaConfiguration { - // TODO: support recaptcha, not just hcaptcha - // use an enum to define which captcha services can be used? - // LBPUnion.ProjectLighthouse.Types.Settings.CaptchaService public bool CaptchaEnabled { get; set; } + public CaptchaType Type { get; set; } = CaptchaType.HCaptcha; + public string SiteKey { get; set; } = ""; public string Secret { get; set; } = ""; diff --git a/ProjectLighthouse/Configuration/ServerConfiguration.cs b/ProjectLighthouse/Configuration/ServerConfiguration.cs index 3142339e..30c5ee41 100644 --- a/ProjectLighthouse/Configuration/ServerConfiguration.cs +++ b/ProjectLighthouse/Configuration/ServerConfiguration.cs @@ -23,7 +23,7 @@ public class ServerConfiguration // You can use an ObsoleteAttribute instead. Make sure you set it to error, though. // // Thanks for listening~ - public const int CurrentConfigVersion = 6; + public const int CurrentConfigVersion = 7; #region Meta diff --git a/ProjectLighthouse/Extensions/RequestExtensions.cs b/ProjectLighthouse/Extensions/RequestExtensions.cs index d375246c..c922945d 100644 --- a/ProjectLighthouse/Extensions/RequestExtensions.cs +++ b/ProjectLighthouse/Extensions/RequestExtensions.cs @@ -15,7 +15,21 @@ namespace LBPUnion.ProjectLighthouse.Extensions; public static class RequestExtensions { - + static RequestExtensions() + { + Uri captchaUri = ServerConfiguration.Instance.Captcha.Type switch + { + CaptchaType.HCaptcha => new Uri("https://hcaptcha.com"), + CaptchaType.ReCaptcha => new Uri("https://www.google.com/recaptcha/api/"), + _ => throw new ArgumentOutOfRangeException(), + }; + + client = new HttpClient + { + BaseAddress = captchaUri, + }; + } + #region Mobile Checking // yoinked and adapted from https://stackoverflow.com/a/68641796 @@ -32,10 +46,7 @@ public static class RequestExtensions #region Captcha - private static readonly HttpClient client = new() - { - BaseAddress = new Uri("https://hcaptcha.com"), - }; + private static readonly HttpClient client; [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] private static async Task verifyCaptcha(string token) @@ -48,7 +59,7 @@ public static class RequestExtensions new("response", token), }; - HttpResponseMessage response = await client.PostAsync("/siteverify", new FormUrlEncodedContent(payload)); + HttpResponseMessage response = await client.PostAsync("siteverify", new FormUrlEncodedContent(payload)); response.EnsureSuccessStatusCode(); @@ -63,7 +74,14 @@ public static class RequestExtensions { if (ServerConfiguration.Instance.Captcha.CaptchaEnabled) { - bool gotCaptcha = request.Form.TryGetValue("h-captcha-response", out StringValues values); + string keyName = ServerConfiguration.Instance.Captcha.Type switch + { + CaptchaType.HCaptcha => "h-captcha-response", + CaptchaType.ReCaptcha => "g-recaptcha-response", + _ => throw new ArgumentOutOfRangeException(), + }; + + bool gotCaptcha = request.Form.TryGetValue(keyName, out StringValues values); if (!gotCaptcha) return false; if (!await verifyCaptcha(values[0])) return false; From 94765c67f32f560c2e108d30ef0d7d68874a7df6 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 18:50:11 -0400 Subject: [PATCH 05/10] Make login form redirect to landing page if already logged in --- ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml | 2 +- .../Pages/LoginForm.cshtml.cs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml index 37aeb5c4..fbebba49 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml @@ -13,7 +13,7 @@ function onSubmit(form) { if (document.referrer !== null && document.referrer !== "") { const url = new URL(document.referrer); - if (url.pathname !== "/logout") + if (url.pathname !== "/logout" && url.pathname !== "/login") document.getElementById("redirect").value = url.pathname; } diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs index 9b1b5b99..662f1f5b 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs @@ -113,5 +113,11 @@ public class LoginForm : BaseLayout } [UsedImplicitly] - public IActionResult OnGet() => this.Page(); + public IActionResult OnGet() + { + if (this.Database.UserFromWebRequest(this.Request) != null) + return this.RedirectToPage(nameof(LandingPage)); + + return this.Page(); + } } \ No newline at end of file From 23900f821738fc95caba5aa4afe7354c3651c6a0 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 19:18:02 -0400 Subject: [PATCH 06/10] Add level publish logging --- .../Controllers/Slots/PublishController.cs | 55 ++++++++++++++++--- ProjectLighthouse/Logging/LogArea.cs | 1 + 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs index 8c7a2eb7..c47c9c29 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs @@ -4,6 +4,7 @@ using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Files; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Levels; +using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Serialization; @@ -82,34 +83,67 @@ public class PublishController : ControllerBase GameToken gameToken = userAndToken.Value.Item2; Slot? slot = await this.getSlotFromBody(); - if (slot == null) return this.BadRequest(); + if (slot == null) + { + Logger.Warn("Rejecting level upload, slot is null", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Location == null) return this.BadRequest(); + if (slot.Location == null) + { + Logger.Warn("Rejecting level upload, slot location is null", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Description.Length > 500) return this.BadRequest(); + if (slot.Description.Length > 500) + { + Logger.Warn("Rejecting level upload, description too long", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Name.Length > 64) return this.BadRequest(); + if (slot.Name.Length > 64) + { + Logger.Warn("Rejecting level upload, title too long", LogArea.Publish); + return this.BadRequest(); + } if (slot.Resources.Any(resource => !FileHelper.ResourceExists(resource))) { + Logger.Warn("Rejecting level upload, missing resource(s)", LogArea.Publish); return this.BadRequest(); } LbpFile? rootLevel = LbpFile.FromHash(slot.RootLevel); - if (rootLevel == null) return this.BadRequest(); + if (rootLevel == null) + { + Logger.Warn("Rejecting level upload, unable to find rootLevel", LogArea.Publish); + return this.BadRequest(); + } - if (rootLevel.FileType != LbpFileType.Level) return this.BadRequest(); + if (rootLevel.FileType != LbpFileType.Level) + { + Logger.Warn("Rejecting level upload, rootLevel is not a level", LogArea.Publish); + return this.BadRequest(); + } // Republish logic if (slot.SlotId != 0) { Slot? oldSlot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slot.SlotId); - if (oldSlot == null) return this.NotFound(); + if (oldSlot == null) + { + Logger.Warn("Rejecting level republish, wasn't able to find old slot", LogArea.Publish); + return this.NotFound(); + } if (oldSlot.Location == null) throw new ArgumentNullException(); - if (oldSlot.CreatorId != user.UserId) return this.BadRequest(); + if (oldSlot.CreatorId != user.UserId) + { + Logger.Warn("Rejecting level republish, old level not owned by current user", LogArea.Publish); + return this.BadRequest(); + } oldSlot.Location.X = slot.Location.X; oldSlot.Location.Y = slot.Location.Y; @@ -166,7 +200,8 @@ public class PublishController : ControllerBase if (user.GetUsedSlotsForGame(gameToken.GameVersion) > ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots) { - return this.StatusCode(403, ""); + Logger.Warn("Rejecting level upload, too many published slots", LogArea.Publish); + return this.BadRequest(); } //TODO: parse location in body @@ -197,6 +232,8 @@ public class PublishController : ControllerBase "New level published!", $"**{user.Username}** just published a new level: [**{slot.Name}**]({ServerConfiguration.Instance.ExternalUrl}/slot/{slot.SlotId})\n{slot.Description}" ); + + Logger.Success($"Successfully published level {slot.Name} (id: {slot.SlotId}) by {user.Username} (id: {user.UserId})", LogArea.Publish); return this.Ok(slot.Serialize(gameToken.GameVersion)); } diff --git a/ProjectLighthouse/Logging/LogArea.cs b/ProjectLighthouse/Logging/LogArea.cs index f83c0d76..3a8a6ad6 100644 --- a/ProjectLighthouse/Logging/LogArea.cs +++ b/ProjectLighthouse/Logging/LogArea.cs @@ -21,4 +21,5 @@ public enum LogArea Redis, Command, Admin, + Publish, } \ No newline at end of file From 5d6e339fa84ca4c3594eacb54ecb2d9c241eb5fe Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 19:24:18 -0400 Subject: [PATCH 07/10] Bump description max length to 512, log character count --- .../Controllers/Slots/PublishController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs index c47c9c29..5f5d423c 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs @@ -95,15 +95,15 @@ public class PublishController : ControllerBase return this.BadRequest(); } - if (slot.Description.Length > 500) + if (slot.Description.Length > 512) { - Logger.Warn("Rejecting level upload, description too long", LogArea.Publish); + Logger.Warn($"Rejecting level upload, description too long ({slot.Description.Length} characters)", LogArea.Publish); return this.BadRequest(); } if (slot.Name.Length > 64) { - Logger.Warn("Rejecting level upload, title too long", LogArea.Publish); + Logger.Warn($"Rejecting level upload, title too long ({slot.Name.Length} characters)", LogArea.Publish); return this.BadRequest(); } From be592bbacb4ceaf9889a68ea3d64d0fb0a23eafd Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 19:57:13 -0400 Subject: [PATCH 08/10] Eliminate duplicate rooms --- .../Debug/RoomVisualizerController.cs | 13 +++++++++++++ .../Pages/Debug/RoomVisualizerPage.cshtml | 4 ++++ ProjectLighthouse/Match/Rooms/RoomHelper.cs | 17 ++++++++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs b/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs index 7039a9bf..b4772da5 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs @@ -46,4 +46,17 @@ public class RoomVisualizerController : ControllerBase return this.Redirect("/debug/roomVisualizer"); #endif } + + [HttpGet("createRoomsWithDuplicatePlayers")] + public async Task CreateRoomsWithDuplicatePlayers() + { + #if !DEBUG + return this.NotFound(); + #else + List users = await this.database.Users.OrderByDescending(_ => EF.Functions.Random()).Take(1).Select(u => u.UserId).ToListAsync(); + RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); + RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); + return this.Redirect("/debug/roomVisualizer"); + #endif + } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml index 9845e193..f8b81b74 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml @@ -44,6 +44,10 @@
Create Fake Room
+ +
Create Rooms With Duplicate Players
+
+
Nuke all rooms
diff --git a/ProjectLighthouse/Match/Rooms/RoomHelper.cs b/ProjectLighthouse/Match/Rooms/RoomHelper.cs index b65c3b3e..6c6f4fff 100644 --- a/ProjectLighthouse/Match/Rooms/RoomHelper.cs +++ b/ProjectLighthouse/Match/Rooms/RoomHelper.cs @@ -225,7 +225,7 @@ public class RoomHelper { try { - rooms.RemoveAll(r => r.HostId == hostId); + rooms.RemoveAll(r => r.PlayerIds.Contains((int)hostId)); } catch { @@ -233,15 +233,18 @@ public class RoomHelper } } - // Remove players in this new room from other rooms + // Remove rooms containing players in this new room if (newRoom != null) - foreach (Room room in rooms) + { + foreach (Room room in rooms.Where(room => room != newRoom)) { - if (room == newRoom) continue; - - foreach (int newRoomPlayer in newRoom.PlayerIds) room.PlayerIds.RemoveAll(p => p == newRoomPlayer); - roomsToUpdate.Add(room); + foreach (int newRoomPlayer in newRoom.PlayerIds) + { + if (room.PlayerIds.Contains(newRoomPlayer)) + rooms.Remove(room); + } } + } foreach (Room room in roomsToUpdate) { From b30195c5ba48a17c8155a22d6527c80eca767a49 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 20:29:06 -0400 Subject: [PATCH 09/10] Random findBestRoom list, clear recent dive-in list if rooms are unavailable --- ProjectLighthouse/Helpers/MatchHelper.cs | 2 ++ ProjectLighthouse/Match/Rooms/RoomHelper.cs | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ProjectLighthouse/Helpers/MatchHelper.cs b/ProjectLighthouse/Helpers/MatchHelper.cs index aa7d5908..45519705 100644 --- a/ProjectLighthouse/Helpers/MatchHelper.cs +++ b/ProjectLighthouse/Helpers/MatchHelper.cs @@ -36,6 +36,8 @@ public static class MatchHelper return recentlyDivedIn.Contains(otherUserId); } + public static bool ClearUserRecentDiveIns(int userId) => UserRecentlyDivedIn.Remove(userId); + // This is the function used to show people how laughably awful LBP's protocol is. Beware. public static IMatchCommand? Deserialize(string data) { diff --git a/ProjectLighthouse/Match/Rooms/RoomHelper.cs b/ProjectLighthouse/Match/Rooms/RoomHelper.cs index 6c6f4fff..2e0c998d 100644 --- a/ProjectLighthouse/Match/Rooms/RoomHelper.cs +++ b/ProjectLighthouse/Match/Rooms/RoomHelper.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -47,10 +48,10 @@ public class RoomHelper return null; } - IEnumerable rooms = Rooms; + Random random = new(); + IEnumerable rooms = Rooms.OrderBy(_ => random.Next()); rooms = rooms.OrderBy(r => r.IsLookingForPlayers); - rooms = rooms.Where(r => r.RoomVersion == roomVersion).ToList(); if (platform != null) rooms = rooms.Where(r => r.RoomPlatform == platform).ToList(); @@ -137,6 +138,12 @@ public class RoomHelper return response; } + if (user != null) + { + MatchHelper.ClearUserRecentDiveIns(user.UserId); + Logger.Info($"Cleared {user.Username} (id: {user.UserId})'s recent dive-ins", LogArea.Match); + } + return null; } From 6f0752c2471e7c4ff5d203550f8904966cad8508 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 25 Jul 2022 20:31:19 -0400 Subject: [PATCH 10/10] Fix room deletions --- ProjectLighthouse/Match/Rooms/RoomHelper.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ProjectLighthouse/Match/Rooms/RoomHelper.cs b/ProjectLighthouse/Match/Rooms/RoomHelper.cs index 2e0c998d..8726c216 100644 --- a/ProjectLighthouse/Match/Rooms/RoomHelper.cs +++ b/ProjectLighthouse/Match/Rooms/RoomHelper.cs @@ -227,6 +227,13 @@ public class RoomHelper roomsToUpdate.Add(room); } + // DO NOT REMOVE ROOMS BEFORE THIS POINT! + // this will cause the room to be added back to the database + foreach (Room room in roomsToUpdate) + { + rooms.Update(room); + } + // Delete old rooms based on host if (hostId != null) { @@ -247,17 +254,11 @@ public class RoomHelper { foreach (int newRoomPlayer in newRoom.PlayerIds) { - if (room.PlayerIds.Contains(newRoomPlayer)) - rooms.Remove(room); + if (room.PlayerIds.Contains(newRoomPlayer)) rooms.Remove(room); } } } - foreach (Room room in roomsToUpdate) - { - rooms.Update(room); - } - rooms.RemoveAll(r => r.PlayerIds.Count == 0); // Remove empty rooms rooms.RemoveAll(r => r.HostId == -1); // Remove rooms with broken hosts rooms.RemoveAll(r => r.PlayerIds.Count > 4); // Remove obviously bogus rooms