From c3bf5bf33adb3d72fadc4952bc51bfa0cf35fe6e Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 9 Apr 2015 23:02:12 -0500 Subject: [PATCH] Been a while -- unstable 0.75 -added mask command -added baninfo command -added alias command and removed redundant output from `find` -added rcon command -added webfront (http://127.0.0.1:1624) -true skill is officially implemented -find now shows last connect time -noise on pm (if gsc_enabled) -force 8 line chat height (if gsc_enabled) -tell admins the number of reports on join -enhanced ban tracking -ip wait timeout added -remove report on ban -can't report yourself -remove reported players when banned -fixed rare crash with toadmins backend -fixed crash when finding player stats that don't exist -fixed a bug that caused owner command to reactivate only `creator` rank player existed -fixed a bug that caused certain notifications to be sent to all players --- Admin/App.config | 4 +- Admin/Bans.cs | 7 +- Admin/Command.cs | 189 ++++++++--- Admin/Database.cs | 170 ++++++++-- Admin/Event.cs | 13 +- Admin/File.cs | 6 + Admin/Heartbeat.cs | 2 +- Admin/IW4M ADMIN.csproj | 41 ++- Admin/Main.cs | 10 +- Admin/Player.cs | 84 ++++- Admin/SQLiteDatabase.cs | 234 -------------- Admin/Server.cs | 509 +++++++++++++++++------------- Admin/TrueSkill.cs | 67 ++-- Admin/Utilities.cs | 130 +++++++- Admin/WebFront.cs | 394 +++++++++++++++++++++++ Admin/libs/Moserware.Skills.dll | Bin 0 -> 58368 bytes Admin/libs/SQLite.Interop.dll | Bin 0 -> 903168 bytes Admin/libs/System.Data.SQLite.dll | Bin 0 -> 280064 bytes Admin/packages.config | 4 + Admin/version.txt | 23 +- Admin/webfront/bans.html | 11 + Admin/webfront/header.html | 277 ++++++++++++++++ Admin/webfront/main.html | 12 + Admin/webfront/stats.html | 10 + 24 files changed, 1585 insertions(+), 612 deletions(-) delete mode 100644 Admin/SQLiteDatabase.cs create mode 100644 Admin/WebFront.cs create mode 100644 Admin/libs/Moserware.Skills.dll create mode 100644 Admin/libs/SQLite.Interop.dll create mode 100644 Admin/libs/System.Data.SQLite.dll create mode 100644 Admin/packages.config create mode 100644 Admin/webfront/bans.html create mode 100644 Admin/webfront/header.html create mode 100644 Admin/webfront/main.html create mode 100644 Admin/webfront/stats.html diff --git a/Admin/App.config b/Admin/App.config index fe52a9bf4..d229c2d91 100644 --- a/Admin/App.config +++ b/Admin/App.config @@ -1,6 +1,6 @@ - - + + diff --git a/Admin/Bans.cs b/Admin/Bans.cs index c2dc9c62f..266e83928 100644 --- a/Admin/Bans.cs +++ b/Admin/Bans.cs @@ -37,7 +37,12 @@ namespace IW4MAdmin public String getWhen() { - return When.ToString("yyyy-MM-dd HH:mm:ss"); ; + return When.ToString("MM/dd/yy HH:mm:ss"); ; + } + + public DateTime getTime() + { + return When; } private String Reason; diff --git a/Admin/Command.cs b/Admin/Command.cs index a191a0e6f..f833f5b84 100644 --- a/Admin/Command.cs +++ b/Admin/Command.cs @@ -154,7 +154,6 @@ namespace IW4MAdmin E.Target.tempBan(Message); else E.Origin.Tell("You cannot temp ban " + E.Target.getName()); - } } @@ -171,7 +170,7 @@ namespace IW4MAdmin if (E.Owner.Website == null) Message = "^1Player Banned: ^5" + E.Target.LastOffense; else - Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal at " + E.Owner.Website + ")"; + Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal at nbsclan.org)"; if (E.Origin.getLevel() > E.Target.getLevel()) { E.Target.Ban(Message, E.Origin); @@ -203,7 +202,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - String You = String.Format("{0} [^3{1}^7] {{2}} {{3}} [{4}^7] IP: {5}", E.Origin.getName(), E.Origin.getClientNum(), E.Origin.getID(), Utilities.levelToColor(E.Origin.getLevel()), E.Origin.getDBID(), E.Origin.getIP()); + String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.getName(), E.Origin.getClientNum(), E.Origin.getID(), E.Origin.getDBID(), Utilities.levelToColor(E.Origin.getLevel()), E.Origin.getIP()); E.Origin.Tell(You); } @@ -260,7 +259,7 @@ namespace IW4MAdmin if (E.Origin.getLevel() >= C.getNeededPerm()) { _commands = _commands + " [^3" + C.getName() + "^7] "; - if (count >= 3) + if (count >= 4) { E.Origin.Tell(_commands); _commands = String.Empty; @@ -359,7 +358,7 @@ namespace IW4MAdmin { foreach (Player P in E.Owner.getPlayers()) { - if (P != null && P.getLevel() > Player.Permission.User) + if (P != null && P.getLevel() > Player.Permission.User && !P.Masked) { E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.getLevel()), P.getName())); } @@ -421,46 +420,10 @@ namespace IW4MAdmin foreach (Player P in db_players) { - String mesg; - P.Alias = E.Owner.aliasDB.getPlayer(P.getDBID()); - - if (P.getLevel() == Player.Permission.Banned) - mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2} [{3}^7] - {4}", P.getName(), P.getDBID(), P.getID(), Utilities.levelToColor(P.getLevel()), P.getLastO()); - else - mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2} [{3}^7]", P.getName(), P.getDBID(), P.getID(), Utilities.levelToColor(P.getLevel())); - + String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.getName(), P.getDBID(), Utilities.levelToColor(P.getLevel()), P.getIP(), P.getLastConnection()); E.Origin.Tell(mesg); - - if (P.Alias == null) - continue; - - if (P.Alias.getNames() != null) - { - mesg = "Aliases: "; - foreach (String S in P.Alias.getNames()) - { - if (S != String.Empty) - mesg += S + " | "; - } - E.Origin.Tell(mesg); - } - - if (P.Alias.getIPS() != null) - { - mesg = "IPs: "; - foreach (String IP in P.Alias.getIPS()) - { - if (IP.Split('.').Length > 3 && IP != String.Empty) - mesg += IP + " | "; - } - - E.Origin.Tell(mesg); - - } } - } - } class Rules : Command @@ -477,7 +440,6 @@ namespace IW4MAdmin E.Origin.Tell("- " + r); } } - } class PrivateMessage : Command @@ -487,6 +449,7 @@ namespace IW4MAdmin public override void Execute(Event E) { E.Data = Utilities.removeWords(E.Data, 1); + E.Target.Alert(); E.Target.Tell("^1" + E.Origin.getName() + " ^3[PM]^7 - " + E.Data); E.Origin.Tell(String.Format("To ^3{0} ^7-> {1}", E.Target.getName(), E.Data)); } @@ -499,12 +462,20 @@ namespace IW4MAdmin public override void Execute(Event E) { if (E.Target == null) - E.Origin.Tell(String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Origin.stats.Kills, E.Origin.stats.Deaths, E.Origin.stats.KDR, E.Origin.stats.Skill)); - else { if (E.Target.stats == null) - E.Target.stats = E.Owner.statDB.getStats(E.Target.getDBID()); - E.Origin.Tell(String.Format("[^3{4}^7] ^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Target.stats.Kills, E.Target.stats.Deaths, E.Target.stats.KDR, E.Target.stats.Skill, E.Target.getName())); + E.Origin.Tell("You do not have any stats!"); + else + E.Origin.Tell(String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Origin.stats.Kills, E.Origin.stats.Deaths, E.Origin.stats.KDR, E.Origin.stats.Skill)); + } + + else + { + E.Target.stats = E.Owner.statDB.getStats(E.Target.getDBID()); + if (E.Target.stats == null) + E.Origin.Tell("That person does not have any stats at this time!"); + else + E.Origin.Tell(String.Format("[^3{4}^7] ^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Target.stats.Kills, E.Target.stats.Deaths, E.Target.stats.KDR, E.Target.stats.Skill, E.Target.getName())); } } } @@ -527,6 +498,7 @@ namespace IW4MAdmin TopP.Add(P); } } + if (TopP.Count > 0) { E.Origin.Tell("^1TOP PLAYERS"); @@ -536,6 +508,7 @@ namespace IW4MAdmin E.Origin.Tell(String.Format("^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL", P.getName(), P.stats.KDR, P.stats.Skill)); } } + else E.Origin.Tell("There are no top players yet!"); } @@ -608,6 +581,12 @@ namespace IW4MAdmin public override void Execute(Event E) { + if (E.Target == E.Origin) + { + E.Origin.Tell("You cannot report yourself, silly."); + return; + } + if (E.Target.getLevel() > E.Origin.getLevel()) { E.Origin.Tell("You cannot report " + E.Target.getName()); @@ -655,5 +634,121 @@ namespace IW4MAdmin E.Owner.RCON.addRCON(String.Format("admin_lastevent tell;{0};{1};{2}", E.Origin.getID(), E.Target.getID(), E.Data)); } } + + class Mask : Command + { + public Mask(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + + public override void Execute(Event E) + { + if (E.Origin.Masked) + { + E.Origin.Masked = false; + E.Origin.Tell("You are now unmasked"); + } + else + { + E.Origin.Masked = true; + E.Origin.Tell("You are now masked"); + } + } + } + + class BanInfo : Command + { + public BanInfo(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + + public override void Execute(Event E) + { + if (E.Target == null) + { + E.Origin.Tell("No bans for that player."); + return; + } + + Ban B = E.Owner.Bans.Find(b => b.getID().Equals(E.Target.getID())); + + if (B == null) + { + E.Origin.Tell("No active ban was found for that player."); + return; + } + + Player Banner = E.Owner.clientDB.getPlayer(B.getBanner(), -1); + + if (Banner == null) + { + E.Origin.Tell("Ban was found for the player, but origin of the ban is unavailable."); + return; + } + + E.Origin.Tell(String.Format("^1{0} ^7was banned by ^5{1} ^7for: {2}", E.Target.getName(), Banner.getName(), B.getReason())); + } + } + + class Alias : Command + { + public Alias(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + + public override void Execute(Event E) + { + E.Target.Alias = E.Owner.aliasDB.getPlayer(E.Target.getDBID()); + + if (E.Target.Alias == null) + { + E.Target.Tell("Could not find alias info for that player."); + return; + } + + E.Target.Tell("[^3" + E.Target.getName() + "^7]"); + StringBuilder message = new StringBuilder(); + + List playerAliases = new List(); + E.Owner.getAliases(playerAliases, E.Target); + + // if (E.Target.Alias.getNames() != null) + { + message.Append("Aliases: "); + + foreach (Player P in playerAliases) + { + foreach (String S in P.Alias.getNames()) + { + if (S != String.Empty && S != E.Target.getName()) + message.Append(S + " | "); + } + } + E.Origin.Tell(message.ToString()); + } + + if (E.Target.Alias.getIPS() != null) + { + message.Append("IPS: "); + + foreach (Player P2 in playerAliases) + { + foreach (String IP in P2.Alias.getIPS()) + { + if (IP.Split('.').Length > 3 && IP != String.Empty && !message.ToString().Contains(IP)) + message.Append (IP + " | "); + } + } + + E.Origin.Tell(message.ToString()); + } + } + } + + class _RCON : Command + { + public _RCON(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + + public override void Execute(Event E) + { + String[] Response = E.Owner.RCON.addRCON(E.Data.Trim()); + if (Response.Length > 0) + E.Origin.Tell("Successfuly sent RCON command!"); + } + } } \ No newline at end of file diff --git a/Admin/Database.cs b/Admin/Database.cs index 218f5a847..40353ac3d 100644 --- a/Admin/Database.cs +++ b/Admin/Database.cs @@ -79,11 +79,17 @@ namespace IW4MAdmin protected int ExecuteNonQuery(String Request) { waitForClose(); - Con.Open(); - SQLiteCommand CMD = new SQLiteCommand(Con); - CMD.CommandText = Request; - int rowsUpdated = CMD.ExecuteNonQuery(); - Con.Close(); + int rowsUpdated = 0; + + lock (Con) + { + Con.Open(); + SQLiteCommand CMD = new SQLiteCommand(Con); + CMD.CommandText = Request; + rowsUpdated = CMD.ExecuteNonQuery(); + Con.Close(); + } + return rowsUpdated; } @@ -93,13 +99,17 @@ namespace IW4MAdmin try { waitForClose(); - Con.Open(); - SQLiteCommand mycommand = new SQLiteCommand(Con); - mycommand.CommandText = sql; - SQLiteDataReader reader = mycommand.ExecuteReader(); - dt.Load(reader); - reader.Close(); - Con.Close(); + lock (Con) + { + Con.Open(); + SQLiteCommand mycommand = new SQLiteCommand(Con); + mycommand.CommandText = sql; + SQLiteDataReader reader = mycommand.ExecuteReader(); + dt.Load(reader); + reader.Close(); + Con.Close(); + } + } catch (Exception e) { @@ -134,7 +144,7 @@ namespace IW4MAdmin { if(!File.Exists(FileName)) { - String Create = "CREATE TABLE [CLIENTS] ( [Name] TEXT NULL, [npID] TEXT NULL, [Number] INTEGER PRIMARY KEY AUTOINCREMENT, [Level] INT DEFAULT 0 NULL, [LastOffense] TEXT NULL, [Connections] INT DEFAULT 1 NULL, [IP] TEXT NULL);"; + String Create = "CREATE TABLE [CLIENTS] ( [Name] TEXT NULL, [npID] TEXT NULL, [Number] INTEGER PRIMARY KEY AUTOINCREMENT, [Level] INT DEFAULT 0 NULL, [LastOffense] TEXT NULL, [Connections] INT DEFAULT 1 NULL, [IP] TEXT NULL, [LastConnection] TEXT NULL);"; ExecuteNonQuery(Create); Create = "CREATE TABLE [BANS] ( [Reason] TEXT NULL, [npID] TEXT NULL, [bannedByID] TEXT NULL, [IP] TEXT NULL, [TIME] TEXT NULL);"; ExecuteNonQuery(Create); @@ -150,12 +160,18 @@ namespace IW4MAdmin if (Result != null && Result.Rows.Count > 0) { DataRow ResponseRow = Result.Rows[0]; - - - // if (ResponseRow["IP"].ToString().Length < 2) - // ResponseRow["IP"] = DateTime.Now.ToString(); // because aliases and backwards compatibility + DateTime LC; - return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString()); + try + { + LC = DateTime.Parse(ResponseRow["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } + + return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), LC); } else @@ -171,11 +187,17 @@ namespace IW4MAdmin if (Result != null && Result.Rows.Count > 0) { DataRow p = Result.Rows[0]; + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } - // if (p["IP"].ToString().Length < 2) - // p["IP"] = DateTime.Now.ToString(); // because aliases and backwards compatibility - - return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString()); + return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC); } else @@ -194,7 +216,17 @@ namespace IW4MAdmin { foreach (DataRow p in Result.Rows) { - Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString())); + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } + + Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC)); } return Players; } @@ -206,7 +238,7 @@ namespace IW4MAdmin //Returns any player with level 4 permissions, null if no owner found public Player getOwner() { - String Query = String.Format("SELECT * FROM CLIENTS WHERE Level = '{0}'", 4); + String Query = String.Format("SELECT * FROM CLIENTS WHERE Level >= '{0}'", 4); DataTable Result = GetDataTable(Query); if (Result != null && Result.Rows.Count > 0) @@ -225,14 +257,12 @@ namespace IW4MAdmin public List getBans() { List Bans = new List(); - DataTable Result = GetDataTable("SELECT * FROM BANS"); + DataTable Result = GetDataTable("SELECT * FROM BANS ORDER BY TIME DESC"); foreach (DataRow Row in Result.Rows) { if (Row["TIME"].ToString().Length < 2) //compatibility with my old database Row["TIME"] = DateTime.Now.ToString(); - // if (Row["IP"].ToString().Length < 2) - // Row["IP"] = DateTime.Now.ToString(); //because we don't have old ip's and don't want a messy alias Bans.Add(new Ban(Row["Reason"].ToString(), Row["npID"].ToString(), Row["bannedByID"].ToString(), DateTime.Parse(Row["TIME"].ToString()), Row["IP"].ToString())); } @@ -261,6 +291,7 @@ namespace IW4MAdmin newPlayer.Add("LastOffense", ""); newPlayer.Add("Connections", 1); newPlayer.Add("IP", P.getIP()); + newPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); Insert("CLIENTS", newPlayer); } @@ -276,6 +307,7 @@ namespace IW4MAdmin updatedPlayer.Add("LastOffense", P.getLastO()); updatedPlayer.Add("Connections", P.getConnections()); updatedPlayer.Add("IP", P.getIP()); + updatedPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.getID())); } @@ -314,7 +346,7 @@ namespace IW4MAdmin { if (!File.Exists(FileName)) { - String Create = "CREATE TABLE [STATS] ( [Number] INTEGER, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] REAL DEFAULT 0, [SKILL] REAL DEFAULT 0 );"; + String Create = "CREATE TABLE [STATS] ( [Number] INTEGER, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] REAL DEFAULT 0, [SKILL] REAL DEFAULT 0, [MEAN] REAL DEFAULT 0, [DEV] REAL DEFAULT 0 );"; ExecuteNonQuery(Create); } } @@ -328,11 +360,18 @@ namespace IW4MAdmin if (Result != null && Result.Rows.Count > 0) { DataRow ResponseRow = Result.Rows[0]; - return new Stats(Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["SKILL"])); + if (ResponseRow["MEAN"] == DBNull.Value) + ResponseRow["MEAN"] = 25; + if (ResponseRow["DEV"] == DBNull.Value) + ResponseRow["DEV"] = 8; + if (ResponseRow["SKILL"] == DBNull.Value) + ResponseRow["SKILL"] = 0; + + return new Stats(Convert.ToInt32(ResponseRow["Number"]), Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["SKILL"]), Convert.ToDouble(ResponseRow["MEAN"]), Convert.ToDouble(ResponseRow["DEV"])); } else - return null; + return new Stats(0, 0, 0, 0, 0, 25, 8.3333); } public void addPlayer(Player P) @@ -343,7 +382,9 @@ namespace IW4MAdmin newPlayer.Add("KILLS", 0); newPlayer.Add("DEATHS", 0); newPlayer.Add("KDR", 0); - newPlayer.Add("SKILL", 1); + newPlayer.Add("SKILL", Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.ConservativeRating); + newPlayer.Add("MEAN", Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.Mean); + newPlayer.Add("DEV", Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.StandardDeviation); Insert("STATS", newPlayer); } @@ -357,6 +398,8 @@ namespace IW4MAdmin updatedPlayer.Add("DEATHS", P.stats.Deaths); updatedPlayer.Add("KDR", Math.Round(P.stats.KDR, 2)); updatedPlayer.Add("SKILL", P.stats.Skill); + updatedPlayer.Add("MEAN", P.stats.Rating.Mean); + updatedPlayer.Add("DEV", P.stats.Rating.StandardDeviation); Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.getDBID())); } @@ -364,7 +407,7 @@ namespace IW4MAdmin //Returns top 8 players (we filter through them later) public List topStats() { - String Query = String.Format("SELECT * FROM STATS WHERE SKILL > '{0}' ORDER BY SKILL DESC LIMIT 8", 10); + String Query = String.Format("SELECT * FROM STATS WHERE SKILL > '{0}' ORDER BY SKILL DESC LIMIT 5", 230); DataTable Result = GetDataTable(Query); List Top = new List(); @@ -373,8 +416,16 @@ namespace IW4MAdmin { foreach (DataRow D in Result.Rows) { - Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"])); - if (S.Skill > 10) + if (D["MEAN"] == DBNull.Value) + continue; + if (D["DEV"] == DBNull.Value) + continue; + + if (D["SKILL"] == DBNull.Value) + D["SKILL"] = 0; + + Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["KILLS"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]), Convert.ToDouble(D["MEAN"]), Convert.ToDouble(D["DEV"])); + if (S.Skill > 230) Top.Add(S); } } @@ -382,6 +433,42 @@ namespace IW4MAdmin return Top; } + public List getMultipleStats(int start, int length) + { + String Query = String.Format("SELECT * FROM STATS ORDER BY SKILL DESC LIMIT '{0}' OFFSET '{1}'", length, start); + DataTable Result = GetDataTable(Query); + + List Stats = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow D in Result.Rows) + { + if (D["MEAN"] == DBNull.Value) + continue; + if (D["DEV"] == DBNull.Value) + continue; + + if (D["SKILL"] == DBNull.Value) + D["SKILL"] = 0; + + Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["KILLS"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]), Convert.ToDouble(D["MEAN"]), Convert.ToDouble(D["DEV"])); + Stats.Add(S); + } + } + + return Stats; + } + + public int totalStats() + { + DataTable Result = GetDataTable("SELECT * from STATS ORDER BY Number DESC LIMIT 1"); + if (Result.Rows.Count > 0) + return Convert.ToInt32(Result.Rows[0]["Number"]); + else + return 0; + } + public void clearSkill() { String Query = "SELECT * FROM STATS"; @@ -423,6 +510,21 @@ namespace IW4MAdmin return null; } + public List getPlayer(String IP) + { + String Query = String.Format("SELECT * FROM ALIASES WHERE IPS LIKE '%{0}%'", IP); + DataTable Result = GetDataTable(Query); + List players = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow p in Result.Rows) + players.Add(new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString())); + } + + return players; + } + public void addPlayer(Aliases Alias) { Dictionary newPlayer = new Dictionary(); diff --git a/Admin/Event.cs b/Admin/Event.cs index 19563b17a..510808fe9 100644 --- a/Admin/Event.cs +++ b/Admin/Event.cs @@ -66,24 +66,19 @@ namespace IW4MAdmin eventType = eventType.Trim(); if (eventType == "J") - return new Event(GType.Connect, null, SV.clientFromLine(line, 3, true), null, SV); + return new Event(GType.Connect, null, SV.clientFromEventLine(line, 2), null, SV); if (eventType == "Q") - return new Event(GType.Disconnect, null, SV.getPlayers()[Convert.ToInt16(line[2])], null, null); + return new Event(GType.Disconnect, null, SV.clientFromEventLine(line, 2), null, SV); if (eventType == "K") - return new Event(GType.Kill, line[9], SV.clientFromLineArr(line, true), SV.clientFromLineArr(line, false), null); + return new Event(GType.Kill, line[9], SV.clientFromEventLine(line, 6), SV.clientFromEventLine(line, 2), SV); if (line[0].Substring(line[0].Length - 3).Trim() == "say") { - if (line.Length < 4) - { - Console.WriteLine("SAY FUCKED UP BIG-TIME"); - return null; - } Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]"); string message = rgx.Replace(line[4], ""); - return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromLine(line, 3, false), null, null); + return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromEventLine(line, 2), null, SV); } if (eventType == ":") diff --git a/Admin/File.cs b/Admin/File.cs index 98fd3f3fa..d6c96c445 100644 --- a/Admin/File.cs +++ b/Admin/File.cs @@ -112,11 +112,17 @@ namespace IW4MAdmin return encoding.GetString(buffer); } } + public String[] readAll() { return Handle.ReadToEnd().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); } + public String getLines() + { + return Handle.ReadToEnd(); + } + public String[] end(int neededLines) { var lines = new List(); diff --git a/Admin/Heartbeat.cs b/Admin/Heartbeat.cs index 8fd6e601c..c43560873 100644 --- a/Admin/Heartbeat.cs +++ b/Admin/Heartbeat.cs @@ -14,7 +14,7 @@ namespace IW4MAdmin public void Send() { - String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.getClientNum().ToString() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString()); + String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.statusPlayers.Count.ToString() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString()); Handle.Request(URI); } diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj index 3ba02d142..b46b6200f 100644 --- a/Admin/IW4M ADMIN.csproj +++ b/Admin/IW4M ADMIN.csproj @@ -9,7 +9,7 @@ Properties IW4MAdmin IW4MAdmin - v2.0 + v4.0 512 true @@ -78,11 +78,18 @@ IW4MAdmin.Program + + ..\packages\Kayak.0.7.2\lib\Kayak.dll + + + False + bin\Debug\Moserware.Skills.dll + - + False - bin\Release\System.Data.SQLite.dll + libs\System.Data.SQLite.dll @@ -110,9 +117,31 @@ + - + + PreserveNewest + + + + PreserveNewest + + + Always + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -127,6 +156,7 @@ PreserveNewest + SettingsSingleFileGenerator @@ -151,7 +181,8 @@ - copy $(TargetDir)$(TargetFileName) $(SolutionDir)OFFICIAL\NBS\$(TargetFileName) + copy $(TargetDir)$(TargetFileName) $(SolutionDir)OFFICIAL\Release\$(TargetFileName) +copy $(SolutionDir)Admin\version.txt $(SolutionDir)OFFICIAL\Release\version.txt GSAVpevHj zgY6B@rr(lgroh`I1tB-r~)tid=d^y0>|{ zq#{W7Ht$QclTD5J(eoX?oT!Y=j`_v&T^?SF>B`v4F}&6W{w@*Dbt$#pqdCiU7krB( zybGRDYpbGCNAFtO72#d*DsGfvo|V?qu?-x%cuPr(fp+uJL}k`j4ZAx&kW~Bh_;XNevj~ndxgqKSi1@tN3ENOP!NXKXVs-)#WdwKjck;{R& z366bysHC$%`}s1WDyz8Be8&NPP|^&bgWO(@=|sOi#QhY-vO_$a2wQ2X<8z*`Y%e>G z@Ux1hT1R<61?Do3Eo-#Kag3J|EwolOYT!7|cT0L3=qqkLg`NwoZH?ADPH-Pd2OGTy z6e5Uy+vu;3lYA0U1-sg4yWZ4-?_Ka@}!-4|y6r=dsE0zdC;8lZeXL zoOn;KYrOj`w28IxI?pE(qyIWDArhniI%m%aPn=P1a9^T@YyF;ALezF zKR{H;HpSQX`h`CvZC}JU0-8)z!G4TS23n>l)$3QjMNtQ@-}rt-wLNe13q(7ak(Sc{25h~}|X3HjhT zny3<5zR1ha->pQ?O7>Plk(W&$F_+S@0|{fiEIoD}(meJ}!UQk7K3dYngfcIOzJjQd zg*Tq*<)g1Bs$dNpXL3J1WHC()z;S&Rk7C4*5Uf1Fj_w=ZS|a&J)-sNl6;)sc{J2-3!=MJak}jlEMXztrHa$NB;kFj zI6XiT-j|BgYfHlWQgM2eB)l&br#F;@_od?WBuPsXk#Z%yNffX`l(#eSuveVkSJJ`6 zFM;M0RavJKzxHaRuOO;mc-N?rep+|}odcU~CAAB~YrF(KN)lec8Qfx7A=b_m*# zl*!70`*jg04d@ef0Ma3-U~k_3o$7IgV6e z)k*H|$ko4;)Ced~_x(!P(vtf*2IvKnx&RH-=Ma^#e#srZ^Ys&wMkHr>57Dg?BHhH~ z!H(g2KS@sjjnJn{nv*=zF;YJyX$jCM-Qy&tD`TsZ2Y5fA#}HLm8`e%|(CigPN>8FTxT33<_y~pe4h{S$(ypH+1_CzkiJyAz*_^TeW;hO=o zy^9sia=hSORwLaL$~MT6VFqbgOHmTcd1)9DBT9Q&j3W z;JsE6rdwYl-CN2w$Z_2J9Yv*%Gu|5%VY*E<()~r*205;HZ&p<5_}P1lB22fvM!Fr! z2JPwdcSWTRZ=YR?Fx|&B((O^UL5?t=PZgCqVtqbWG|O?X&k5ar3VQ`!u@~@@dS@cs zId=0osZUc>;B!`AQ%(GWzFtu*yFhuu9AeICa=*_-MTO2-c12OsgaZDfq9six`Bc*j zO{V%>)3;Kd^Vpmw&-vWc&wh*xn!M_BTW@(r&sZ(T+&$uRV=k ziej0kQAkwAIyQ}EwT#WeW-W)6(qWvEl-V>Jh<%57R#*d?9`W%q(j^UVdK@TM(uAfd z+}kLYG^1%I&@4$WfX&BPC+Rh?`50Rzy$3d5( z7HaH~RMsqsg&7wm&2AP8bW76GW~Y5>8!ax1y1d@3+^B8zkn}+_*vT0WN!r~Ec5=pa zNr%8z$9O~18L-tcc1pSqwz|f5lFa7WK6%}cwQEH;x0DUh>&y-q-$ujm(&8%H8lE4>H@Yn;}JCW5Vzv6-lf&1ezj8*h|c!Sc%3f))*Z8ymNX#3)WQj322kFv4g1CK_Ri3V5=S zqUdGcWFuV=%S?^qDMq=ZB~4!TO)-usdc(Jgk$jc%WPMXN_%<~%B+Y2?fp0Ton4}k) zZ18PiJWho3%in!l8cT@IXp>Vv@l7>WNGeM`;M>~xn@9(q1-y;1s|J0pXp6m#@uQ-R z_O^!4Pp;#8)M#&nD?04k(dbSju68>cqlv`TZf7Ip8l|&7PW{Tai}8e{qd;AaWkmDX z_0;pe8O9-L3r_pdx0~_3qy|9U4eL7Q0(qw0_U&P`l+-!R=Im+QPgG%LrycdoG>Rn+ zOWR`4G^R_M2)16vQb{ww*2{QJ(o(SXHvTGU9oTvsdnEl0Y+1%vlJu`Wf#NRWZEQ?q|gQg0?dDeQTt-l71#y zO;p9KHkr zn?=r%#yCl5+C1+Z1yAyX?X2Gl=K}`(Vgcpyi{Gox(Z+5`-u`bm#~87?uze488EZ_E zbgj(+-vB;NgoGZbQT-APLXFy+bhn=#(bg*meTfy^D!fYUihi99&DS!A2WtYdW>k2 zAU3^iK6vhxR0*~cgVC!&m26qt-<%~zJEAi7T3egnBzv%s8j$qVoyk22mM1)V6?6Gm?Wb7ctjOGg>K%^_yno65(u<=vQI9 zFR3iGmEUwDAOzEiu`9^L{Bk66Rw~W#B zdfGI$6FlEDa_RN7X>4D|UdAS)Wi<7=Tzt3pFUE=(q=oFOj@{3U&{|Ckh zdRc8Ao9zto|Ep0SZG)5k197y<+qwnr1cV6vwX^BLuOePT4@S6v0)b5lgQZ zPGe=TGXH3lOTv}wN8^|zT#v3At&*{XX$)7ApNt-oa3#5B%#wub=5^z&BwROd80je@ z9j==)Uxv=5dSj#*n3D+@)*|LSO;X3AJ?v#YoWCG*sU$pqLFQf}asGl$ z*4kCVyZ%7%&vhrNwj>;5oBiu3Ds}AihhO?2Pw_V@(PjkYf=}lT`Nx=jB`pT3Z%!v# z2v^?OUJc9^tRM9~HR#%4NEC3s%(Pcq+^(%*&e~P(Q(!kEQ{hOKZb)aLQdk`(moi(UYN3@B#u7#PVD3-M_dn)?e(b62I$T#3# z^HD{?0cqw_is}WlH5Vuf_w8t|QWO`EZf;SO9MIYPOi{~#uI4dC9Rj+W7Zr62$TV*& z$`0sbHciJ`;|^kQK!3B82#?|ZfLwF6qT+xd=BJ8g1&lVoQZz4Mta(Y%(tz>iZ$wpA zt1c=05!2QQOQ^ECcF6?tk<`CSuqe~K- zWR8@yv`Z||LxR}4E(N^Ud`#Llb%_I-CTV+@Y@k_^K89Q-oAV_dgIp$?&r7-pwSLT8 zDaqb76X*>|^}D_kP-4C(sYTaKK!1~z(RGyP7D@z}+?4pYofBD}JJ z_ifC3iK?tGx~A}{W@||oiP}l}m8hd6N5&}6sb*(EboDaT%q6N|OPYKYFx4zk^j*L- zbD5&60Tt$EMZX42H$A)1S%Gv$;0!Z_sDg!N*aK&pEhRO`a0bpY3#Dg+jL^Vm%z2VB zQ(+%zu9nm+BO-9N`JSTsfzO&BN@|l47dXem%^O8DcvM)GvuUh2 zqkyk8eI=Db6q2^72kQ}5+=InmlW1~5gXdY|O{ZimYv$VgkHSc~caFcmSQpfHr=r88MTwxp5-4V3e zd^baL+pcDg4f0T)-n||UfM8a(08t)=H*dkqV!t>{p%WkKPJe(JS4 zC_+(a@3({MD{9_*b5N|J+}`_wk`#^a{drKbqS?Ji1vORlQtwk9)$~CP+n(OT+&sVS zJvOMBN~dLg8Pr@+ovhPAEfl3@T?lHWs880-pw@~;XYt^6il%3I2IKGKi8J<6maiLa z&KeukQQ1Du3JFeEbTn&UP-jJFv+4$SQFJ4#QE+!f9)0!&^;8tvr)hAeq9%QY1@%(Y zvCkQg-irG7X%$>eLx&`Md+T15Qc%Y(B`s4=> zQuI}yVZlX;uJjojJXDb_`*hH7MIqU3f=4Qf%N`aqR#BJiiNOyl8Va`Yii)!z4thvY zMfQ~7hZQZ$E)Rwu^p!{SX71RPDN5+KFKDr%44@^7hW7hBc&Vb|e#e5JS5yh~ zqM{Z3P6fZDXcOe}ilR^YZ46$a=w!c;;5CYV>325xHAOx-KL)?4s6o!p!EY-{%i$sK zDe4NeNl{LYBV@CpF*yMte^XSJ6CSc%(Sn?qkiRQ>B_}>)x1x%NiaziEV93{sPW7J@@{OYF{ilVTQ&cPWbkIdb^>T*= z{h+8N&?QA#xzB`LR&;;vf{-5-J({~D_(`=36M+Aji3oR*Fg;S3*)1 z&2s!2(zZsr_R5CkbyS4qr7Obny3|P5RoMnPJVLuE!aHWY6k)oY8tM8g86X<<_q?)Ux)&8;y5)*6-77WHtx&c>j{MM7 zib@?LLtj@k%P~3h?HcJeC>xHyjf!ymZBm5g{k2BAEy^~?Q4zXT5xi#=x?K^btE!Q1 zm$G5H4;5j$j}>9M&uXOGt8AEVzamU`P!Xm(TqE5PWy3qxM-^dv9#e#OtiSSjzW}d7 za6Yqzo$$D-C@}1#N5~+TEj;X$M;g&Wt0FHt>}!vnM0iIcF6^|&P$Ik+l*!L{Od#6H z=H{jFZ#|9?Rap3D>bD-JiK?vSWV=R$c_xK@>)|mN%fmcdgq`)MLnPi<`pzSsNaXpQ z#~dP&%Xc0x6JaiG!@l!)he+gd-s3|ek;_Go!$cyNiymo(Sf0q`qDLkXrYqnVJ#vZW zS>}M=VHZ7~lN3522j~S!^#|kwt&)^H;JC;49-Ae#CE72k2hmv~EMY>}_Z|^NSb7;- zH{gk|A3gR+`f$Kh>xRd7MB=*trpHZb!)xuE9w9?SI=t?`=`n&xT=)O%v54r5b~R;g z*v}r;edu{cJ2qf$*e@PIk|sD8hu!i>lQgs2+^}D%Pe4m}-59Vu>^F}&WW##)GJf-T zQFz+XcH3h$Q3b0vuz=t8*dytlfos5aMN;y>Y|gBZp;&qaYdP>uf6Zzqsr^8B6Wy94 zsXLHv9g);`;JPrwx-F>)N-(XMVIr4tL>ZFG29_J9RUv5xlxMTnN?I`R-7pX98zMaK zy$s8`Du}IwT9>JM*CcuSHwFqBE{@?7zmFhYx}?~)NvxJtBFW4@?NiHIBk7e^ zSo-rLFdd$UFCg7EB0Qp#VGiqzvYij}wQecfl`yB}H`0}^fcslvif)AYTS-Ki%ayPI ztFy9w>Jwz$PgG%z$v106o}c6=)DE>il=OXm z9N6|r`Yk^j=nF|<1@P{cbxKlP0ld3qotMB*NDH)Tf@+n`j;zGiX}vNNd~! zSi(FuY0#|N(N^vlQQq`Hi)+`n3MDNav;t^^AjsuCpov6P_7~IF1vapzOS(J=-mJ3L zOJakO4oh+pv9VY}mA(GpZM7R%-h#Bm!MlL!N@_JYBJduolk~*V7;9w{?Womra4#d) z$|n-DMnmfXB5}8{p*538JWFn9EfYk~lH;sBM7RbVtQ}_^73qKqcq8k3qAL6B!6#}r zvTjMjbKA)Bd{ERH&t@YlMAD0cFMww((N68P!9M~G5;pCF!N1gww-!j+J~)miTF*=R zbZ`OCIzcoV6Ri)3#PKCsJBh^cC0PfE#PKCrSBS*%C0X!73bdz~6_c%|MB;8?vIPeC zS7p|+tqG|nf1no17H-=QzmeebyvKGbq^+VRK#s(NJ51&`d=S*wRCLD|#4m>8ofmP(MYbKsk!01NB!l*Oniet7thK zUxA`Ewu;cfirxV#QnVT9J{NhN8l1w1DZ;1Dip(ite&N;h!(hMgQ7%t2ad33_gNm*X zP7EKfh!-Y?KcuL&vt{_hiaIzug+HR`gTa~Mk1Fyk>=Zs(kxyYk_+yIv3x|f6D0;BT z`0%NUE~b=(mnjN^(#sVkbxI6>Qqk3v#PAA5GrJ{*Kcy(5@agdBidqd`68?-LN9v03 zXB8zBt_ZJG)C_2z)slMTLY7fDHfVv>Q&MTyVL=P6ev&AVB{eSkG<=PbL| zg>SL~B|TYm!+*0?Pf}UxrSQL5&53Y6i)Gua2}IM_`J%dYwp$?+Fqbm6+t$n2Vbzz! zheX%eX*E^U5NOgQ;Tb$6rOw~2%_V|jhosi2vKBoqsO6Aubw05Qryy0b9z*)n`OI1~ z)kOt$4qC?~4FKB_E4)V$I6n_i#^z1ljvY z!nGsVo-Ya4ju86=Nw{`|*(X$pbhviZwx5uMYe$4V?I~fywIkBLOcJggQFb<6*l_Kr zZ_ky4YsWqIwUTh{Xk@=C3D=Hzd)f?<4%dzZd$}ZBI~v>fNW!%v(Ox)Hc;ed8)V^L4 zt{u(ow6yZvep$J!!Zi;Xv>8=P@lAeliCCOBTD@h+kxRPWm!j+`2B3w!OE5el| zPZ6#p`HFBQDNuwf$sk3zk_=XaD@mauTuFv0!j)vWB3wyED#DfI0sAIuL9r(qW8Y0A z_C#asXNkm~XpDW)EIcb>Pc+uPn@G&_W9@s1aK@bPHP-%>u(7`neK_br`(;U|fX3PN zXE2vD8jgVR_NJ0>1WdFKlY}GSar-n$I0B~HmrKGCP-_3HBpd-{_M?(;1WdEvkc1=>`?E#W-jBT>t zBMHaYU+niv!ZEhl-cu5evA^02CE*y`W`9@`j=XNMl5mWDYIn{R$ADw(GkcsQ9AgLVttH_Y``q4J5{|LM z_WLB^82iHhD3Lg0$Lx!U#Jdj1?0bpCIr`H6g`$@o$L-$`xJi($Cu02pj#5;92_#A~A~3*=x_o zJh3iw>z=bWC92Z=?oZ+8?N11@*S>$0=Xv`|X~Xv_&)auN+dbrYR8lI@57HC=HsZXU zEui+)@NXl|+iMevnw__&5s7v=Z=Xbjby;5bf_<8zHFdwYuMwWwBlmX-zifY>Nc6}n z_Ae!2kGyU-7K-zSJ@S^lyCm$9zu5;!!XA0sK2j3)Nai_R681>$xm6PONZr$VPUML_ z(!;a2B$qc(z+4(qWJE_AHTveaY#$i%7JDzvo#Z(Gvci5sNV$ zw#25o0iI2XPTJ?(UsX5Aa}<&I%ab6_G9r;nkmqtDkxP*0F(S<6NZnx1i!vP^ZK$VX ziKrRYy0+(|L?V~Eo{NY?F8Cd1{Ehi)y>UN&h50t9#%#ke>FRXCc{)3 zizlBZpq#Y;)ma+FbSBLr9Sq9Z=sUtC6f>1ngi$%0p<-O&xfHWhDQEb5WIB~-u-7SG z8oU7T)R>c0YEkGnYA3L0Ds`f0X}Tia$s`hbjCOg)ukIFs!q4pa%Pq;%|a- z_UrG$Isma+uG zI(rG!V6TCi>|L^Manl_T=Ijuts}5*&9d*6Im{!!`e@^^yRsWjx{PqvyHCA17_plD% zQoz=$w!)XPR1U6qcc0&fb#_(xb2hY7b#A}+teM+ykczYEP&$4!h0Z4Q0h4)*#P380 zgL<%fpcab*)!2jJ!>P6|fBcm{leGthFMg1ZIEuTM``_!Mvw=_(gAJ#;jiI_t_+8!p zj8DzBDuEnejsk^ar`#4$%u5ur8q^@G$=-o5e5(W$z8wL|SrvspRbid&hp@p8-4TD7 z;*V0iNF`LvNXH=_z6nD+a%z?|X^B)PrJn5DL{%)n{?a)4VgvCe~ zv!bwm2WfTqMh70Rh`#|b8oNz-TB9&5Vw@1>ER15JNs~#j4Mj`-a}_-b`zL-82>nG& znOj)QsMs^%PxxrObf6Ny$i-CMsH|QT(;pP(UW$2uVjiNHNh(HT81K?46rS#;PeYiq zXDLR6g}(@6-86QmkGnsHbvdKDd;WfAHmDSn+S3N#rNNvAF+!=po%s#5&o$;a% zxS#j`X)DMduM`G5?lzxS*WcBv#fty?qjR_ZPhCMoo&RsH4z57{A(XE zLu%~LtO$3mBmeHY;J&8(gGSK*zS-G#K8CcKt1Rx(qe@WhP|BI z9R~NhRfl!Dt6*o4I;#b=`Ef zmGbDl6g~|q&WOe?Qur3d3&j`_ud$xA`xVD1>R=y(R#A$`Uxd9WUW}AL2y<2& zRA*urhxZf26$D(Xk|*ZIS=<;rQgL4>iQ=)HYwqoF=7(?e(SAnk(=g2CwScItsN3DO z1?B%|_N(ss;NF$94wUxJs|@#bq#OAN&7rW+;SlC*48=T3D)N7f;wvboQYmN4Df~8B z{|X9klHU=tmtu~PkGT3id56zMx0s()SYz%vV?IWW{L%A|O8k{_aBms+u(%Uwjm5P7 zpa!c8YO;o)@NG{}jkN>i410o3_W=yLZvgWES>1DU4~tYi?(oT>7@_Vn#-FLlzxMH< zQEAnfVcbi(`?1{3YNMPz?wYf!t?=HdepgS9`QWLurIgP~%4a>Lb)Px$N*2Bztl~M`WyP7+ zJ?1~3&ko9eKPYF1DUA7Zc8tQfE@QS)nbMEZlS*-T>&2)i_x z!npQnumV=65;5VFDi%~{P06z@#iUbMaZ?%AYx^AZ`Dk<+}z{u z9>#Jx>qBWpo_Q1_?sQ>TW7W#pK!|~RiJ%4>3u>~*?(liyU;4P``R{~rU!<|wkUyt8 zbvm01VS_yn3U{ACH44L5i^=C>im9%@#um}8OvK<`RAcx>7S|IEyhFm}@rts9C+>(i zd_^3OUEC)>O{vaM{`edRcES`Ru3LQ}hO>)gtya!{qL|-%YVYSK_Ko+>g2sa^tk8)#*8oA)ic%<8oicM4n^8UuO?f z9eyA4M^7GqpM&eZ^q*O0#j#I1@QM~X+b>$<%B2{%*m;NH3_aQCp>fLg#jxlPK`1^R6ODUCj2L1co z40aH#COZylW9L9U*pHwVQ_BdS1LX4ssKHKw zn(RAJ8@mSTK~L%}dQxv^+Cw<*?4Y%n52!|G+*P7@ULaan^n^h2sY{Awx$c-nKn%RI z0jrzAVj*m@#-KKOqV2(&LD*ucpmv7OzQt1&*YnU05bt^;Lgaa844z+6mTMgs_ZIMJ z2+T{cQn=!KL2f$h0}A(AK}|Lg)b$((pYZDPI!m+_-dE9C5&5V2q5lIAw$WP(9xN~& zYyJr3AnGQ18iwI{E5*CFiMX#Na&`}6uhtnpzc$#@DmTvNLRhq$Mt4hGBX<$`EGHFb zp*pNF(LSOMxSKNA%jAirxSk`6+Pdp1@)31gPhs~_gENW2-hp_NZTds2s||5haow@} zeGdPw&z=4T+evl!P}RZZgMCbd-PJXtR@cPkFJ{hvH(s=l=+D@b4eH4z^<>wRJ24ji zjEbEqwyjQWYcO$K)$y)=dl1Uf*-<*i-&P6`9%3st0{cF|%XA<`o z6KA&OSrFxlHgPYpI>wc!XgzT^_ypDMpT&rGV{n#m%_0A848Dn>F;v&_ityd@!T#Wy zNkrXnwsh5@+Uj}_?OSTGE1)L(nQALq4AZ(&X%D-?uAIf&9pa9$hqA)GWtumzo`!sf z1fO2P{cVcJr&or2dWFxnIC}`xHBVxUt3)5l6W?`o#o(F?YdWaG0>EmrCN{Kgq*ijj z8j1ibXEC5U!>cNTuBzbvEyUR5?DVgFYTh-)w4Bnq?(qNLEm71b5o)E;adC#>e|0|- zQ@Q-_ex3O5dBWbwEoThZtO>?&`DDbs-9##3y?cFxPg{7O2Ua&wxJv_P)|A)FceDP{ zb?bk;4)E-Tj^)qPHi%|LF-wb7)iM9-ieC7)p;oO9*KAd^{!y!nzEOQY!C)evKaO`j zv%@yg$n&4&`QOoV{yXyIEFD?~_K-BQ;h8e&?QU0De{8MUPcRjyRDU$yMN4MT*{KfK zJUik!pnFdfo|$f`F#JC$70#;~&90p8{MUS5lSkH}q@zjQ*9h^holvpLi2ETTEar9* zBf{d!PQ;WzZaRAc6z-XTn(TGTUtERZbJ#z!Vp`WV-4^l}`k`AGN1W^WRFwGV^#w|c zJvfL3ncZC7nl+=Qno^i?;=SARnQk*IlO=9Bc45BPy&h5hI?$ z2v7HsD31D0AAJJmQwvmMSR!YB6vh}%F}jR#_x#sk*Y#kv=f4w!^@mYUH4%5PaRiB( z7OqWbvWt+x?-LbF?(Sqbj_UZdH$JM?$7v$y8Z8&2}K*;ea5@H zRh&U_jzrI?*8gATL$NN4Q7^`b7&U*UNBtR}|82caw5OO|o6<}xv@L~E;Yl%t@80+B zZvEfWGet|H!ryrf!x>V{rFdW36&53XD(zmnQQHb15nsLYz*H><<^=szb*foB@cAf^TD z#9D!^73<0Fh5vVg|GL0`J-{y${{JxjH;g^P_G*v9e^cl`Cz}fYp9;1LX7CF5|5I?1 zpMw9-WFy%uC}kFeXF+%|dk4Pf6~k)7Uu#!#{6)0Iq%VQSvR6spBHcu~jr2p(eWXV~ zGxVtw^VCT>VT<+LNkbzR>xGj>gN~duA>t*yd{POd zS~=+n(Djp^1>HPpF~o0|@hc$){&pU8|0Hh>!>1s8X3}>NZ|OfwY7FI~Zqhe;-H6ym zis2-7lWp|69WkEYgmR%)#n*h&AuW98MGq?uk1W>f7msrm>xsqD5N=hR#4xH_fgBIvq8n#kw>W9Q1)=~IR8kk zy!hcrY{_iywy(^%Ux$S31p3@H&CqP+aJH7(pOBB9Uyf!k~z`FH-8fJqo zY4VrI9`L2p?U9k%%*h8p;haXcHUf{^aCQQTcS<^XZJ|Ln#d-u_b3j-DKw`FJf6#dY+N}*wUzx z#`|4YMvXVdJZ41|8~DpSWnhhEq4aBkWqMWdG3Ze*J@!WUHip0Ax{cvC62}{#fPW=< z4uvnwu;|e+YJ#FCK#B1X#$Ta`gkP;F;6veSs|An>!zFY^N~q1tAyr=VEE;Rr+9RU( zQ7ZIV6kWm^WGsq))d(&*&lo6*1I zSI~lzaDK84r^=CL9zYE!`aN`W%`DRV}ow8aV1ZI zXDR4g`mBhF^+gJ*dt zo!?^p%aXYII1(QFMS?w59tp7;!$dm+@rQ!EAUuF2!sP^omsO_HZS@Y=We({j1C3v2havS11NAH68 zoap{us6RrU!znzR!jmXGiNcGc&w%H;=nJ6RqLUzp&#Bz=6s{G6v&xqxmjY35HZ0a} zPGNDyx-pf-wP!uS+MX3b4U^fckxe`+HT=@)cr9vbK-@^P@zex1-rUnREN;A(H8nDB zhKb*t#rod^)42;X7_!XevK)8QG zEX!gY5|TiplKi|ew~NkXwkr}=5Oe+16t3~qs8OCP=v=R$v%i97k`=5|#$O^G6z^a= zrbacwJR3D~&`4iPBmG?(>F=_=Q>*H(pdP-K#;*gunLM_EgZjofnwhajVXwg7lsRHd z2`g*#l8NDB=o_;eZGvCnU)1PTIGb2oBcZz&&MF1`Er==LIF1VVCNsL!5x*Jg5C)2~ zWgZ=A9vx#I%PPG$eg?-D%Y%Lu>h~ecpV{#rYE{MA;E(faLs(_XyvD<9IXr%!KA?0$ zyxqXL9eZpn+edoDEGf_Ea8ubouN9%_x3Ah+M*U(&vBVOLs zmrYid#EzJLWuqdGm<>UT^%t5%LwMHIOMyqsj%E2Uf})Z_y^A=07pqwBRkk*AJhWIW z8?QZ3);nRmxui+|gz?&=WjMcOc^5&rylg}Q_LKa;GO&(?n5V&dla6k@_CZ;Bg58EK z@3b8$OJGjhucZD@U^t$%7wKTq@ua1s&ylVp-AQ_s^b)Bx4RfeN+JdwPXqI;0w1o-9 z^kv?WW}06D8)=TG_)Zz0J4TvMKzOA2ENG~0BZYU8?j;@A6623T_#mBygVaBZ8GbwQ zAk9JtsecwT`qnRftM?$yOT`SosE8{QfpEk znux3UH*puJzg?v~FTi+7PP#>FoT1^$XlOWIuCjLJRdp{=O|G)8 z^2HrjZ-~LxcADRo=O$;^u9lzlJE!$ctsi&}W`mP{SvLPCaSsEld}N+2%A&=wRG~$ zllDV6r{XKn!4(%;#=x|3;S4X}wlWp-t{>l}2rn zM!($^YI~#tdwx0SNOL~v^Q5aO{$0{-6!Q^;! z_8hTv22TUGHX(2oO8`lVBw zq{H#D=pJyqLD79_MD+MS)V+C}+(nr`Ufq+P=>d`uLx6~o$q6AOBohe1BqTlElcZrT zW+sF{py}!EnKbF?Zn}Gt84dyQAbxHX`t43XcRaa455Aa~cYZqNzbypW$#nn|5 zSN%qJfA9D6RDF(~3Ft2V@k?G)$5T(;Pd)WKPgQ+ddYuwFq2{t~b0T`rE7uz84m&qf zcNo~5l95cw=%s{0ejv5%l`@}>ec_cK+Hz0i8?XF0+@HMi(_4NJBdy*8viQQ5r&>>k zJ2i{^c`rtO<>I|)!;vj{8S~$@Zn|~O1$k*hq%C&bh6}iguZWhUCH#Ptc884i9Wpx)$geZrAtQ5# zjMW49ZN=h(Y?S(MHcFm^a69Qw+O4jcaJ=$l(^-8vO{bIZwd#uIODS$60E z+{`Op0(a*tUIF*4L$8K=?xDYcd%>Z+(vM(mqp^uPZ zq>m3OKZ#8p`eEXHfiI36KD5@{jlTcz%)5og4$u1Np}o-iUYD5Lb$HfS5KagterM;l zGfcW|_H7HgE^b?STgQTn+cw;GY4mQP!*>ZCen4n%PaAcI4+u@ZOZs(Br1!S9CW~^; zfO{Fj-;V9OZSU-RB2x$#1%7ze-`w`5u4~%9blYEc-Q4ovj(=;rTh`s7mT%qmZ*8B! zH(K)X&zR$G@1OM<^re5+o#@4Gqx^FJ{oD3iB{ z-SIDg@Y~UQX5GB$Ka!6Kr9CF@JDk4gA38z%icE?nqwp}p@) z-tP*|cLn}+`R(c_Bflv;aN3g*{({Gok!>gbY}PZ8t4F_f+A{+AJ?3lA(kGGkK|q)q zH^-UFVBb34WNt^U?{15m$IPL4+_hmW$T-|j%g8(usUiHu$U(S|MXrbYwaCqIACJ5O?zbYh!~JgL zwQx5^FF$sU*&MwJ?zZUd$D-F!j@8a6N1!LlHV*&?y%zUUf$xp7^{y6<$xj967lQMQ;QY3Q?f-oXXUELq?97_QS%}Z#EF3?J<8#6+ zmVELomi(ewEV*MAb1j?2TxUqGvu3evYiDsz&zZ$J-8hT2ZbtEA+-l)O($E=g)bS~4m4*9+t(!GD?H-zxZb2>$B@^G$+zw_v_Q zFyAYX4+!LbfqYormRyer&KCvpnBaU(a2}WPza`~=S9FJZw(;rJue=0rw zh4l0p>FIB!r@xn;niy$#R*b7V9wQAO7vsDfA0rK)5F-tr9D4=a7sW`!9Wl<=ve+m_ z?2OocxM#(xaM#8r;GPq^7VgH_jc_-|K7u*g7JC`OsTldj&e$P@2V$JH;TUJ_(ims$ z`!UYulLG&-z<(<6U&J_@&%`*Jzm1Uwejnp(npV!{tX9ruyp^+gTq|kg_*T-!39X#X zlUq5PFKXp%cC@mO%UapTGg{flvs&55wXN*qIj!vD##Z)mb1VC}t(ARDwX%;pTiM5+ zR`zkAm3?X0ER zepei?uG_h0zYlkgd9wYNr>?;_WZ!BA()5op*LBl>p*bx6?WSV|uvucKGWN05r5ze`nk4C z&Pc<*uI=GPhr}OSN&gm<_b~j6=A6Bb{?MGQ>mG$)Z>z3+%BIu5y{%&f{kyFHR+PUo zruoy>F9!Ufwqe-oH2tvk+i_Q$?WZs8gP&_#boNU4*R_qUOj|!kf9`1;=-)DTjrglt zKf2)-#M!=do2?f<^A&BJKI4Z1KKpmrrqgHo!|*vTk6Ji=!k@74r)-=)^S5AO68{$X zpD+N9OG5Y&ll@)efKK&}TaRBXi1~OKti}iQn8w zpLq0%m$d0=_#6lNOsC&6w_`=lrWY-oKH>DG|L~8@d2Qz{@HxJR;4?q{{cR6+(myii zeVzB(^urSWY$tu<(ce$Hv+0jY`agHlXFC1;Z9nOJ!lpkZ>A&iv&vg3rw)py%EICjx1R8>t@H_h7(VkInh!Ym^I_{>wF-Qsb?u7ppRfM5O(^%6!>i=0 z)bN)L8gmM?nn$b;QMsyF#gbr{5ut|)qLZ)U!UJ%md}3irWSL}?ALCNK(8|9 zHRhX(ez$0L$AukxIzH6#g^ura{Ia8M@p+5)EWUd2_~JJ${?g)qU;NX>&n%w3HKBemR-IqyR5jZw(R<4cPu-+>_f}`ZrQ`j{(jk4m;GSbFP24@pSZkZ z`P${1mJcnzVtIb~)bd-Gzh?Oxm#zcte6Kft?^P@E_ zXUEUpv-Xa)f3^0X*8XJef_0~^tE_wFx_KKeIfs;Ks)`KDjY|{;unfU=l}5h7i~Ic(@!_OaPx~dU%ENJxwLs=^Ua&TvgPS53ocl5!CNj^x^?^3 z(XEZGH*LLj>l?Qw6IUk2689&*p7`g)_Y=QPv~(TQ^`fpdT^Dv`x+c1A>3Ub!`??bt3bOFffn?|uR9=d6eJd_MH&3vrVJzr%Az3hrYo^Kg$pvjlhNnVkKb z&cx+*^Vu`M4R?Ii_u$4miTOk)F@MI7_P|C#%p;w|jI1Z-6Pr(j`}55&g!}!jWsqcU zK7%g9QPkan8$+#d+wkU=w^rtwGjOM5jah+vDeFzioMWoExpFOTtXywW<_6qaxf!=s zUW&Hf0*sfLUh^v4UU|LgH*YW%^Cn=w1(xo&nwq&AR)BkOo8_J60HnR^%)3#-dr`uD z<|XC<+-mtKN_q&lTK*0yFdE&{CN`8Ohi{Ku262m8) z#PA|<&pxRG;q%1};-?q(Lk8F*?%2X1gs+qEZQ{ON+z*QTcj9UZ(`$KrA%B%l>-wRD zwZ_B}wyk#w+f(j%DfYj;OKydG^)au4JGSI?a4$XfO>k>V-UhdPEce`(EO{^7*DPV1 zA6nLq-Qv*Fxp2R@jHP{B+#ibjw7AE27Qmqvb+VR~oy2*uxZUFR3H%CiOPwt9C7t_$ z|FX_1+}81eT%2N$ev@L}NcRnZ9MgRZ+#TJ79PVam`?t59V9XUe8UBmo*#3PxKLki zrj+x+JuD~aetAz0tR#O~5pL-+Qo;doZxpxv@^=9qbZ75n3EHZ=_AWfdn78lkfE&H? zYPj>SWG@z7$sVnea6;URue=7SnJce_`<^S`2lsI;K9e62P3$t0Q=r?fNV9h0r^B^4j>de>7;Y5zGUg$? zE&2k$x5CA{UNaxzMDzr}yWmE_hZg|S9X%0{?Qo;!ljbBqc0^AGWG7sF%L-?fadTnx zg@9ZHH)=iwsU>dyJ^CU*egrpaK8+pXc=MC!X@EZkH)=j(79qT~r33J7aHHn4W--F= zZCL{Nd*I@`N@gh_A81(y$ot_&!S9#D{hT=+?&r-)xL+`<;C|7phWn^F8}8rZu1OSf z{Cc>L;Ra>Yd>K1Y)O-bdC4MO)vI)CaLEN#(7C=VfMoclX72$nwBW663K)57sIg$jV z0yhc^Z8zL&B0J#LB5A^0;D1COC!C2-y-hIBmIEC3~t2S6}cGU*NOX<$PgfJ zg&T$Cb{E2LgBvw}8QG2S+u=rG%iV+UJ#b;wj9iZJUy1v<$Q6J*BJK|&8Nh!S$pZ4E zxId2M5Pm9B0Q?V;F@%3F?te#$fcy{KD3;KEgd^g%M8^S%!i|_%w1V&~xDnG9y$0b{ zapTcC!tK!sxW_~f!aWXWW>GUcdL7(3(Hr2-jot|N1e~5m&4TDHa8HcB9PUZDaT+xz zM-RbW7`+|t3!|@sdrI^*a9D*9zfnC?pvbw0{&*W5p#F+uMmDKT)a1mz6asA ziTie(%tg#Q#C>P<{ea&C7vCz2{x!n)iu+g5`v7^jxbKZV0Qh^vJskZI;O~QrZ{J2g zg7636M$KPGKZ@`N#l0VAJW+F>xDP}>0r=mD`{C#(0soM=ABlbn@V^!JW6{q5{!wus zj6Mwb$KgiJC!(K2_#tusF8T#PJ}K^}qK^XpX>mUr{Sx4x5%=NfmjQo7+|Nh93i#*X zMquUsI>KKN_tEG-0`m88u~MSnK=?7ZSSiteLij6i@kO`jw-NqNaeop04j?}l_vz^O z0RN@9&qV(f@L!4h-_ai+{6Enr;6_@02shgDBe*RsPr+T(@*i+JT7Cxi^p>B)J)`Am zxGP(J1$RTsui>88@*B7VEx&_1(Q*W}91wT1Cx+ zr7iGapO3-)U`rbye=Y8pTiOBn3f!pqYRj<*e+_OF_giNp{14(j-ZB@Ee-!tdE%N~X zCvm^sG9U17!Ht;jv@AgQpT+%d%SnKI4{p@_OUpup{}nD??6sT%_lcHM;Xc{22<{JC z7Q_8j%Tl<{v@8eaui-|`f3=*B@NeK^9nD$^cmAwZa8H=E8t#HwXA=@zM@Vcv+=a1o z;hq-56%W%9J0I@i*d~;)1TJ3j#PLar3du0nfpWn9Z08#TX(-H7nh;{Lzb&4Bz)+#|7D0RO$X zC$zpC@cH5{XniHZldXr~UfX&*-0NCj1^4x>uZf&*UfbFNjpB^iG4tlzesbF}*bf() z#b)-r6X*T+q6LdTwD@a_f4BHIOO9K*WNCWo;L?$$KUsS5ihntC!>VnoUU1gW&-$;k z9$kIan(;NKtvzFHVr~E0|2o%fXy5Sk#{b#4>iq5J|6x<>=HoZNZ%gcg`~}qurY?BJ z1u_{6EFt zAIB91pw=toZf#_2N&&-z@&Y_(#N_ihoi3>*C)Q|AzQ8;@=pb)6ep5 zjxQ7cmUv41m&dOV|CRCU#6J{&t@yXc-y{C3;-3`%HSuqVe`oyH;@=ftIKcAW5Z@sF z8{?OX|K|8L^rLT$zgqma#qSaS?eR~De^2}|@$ZfQNc_KwM=mD*d*Y{xe>lEL{P)KP z;m?Zxb-X0;`{K8X|3Lg6@jn!QNc@k)za;)gS>&1UKo)rIc@!jHoAzl^#(fG~ce<}VK;(s~*Uh%&ge@OhVTmK*9|0?lsSpT2m ztwXHm+wqgd|4#f&@xK?}A^yL{^Wy&?j;s8@dm{b{@qZYX&5EPh-2e~aJVK7SYMIktVZ__N#7;?Hf*i$AY@O8oilcZ$ED{axap)c&CO z3){ae{weK0fIlmGYWorK7q!p5gz?4gE8v^x()P{bFK^!|{^{+Ph`+LZT>Mq-H;ccz z{SD%u-TsH$m~Wl+*IWPG_U}phdF{Uv|NQpYZsKifUnKsP_Vwa#ZSNL8(LN}Cvb`vN zcl%A^?`Z!^@zd=e6#t_3FNojU{!Q`w+y71ci`#!A{!sg|I8ry!UG0m+-`&1Z{5|a# zi+_3hsQ6d39}qv&{zmxwHX59r&$B4Kg+KQXyB^LXnqjBF^3V)> zA8ZfJu7`{!z1%_|e@EZ|cZk9o6KgVo>?PxpfMmz9# zu^BLf_#49CF#dMo?-Km&#^0s*+k?N$@OL@>_Tujf{9TE^4F0adUlxBO_{-rhkG}%` zM)5a>zkT>C;_qtw?Z;mUf8+Qoh;3- zNNH-QGEvJF()mQAQ7ev2Gzv3hXhI$?ju(a++3{*1j}+Wf8B1nMrIBoIztO6amGXf? ztzlzb**c0B)b-BK>>A#_Zi9!A+dok?X~h}J?JJCDyC)lka=ln7*DX?iwNTz(%8u2$ z%M;@khI-0{Tmx8=;zLJ^WBt`I=JHK z=9&=)D>~v$sD5qImF5Ps@GwkUF$1zxIs?25(>zi2s%@%J#x79i@Km*60&z*#PWof* zS0%}o4*anns8mYR#$14OE}ke%IQsJQ41uo8V{V4ojKt_@v0Q9SO)E(nA`R7f#hNK> zuhhn~4L64uVzrdBB~ELA`rM>fCW4gKJz2)dhFT1sxDqxTb z7{+=dTlV_jJ((+1N!Ydl-L+b!7HI4CY_3tMxslyIQI>w1#MoG^Fow}&D{NMm*ga`n zFwj$vtaK)}7cuHhup|gy78#bU4Y2^37Z1{1&QTl*}7Zs-L z03nnvk5&wPP#HQ1R_Bwgw$XvY%L-82;od?c%l@-%%Bwh8jbj8RL;AR2E0&4e}SDnP^ealpgVv{1?~`Dp5Y1_sEyLy%+#+bVFO#A8JEq?iymlX zM?#TIZlYGN)I1ofE=*?7Q}i&)%3ML3P^n=Rj7&8_ee}#kJv&xtN-mNhnl}KQ{N|Yo zL6vVh(4fWbE|-e+hD@tvdpe5_Pj*erV1v`3wO*1fdHhbM6UnxJ{fbj;H-ZJXV*6RDRZj%TVU{{4wjxAFneU*wEF3mvN^;q2WmXnth zYFRKk+W^gF!OzxbKj&5JW{|Vi>?o8AwPNll#Ujr*R%@+P9I=^=&#`(ZN{wPJTW_SW zipXkB|H#!~GbW8CUaiz+E`$pP1j0}oY_C%z3{XT$g9DTclFAXB<1Cnz;CP^%m$Vga}vi|Gf7xq^cmSzWRt0oh~Dfw12d6c=Q|wyUlk zX{^~=rE1Hsn`EuXnJT%Jt*s6eP{$y6+@P=0D2@VMH(kZ`YZg?G8i$$D#V~GbxEY(e zmGI42p^2EFY%Gemq@1P}yHF=|mm8ey~sn?LkLC*xRCIFR*Cc<-854 zykfRnB>^%<7Fiv1qEu38s~N!wHU?x+U@NfC6(_r^mE1nlUn)R$sz64={wJVB{lbY- zF0d_TVrU}$j!F;*JGE5HaMbW5u0RjkXof2`&X^Y|)5T$tIgzCK!-BD;b95&ca$xs!G()1M$Y9Os( zZ?(9#?k+a=1%O=;%M01Eh^CgSaWaQ1vam8)D~UHM4L}784HO~QWC&_h@*|R@z~PFD z9z)QgFszc)sN_T(sT1bV`nU>;xq(_CSETOfBg^_I=Bi#wQ+mN|m_nt} z&?!_QH`za!>CSXtn(Q7JPWSf-m${@+lerlKU$SA$+X#eBLVB>5rOS0#4^+$~EV(aR z9z)j|R(W7oy^s$?cNWL?9mMk1BKi-O9g{6I6raNLMBP|X)5#S3CK~z5!7|2AL|<`K z{KXKG;Z!CX9B;NsR34KAS=U7KOjfYps18~yaK|!3jY1VQ)C&!h%tFg3nJ%s)rwlQY zvBN20jP&|W!O83jgmnT0gJ4XCgoXV`sH;>NQJ6Ow0+)G|knCI1K*f`|ke;8M7DYhU zm7;1`&@||gp+-rY)VZJo1T**7ije=ar9eisD?0*_J^&J-Fc5cI5r;WmI%p6!dLkb0gzWs)|EG&>ADQ2 zYEWpIQ#eJV@@AA-U7Dv_T3KBaph$}}<7>h?)ShDOBzqJklO$`_YnTu6$H9kry$yl1 zk3PutHUQx~s<}Z(NrScqjVQ5eSgY~EC||=eLK>7hbg-=Gt-@!)#R|C+R!C5!2CEFh zyfMYX>#1b(LI=Vn!Z9Q}5>fesMu<9B9Rvz7NK8+r(%xIBt7gM-uGbGj^E1j-yeNwH ztuZ^n4#`JV$8|BxChcc74We7nDpvr*Qk~Z!pk7ZfO4rk{J&9ln&PB=*Z3x?`s!MTWB72Vu8!%TcG8~j%M8x*w9uX87sv!MO|*+f+0*cpg%Ol zFX`lra&>tcM!L=+fNVqSg4;pDyGQfR;dYI{j-f$+xA1q0zyJ?G)+**;@&S$3i(^pD zTz&oy2RnkvjAAB)rNK^6kgXt7h2Z0`Gb1!FV*=EmZF->SLsZL*+8v>8tUaS{Ld!+> zIfxP=L);klKHc|S`O_eQT~skWVc$n3LqfCr#hRxzVS!Uo2^MQXq5Kv$Ljj!EVlFVu zQe6P(54fUYVJSAF*p?OAv^h)uA-6@3R&ZQ_1qIQr3RYsUPC{`cac?6WI)TT?hbub^ zli57P!SQU#Qm57yWC~JMc!f3(e|YFaF+1!{L$1-L(P|p%=3$MsYYd{1o*0xkrJg+qVD!PKhjqT?;(Aa&{ow~VKe-)i9TjGE-$1Tq966_;j#%h zNgw>`00dWPy;;~G$|`BF^e_Ys@EDu04M?-k2BF|p$Dr?k;0N=X#D=iq_D}81*0F1F z0YU3&_|^lcz14KRqGC%=;Xnajj8DPJoRcPba-D*7S%`EeEn^q3LL1;*I?`@6QOOfs zmR(Ae^EaW z70v)?DBZWCr+awkV0R+bl+?ScXE;4$%24-UI?Eijt|X2X}fA#qqLvBS|-*q1#}gay`~1cwaQ z7Ut4iPEH-QW*fIy*k|?F(Z*?{%Bqb+$t~}b7n?W@C_R}*s?wWjP_g<$zxUUN3wyKe zO-5jtgM%`yeifjD%S1X^IVd8Z(5>t{iE6bpwP`&n5ivuFl7WEm!mzB?$F0Sd%XHIG+tSwlyMYf1YW0I1Q*0g}jG zs*KTsEGB$b(F|iX&9DI85G7qXZVDj!Kw@4zQEA}l0;QtiGrR%Ue<1AiN zu{3$E%wpUO*kSSO4fagJwinH9k;xXC5@x45picqmrd3P^qNiTYPY0G^AShgtanqH} zTMMe)WO%(vn;~?nf;zQyiH5~6$}do%Vc-f$XC^&9UdR{0%A4S}3d{1<2t8!)8sXZB z6Ndu#QyggKg3tpwNl`V);X0@YceY9gQ%t*k`e|9a%~=RVe%Dr*lLJxcU!IA@Vl>B{ z=IJGm6~xkS<2b_cY!|K)Q7oE~pnC^F{^svYxwgQ*ifSjJQQe*`meQlW#d;lF#8pFf zEIN+O2|*TQykl27#f-SH_Tc65%0OjS7ai8czqT{J1^YH{6p+?%dUPQAk=+xC%>&OEQDq!-IR|pemax z;%G!J@npucxH?$NLtBJsQT1Z(e6uj>q!)LY5Ym#pR%kLX)$@v6-DLCmj30wwQ#k za7rKK@`a(Cm0ZDHC)-y?pp4#@5w2B|Qu?ZAe_3z^)T zNVZlD2vh1Xm=?^bK_IQ$VSwllBwiQ~c(G89L_+aIJ|BqVEma&R5X zDn%s|Rq!NOhqz5znV*}Z=`RNd2hD4`9^frlUEM&ithFgYt{e>e%)kgBywB_CdPBrP z=Fr-6FACqVEfAt=!?bRMr@(H8Itfm0aQcmlvkq2hnTw0c6k&j|L(1kbZfRut+-9elFp}0q!Qa&4<;zZ=$?k1fX5zgSBkcPG9$A6S?sL%e`RDr=q-vo8}=ir4mgY#!>MYWdj!{ z4SKOliUpc7Z9!N%(4V|GYvu5J04chuI+oA`3W`+RNpQ}ixABc-ygq=*s@1tP8}m^7 z8~mE$?GVh$g^#l-$Ims!1T0+`lq_5$;)Ze$V%H-hcX(c0i}i2`r%m4jkQ%06YjfL) z&&gyf2{1ixL$PGyPpc?m!l#L!uTL-(Z+9F%TlRx;3p zCkko+tYQ-)55*Cz945-is2&)5GbWk1;KL9sWE{~-BCJLeycQ0 z2cd!Yo~k$iMCYhM_?9g(DY%Tnb)b3TWJHa7R6`}glxb=ZnbtHQFC#njB}Q$a}wslgj?;2U>g+dkg6wnLJ;DF)H9-l0L1WgL#BEWrVKbe zf+=2vDM4kJiNUz$w5qS>v=OF+lwhWY0L1WBVkY}BreXMkYCjR0KtU`q0|apd5X4Zm z)pCv?W+;IO7TLob?RXa1Vr1oEi+xZtPZ`!QWc? zZ5NW2>XcQTMC`F)-HBB3;3<754e{o5D}K4$z@Wh7qAHu&m?We?tXd{RTAGBsx?C)r z=IU{&USYum0S?r%W8+!ui&?zPgoPdN7VxwIYAOs~;wAV9NlPCr6y?fd0#}iyaOYS1 zeMv($Fji%Q?j+y%PmBifA`gR(t+#(aN-j^C^jI0THshUy*9r$PEx6ilFVbUE#P%r~ zu}B2CNmZxH)o@}=-pZqsphoCkT(~?1Em&Su2FrqEVP#Pt6Uw-Y$O`jfKvrJKxpC`* z+)g{?AjAoue-I}OA&wQBt;wA@VF+=;CoRMYLxK%;VKg(`pm5dUO2Wmtqg{96>&b3P z`Su*xgYt+rE0?-N1B12dU>#J1(V@hKgOpNUtqM5VEmUn#z)~LMD@CF%lc?43R>3vE zJ2te&OYg8L)4!2j036C5aR>4-aXJ*DVsVrvZPd;?dWf)_Y>aylfFM+p8bM^G zOcuESw?TPBOW=M`YIH?xFIBR*jZMoaaywsgBaT;Xyrak@Z?04ogqi~Gi{o**ux%rP zCKf7$WS53wIqj9rnxQHhBR3!M^NO(13MPtm2JkVAgS&&naJp`1BVA8*$tK1VcnIcv zDTA7PiCr2hb}{K6GlNS}1^1{)3WNn7_olM6_sFqm3h!|D;XbBEXa0;Gb+)F@lxwrs z-sZZ~td}!HJy6D2n6QM>_9CO+Ayl^)g(9sPo-!Za-E|Uj>`3 zV$~+9cqCUrK2SzYVt8}49Yli5ueiHKDZ@ZqlXoVjd%Vhr<6@h@V;Wo;gZSV*yTp5= zI_x0Wwh)-WHiA23qfq%^Yp@p*%^+Ve0NzO8!W|!X!6e|Wjd8)Ic%=^8zgXmO0lqg| z-!EGLt~oh=%^(;X9%dtR$olAbzXQ6%6A#M)RF(^)bL`!@D@0B*w~!(qg5mXzr=#o3 zxw;Ury>CeE9$l;B4VpYcvumpPl^xyyHY}ic&$*lBdVigkx|MmjDOSnOaoq@?%V6S0pQQcoC*J3h+`x0KXJ3Qz#vq z@i@lCKByB$qs^xhW^ntYP|oY(R#{UM^FjV6a;9`5C)X7u=rBwT@1Ce+848-X`U8s& zjIxTUA_Hz%uv2M$(}yQVvR6a+*M|w2Jl--E%e%_h<*>u&RjqX=O*nb9^nk-l3cP$0 z7{KQUsYO38wYacv%duuSS0JoWO%SzBH36~QJlaDzD52shq&CD})!+upYaBEnsnJ(_ z2b6KG8%q7^dI`=Z49+5x%LNUN2>C%@@Im(R!j+M$bx~#N^14+Ef%(c^t&>^d!^^Cw zyO}Z!Lu%n-$R2F*tO}%zMXrb5v|kI2$*Uhh*Qw$TE>Wfi4-K@X0+nNPmcT6G^1N!K zRZI^>$=#C98B}`xqR=?;2!*@q?5tMZ#3)CfD35SI=5Ays$lZN`p;I-JbbWhq5@+&!oWeGz z>r^J?&W3ao>wA!I5<&31zO3~iqWiH*;9%bktUXe2bqXJ!V2?!r+7Y;Nrexhe3a&{b zZUSFp2&V2TkAM~P-nBO%SPAt|dxLEaw39f}M(&}W@ao;*SJpLAE`wzAfx?yONm^k1 zGH}v4L>iE)<+u;+*Moq1s9|z_K2Q=j5icsE$b|@2AVwNUIqWJyD6}adQ^FonvLhe7 zZw}MAIU$M^l$c<7bsTB>WeSG7 z`$FNArZEaH4(8vb85rzOb`K5V6>MTKxf8e2lf%0PyG5e!DUQ@|nFz9qr~$#xRCtGV zGo;x={~?@N=k}qQeqCq)8{z}7GImw%D9g|R1CrJB;bPle_XH6qJybfhWhlY>1PY1V z=e8mdWQr8J@hJ`WZIztt1Hy!oy#}og6JU(~h1K-|oWu z)@SWS0OjcAhyd}d#rPP{QVN9BqxFLV>zH7ta&X_=~e8EG0^TVW>=yJVKT=`^eZ z@)U?QK11LXAmT1DQk@!j3glEz?z z@FH1ewRpioO21@AfDv~;jPQT?YS@ceb63Of!TP)OpO%QlEuTxG9EZfw$}|jVFs5)?f~6WQ zy}3hyiFJeTgCL{H-SnhCYV z!kVhEP;7ks4w5ClAP}A8Eryv=8kNcjjC(Vtl`B{P%}LVIW+1-yS(&M!!EW0Ig-O-| zLquy~A+in5ms+k|i)E3iDA3$08IZvI1PTs7ak>!57>tp}W!(iTe`F`*LUCpvzl-2n z0nUcoP+?d@E<*Vj6zg$m8-~v&Sa6hbBK>DdF#I{JnpG{rrRPWN<#G=XkQz?ND1$2F z3Z{%g^`PMA!OE0nMA>rn;Od&sc8^jL_8bn0`!a!_7268TxM+Y7E$IygFH3NkhY$hE zCPeIM3AI|i;SY3h5ZHc@v3>`_6>KFF>TO`=)FAgYbu}$Q&yO-;R!uI z;gJb_a&a7opXJ7=mpiB2MbABHCusg)qdgII;G$FitMV+D4uXP#uQBqnQgIl@eO&1RH5!a+&cGshAT4LZ72d$ZM^s^j)bBlJ1K~2xh~&$M zSufzH>W2@D`AJ-vHSl04H|0VBAKTiF{Wh%t9M7--=EA+Pyunj?oLb@JFImBXKJF-3 z<*ZW8q{s2$tQ=ZnziMDpNG|-)0GI}ZT0g{>sNVYum4NEVsv-R>VhzUtUL2PSojR9;nOeXY;bmgr32-3$X+Fr<(38 zf?B8cnI$#d>gLgV8Q+A~3orV8%rdWtG;k=xhjF0VKpMLd`fz3_f+J1kkwb+BZBPb2 z%K|YWl!mCG9`+vu^o)cd5F$1Z7oeu^MeG@nOOt~o`A#L2a0)m`xD0!M3tuAN?5wJX z4)8P6+QdYT`Zz8i;w+eVuxZJHwE>M9014t!9xsbnW0$=;f|zbP7(mXOcZ&gWb_Sl* z>!Zu%1X#9q$O5emL)0@psFs2LnoD(%Aex`rD+gRTZ*6&3FwxjI3a0+5K!-(gNfN&6Eg&`h?kr4{z5J)J8K>Xph0~Q=03EQsC z-1z23hMVKXq$-lDrPJYx4HWfzu{zrFomhNBO?(*^8@6AS?YB|o{^t0wQ8-DkpD$w`(5HPY>Nl%`z5ghhxmx! zPPGQZ6-JKH(00{a04)G>@haE#s;w0spsz7>aa#b4eo#QTc)jA}@_;MSqDc>RGsZ!+ z-T>zJgRpw|Vh(qL>hd*b<~96mv)w=SE6q4g^v(<2*5sLL!658cxp1eMIwx(+_j9M@d82U0ATU3*sUp?CcuF%m)jkxMN#1 z4eVMZg&FRO8X{$B$YE#&LUJ}J>7;<>xSb41_n40&5#1&$z)MG?c|OdObBHXC*tHFo z@?E-ttSvp&Ma#oa3Ip}N$}n$Z32&GNWFGfrAU~f6Y0f(>0VD2lSlJMQ0B{ArOleEF z5yEZQB(GR6-G^8)UQda=#V&f#wBCfua&7mpaE1}A%F?-?902&$D>?EO%mLiE_lV0K zf{*J*x~F5w6e;0NPt-})REWY5j47$f(T{BegkcM%Ol^b16>vw5hM++fX_G-WkZkc) zeLpt^ylF5yx%I7%pWm7{gA83V9h$NClr~4k0q#ehAf}HKPP> z#~NEDw>dij;qtU6Gu)}OA3I;;3d5W8&BGV02{!MK&*fUG!)?Z8mP{40r9Sp4aG{9c zUUfv~U8SfADVR~*4B3xukpUfb`|0dq?x1<>fqc3syRRvWcmRG)ojDkREx}x!H&=UK zRvyXbHH#}iOJb3u@@UR_u12Wa{Av$QHgTz(c{FzwTL{Zm#SaUbmP&rzdw-!&mG58} z=_2V3SCK37ZF6%V_@unSOUo3l-EY;{dlsYerd=#-Vp#$POx&;=V25!I?S?5eQ)} z+z#h|= zgEFov)y1+vTof)yVw_s6(Z{xaZ( zMj;s!o{CGLi0%meU+d_jrICbbg1$hN4kf5IB!i!i z!L_HFJVI6T4%bF4XZGbw2H%hb@zdQxAic#> zsaUtH4xE9%0$`v7`oo!p+HsKC9 z6Cu?sp^FI)a`Oqb6h?efD|~rP10S4ClJs|hbmPO6in6@UR9&#s_}`1DCScJ|T8>i% zjS1PpI_VKECtNNegGXa=bHRguSI{60BGp#lLYS zWXfC^P>BC}fyJFol)R6$PCNh^At;)c$gR*60#y-{07 zAp}IzsJWwN*=CVNt?#CK0C)#Fz0F%HhmJ`W(inkgpnS_N5=-3Rj!q+%HjrgXMlUAw zt-AuRSQh;Ynvf&xPdwBi(7Dy81qZJg>Sr8k;*|H2h_-D!8xtemKNi_gSFl2o8Q8>otWE2V!HcPWM{8)Q~)VWED#PI?e}nak-DG_@S}~ zC}tyDS*B=J#jLJF*i-VBxKmS(Pk7SViuXWrh3X3h-R+s!^_B`|AY|h z2JHX?#5s>WM)E;=cvP2j4!f;29cS1lT)WCyr}!$B^_TI}Z4=e1d`Snp5$R3n6!eW% z5I*DpqtcQ0emf0Hjr=+mMWebY6?yz6zp92=wLAz1O=D##vMAsBgEFeebRs|Tci%7@ zPCHipNh;arUNO33DeQRAgVxv;OCfKVliKh;UghuN?jGcDv4NlI@qS^{fm1lNs}5B2 zrp^-sYoj)#ES7iO!Lx8ptZvK0Z?|~e?JG=xVoIQ6kw)u1xYad*z0=2-R=TAzJlzyw zlspgThsEqjQGXf>r@dfkegWv891oRqcpr>8w*?OIy{r7vr40S;HkVE?>=@qf zyxO_-5#11zAxulOm8FVVNL4C4r3xbxV`F3kei;e_y->g6aS(@4CInr}PD&`yHv98g zL_?Bx+%L=v$&&M8{tu!lO~OoFhSZP2_N?6l{IS78&Cfy(f>vP&c^Jo`-hp#7EF|5m z8M3BnwXEs(jtL*YCP^zMB$|vIopGey571F;maMdA;F+E7qu?kaA^Dp$@}`Oh^hb(V z&ZIpqMtBH^oSbGh2~qilH+&wIVO(6tk4ONHAGp$zS2KGqQ9w+nFmrpqJtY9x$Wzunq6}9A7uM?)BoK#WKSTwF zjkCW=bkWEI%h4(Mz=VLM8P=*JdC_HUFpf;Xe}=#uj2j_A9u|`cE4A6&`7}XNu)H{x zjjMk&fydv1i&v<)*FG@(>rFgq5rD zB5+%Pgx$MW{q-6U52UeO>cPeMF=9QQKBFlp5;L7H!*&7Q4bsAg0_<ZW&P{c7Z%=fecY|G~1w7@2Y>7Dz{803=Wx7qQo!qb%|2ofIz0TNG zOR2(2Gj#ItAcMH=I)(+yNw=AB1n@bC}4&B-*SQ3@MG`C`kuwda^{!#8Xk^&7skP~uU$>xaCr zwasQR`UY4h-#+Z!fseprm5zpZd5L!N!*;@v{Z?oUtEml*#mQ0+wFreljEj*f=hPN+xZH7ZV4!9XAp&D#6Ren?1>`1!#vjGtl<$#87XmD~iKy@Q;tEJFV7cbZtPSg1SU0F9aKUF@p zHQDlD7G|+-${~8hXVG-)#<~{b1)Ik^dhP-A`bS{>g2wC*F-Xc|`9YSW+e4^GYhu)| zpolpPTbeu=sNu^a2#1CX4ZsB@c_eG~D)oH29iX*s2Xq0*iPRoA53v7tdzb5-AStQ^ zK8_$iZe)K4i;s`JUZ5i0JlLtgL2q3g^Vv$-R*GEpZVC z@L`#wq_7)cJJKbvH*~w!v~zTJ=CO0Yo}Ce9SI{qx^1+m}0h%KyhGgi0bP5L59)kC1 z49Rf=&C(W34@vkfOPniaEt$bS#356$8DA|5exKdz5SmIYM5tFS-&R+W(Pl{@s1@X= zquT`iavnBK%ulT{QSF-YtlPeI+12Sogp9->z#EccrcRgbw{IZYp%-W*#N_?>@mo^|WR1pt|M z*#Sfpgjo$7H1La~7Qk2kI2o03u&XV|)%4pL_-%VZ2r+nB00*sq*uzS@jVdsiooHK{_LPDi7VevrQ8JB z-BX(!MaZ7uqe;|md1CBl=j^@#b0LoU-F^sJ%>^-7DA)cFh2+AoXO~I0a*}LiD6A0h zYbT}-S44@0t(sr!fyAnciD-RLVXz|v`cHzQMZ_LU2z`O+;7G$`Kr-+m`v8|0pP}$l zbfzwgr_jD3I9=aa%)?LxXio*Y0ESEUeN_~TIdU^8%oAKf#)c*X$eICM73U}YVJ9)p z>fyuufpuvKRl6~Is$F#9VgN{tC@y;@IU?3)g^{If$Y9 z9!wtgi&Rc4!HH%6sC+=cA5nz%$tQlCQs^0=Xb14f%agx316&>Ts%Tx9VP9Rlgufm~ z(}I4wd4?1avntIL81R>>&7WTTKE6rYV2GKudna6N^;L zLP1>65)p9++oQ;O9-g<0Fj=fqcrgx16uOOHDt7&Hp#)2ZZlqu*+5;)Kf5^!s?iD(I zV1py%qFe&}dC%Q^YN_W6`Zj%y2-lVBntb4qUrwyP=)Tnx-C%JhK#Oa*J7Vc^8?nX> zruc1DizT>Og_qQEv=U78A04>eRUwzi*AFmh*adU`_YMa1l{M6C2voRT>eN%LEqtfI zt}=vh3J9|zx+#1I_b~10xEM`@Tqz%-x1dhk!}X}1+Qo)*cr({C&FL*vYq66%yOvnU zJJ;B88yZ{#{;P&*H$K61&uVQmV9a=pV$H~S^^Ze$*Ny(z9IQN{Hy$L5F(%n(DyCsN zOcsB*;(%))RX}i}h|3Upz%B%=grnK4DI=DGKL!5){1Q?MW{olDPXWgNt4%NduSUMS z88$od|HWn;|6h!f@wqC4%QJ!h7nulj9vpz7tQ!7s>I1*S;984?18?PVF4 zk}Gpd~oX2fk^Wl6IJuDPvmJ853hECdP3zEeN%&1x`ig#LUL^0o0D`D9B@yyD$QH zQDlb9#imEb0irfA{8nT@4F%-Q%1FR|Xxr2W2+j(Px#`Z`CSe9mpGo6y2gsnqL+Stu zr>yEt0ShWh)AQymVDdIjLmGrbX;jN;!gH`dg&lxuRUKxD9f&2s;xLkEf`haUg9K9j z^EWA2sm_dRPPnmb&=NLjb{B?chYZoMF>^Jx%f%(NPlj<1=8CDnYVX3F^qVdT^&`|H zIW^P`>^`Iagi%%Dg0EgZPh+kYRRFLwgE&m}=&^&@k%kC1h?2 zZc<_i);K#QrLiqYJ$Ad)!rW%=4nX?wH;B@J*}enyq(Luc9$luf)M3_mEK5&d1W-mB z35ESrf1{)lvd(Pq!s|_^7v5mbL2ZiNEoHD*;W$c}ABIS2O)x3738tlU>^MJ3+ZV=3 z&Sstqc_ZyXID(h5Cnq_aOOSgIWw<%vi1wl+b1Yqs6~}_J;4u0Cmze<6D{pomMzR+( zFY`B7V+^x>W?r9Zs%JiFqZ=i4fs=Fg(55!d%5ID@=Ur!V2>ID3naTM>G9x{RIT|qY ze3*`<31IouI)w7s78##*uhj@y8k+Ay#7v-`0n8s^edxa}d7g`Ft4I%C4ad3=W_7j; z%Y1q)rvs8)KmD^5{!SIC?r-w)ELc zkoGo!IHP5HIbDw$tTlu0(0qeVFG8y zcFZL0Ol!xCr3Z5!t*t>Em8F2W$hDO+7bUKyIXLBL=@`qio74RH;tV#ooGUa~x;fU5 zo5lVtIXN$!-^^>qFvt23bDnEUPKn%NJSvTzHWgTQGghr?p_ll7snX zZetKbM=WxxYvW9FX%-$W)vRt#@#kgwJema#J2=vjc@FC8HUbIZbUSI6vM^=9G6XS7 z=S7KiSb+<_x&~NQq+v>r9U{q7o~1-;cI4pW(|-t4LRKM-qMd3JMS;#-J~aZboaC^T z{GS`Q11+qhu5c}ox)OhS8Nt@0gn5JDo!le4u#Y9l^%gq)gl(k;fQz2eOS40z=nm=s z7+RAHrMt1fR}s+Ky0lis-SBvtmFx$#8eG-Gh?GzYM|66LW?dF_P?BeP9il7Lz@J_D zoI@3-DO__t%ob`nCH$u@lQa8~P7$1%6iadXpvG&E^{F#b-=IcfmQSC19eK8orAZy@ zrei6+kUrd8g>sxiorD?>wG=811^ltjDd=z<9ky#6{Zp-oI?zF+Qg364)N0uaJZC|! zGJ3~$H@Cu^BR!i1d4^tI$ zs^Vo9yRqkZkOHe1J?hb%L+X`gb#T6P{SiWZwt+qI$Jd-UeT1m1Q*Y;JD1Tr+)zMj} zjLYhbkwMBNSJSnDE5QhxEwl&VbXjt`5pK4zIGWeFbaMvESV^s# z77q5kXs(r3I&Mof*ju+-i8%=zwbE$IU2nOTl@mL zE1-tv9&?;@#!Ro@Kc#iHFDIku){^6Kn(lK-pITg7%}Pzha{$!NF?VZ0*FQO$t}L_Y zAVTDYY$fTH>nf1GMd?xLqj}E??kVIH+=V!bZWc`PkIAR~A?-0QIWoB?W3<+o)j|77 z1~Lrill0Mp5RP6Da~3dQ&%WH6F|MFxpj~Y{2(1g^xxQX!Hlx>Eo%?M6FAyWg8s=R& zbB^n5`8W8O=W<*)iZr57BOegWV2PM(>R1Qdak4W1fgLSkkdJGSHbbr+u1Ys@YUrVU zJAk$fiB8K{!k8<%q^+cPoiUCaXP6v;R72`?HZ5lv9G7&qa4FJgIpHXiZ&3f`9?U+Y z*Eik%{1)#si|b%?V70igj>fRNz6q2K=KuA;2n_6OPLHzW3t)7cq}d`pgxr68cS(R` z<{T6yH0?gRy5~+u1v9yV?Jzl^kXe+@$>)bX+)L{O|g}wy-|*Vm3GP zyo?gaKXLR0$H`W)iuDBr#^5qG%Y(~p4K{5jE^+%?gPLT6JiQK9t;XE~W-WvA@FrK5 z(KuqPfwOGpIkwh^x=Eg9E?F;0HVK?EFkIZjSP(R$deGjK&BwBX4DH!_tV@gnjoM1N z05NKp|L;nB?(sv}7Y_-|DU&*yxX&^F<7NaUo)_GRb@SG3g=5Tv18?N;Hy+Pfk6S5wYW7D+GGkxuV=cd_P?&>D7_gL>ZJJR+N8?G z|GJ)oM=P;ebl^r$!IU(l0(+1@lS`}67MzpQg>GkBb&;W&$D8!&R0vgi{Oz4|NFhnL zU=?J8wV7Rgz&P3};u?Cc9%!GN=xU{FDOZS!cj2*d!oFGMFgvgfb1%_#y+sb@d{yej zW)lvBF2~;$5IeSkKlA9q%-;qYr)WU#XJI%pP^zRbj`y^{C%u!enReaAv39rc7=Q*| znzKpCj3-1@9)ft$VNSQ@osMt(| z^I4NT8pq7r-aOYxqU=R8m+kTRi@C0+uebjLr^;}wCoszUgg=l^P;{h7?Nou_Dq|n0 zYP0VYhRH>zj~<0HHH+LB*8nfNM36g3W@N z$~ET=2UhL$v7DL8QCjb_=L^aRY9R3UQ=ghtRzqo9{*=;Oo4nko>KNjpK4yYag9`ns zXqtu1sTaw7QRQn+3Ff0r=8mg*guzw63pH$)qp@xoUrJIs=H{kD(~n+LNaU$DEpTpX z)T%PmRD_RIeX*CUj%<~Sk0PS9%$!K9&_j&24$=)J+L5i>>UY-+PK3E-$a;RE63XJ zz4l#gK5D%obEJ)qc0RD{n_l^U>x%0bU8QV3yNTQ zl%}=_CmhX0XkhdEpN}!%EI(K4QPQ5P+0R0X(}oxRIfpJmJ^lFxzjXBo-aq=Xk^ z-l*1_Q=9n_1!HFlF}uU5Iyamz_Q_W&*)QdSv_$g87nL8kUvWd{;-yf*6!Nv3pR3?7 zmr}_|O;=&otk=u5VeZP65}UGBF76Q+##nWbJMjvPZhvUbDcov?uvxO9%pFXlH0ocR z3LT~|3a7b4c27dX(Y|)r9uMUDF>HFQ5wv}D;37y6&&hml`e(Z8N5Tp&B$Am}Jx+4O z8`dIB+b;C2h)sOEY+5BqBoe>rl{05(-UD@@-TBQFq=gRrSK-EQaP#?vujH?m=DG8r z>7s6A9&ZK&)g05Z7pAzq2JX#w%_JgGXi=+z&N$~DaSemd`jTj|9&VoQo8QF+RC7Kb`W`dOA5YN0ZiJq zxcP6AvU%8~0$5FM+UcIm7pE~RK{4}B$<0}$Xh!=5DTFg=PVJJ}!lh-v z-7%TB_E!b%mKop&xkv`(`FYGK+ffqfE{)QA5u&ZZj^F%2v|{c1m>iO!pu+FsG|YFyt#1Ub$^}eU1Mn z#><2Tqrrn4(gP1MDUna0cV>0C20h+s#`4Nsz*$zB3aqeI;WD^)D$We!x9~!#*}tyP zi#X}loEJVNA99HqXwk*_<;#a~{leh?_;73%Zm87HN@G^4sfOuX>v%4`KPA4!0 zw^jXLEFRkbpzVbmoLUa&5aQp|^HB?FiWeSq6_Z6$ zOCKsL(GJDkh;*xx$e*j16dY$304V~KYoq3gKgam$5xib~pjBU$DMy*8b^Om!YfxaJ z4Uh9GGkL?Gr#A8|?vNa1JwW#bszB`vdeIJ-q9Pjhfki>+PLxAiB@g9QEPsB~9?BOg znYbM++)m6yTDfxAa1zW%SxP1Pu&HNSNf)n$D)W5)H)p%jR!h0+c1ZZe0hbcwFeJ#x zT&Gs6J>2YmKIWYgAmtxkgW^@AKNt0K%&A+HgcEVZ$?Z|wjn79fnmM3vDqt;?XO3F` z^TOx#%tNJd8acUEDTU~Mk6zBeZMm|PORKc(PAjy%gt;Ay6sr4%UxPEZQl<#XJE*JD zECV_9iduuy3AIl05bg}&+FaRrS+6w8unynK7Hlc%yXofXQ~3OJE&*j#r;egH6$^G( zkDXK@qlV8e|G8Sgfv2Fxn|@9RM16~{_f(e@m>Y?U76*!7Q|5Xo`K~?FQ_bmQja1Vd z4p|hpOfAFN$%xmDg`WVP9+L5m4)3(+YmGEwe2u`PJWU@0g!b$tFnH&GJK}>P%JSWW zh=21Pu797$$lISDS2~yC4>jX{Kdt9G@SpD^09nX-6+>I= z<;Bf^9`mtO;2nDj@^#~_3Bo72a8r(xwEgT0-&zTDVB$SHiU!sEk1 z&d4Ep?{(^i;K#eV`{N zw)A6(Ya3M63?7A5yV{d2kU>H!-L9j3EQo60V{$2$Y|x*+U9j-6z{ z9Qa_Y8>}SALXHmitQe<+@u_+CV@ZjHV=JXvxklXT;6; zv^p2-{DpBsb=mn3V|aDoMnJ#J3b)N^rNg=&O!aaB&h0KK<2vBA&YZ+K&_}a_poom! zGR-`0iM@zBIx(k^K8H~{>t#7yRr>grk0p?q*b8%+S~ zrn@*{oOBXm2iQahmH-!8FG9TB!z)F+*X&>P>A)_{rOt*C$6ZIc0k+O2aVC(H9?bWg35)1 zs=!?l194%uHgG=Za0%+5IWz{GRw;Cse!ermA9t6c6vd~YxFFo+{O13>dGqGYdvE49 zdlXV|6I{b=c%wFC3&>9gNEho8%Mtd4At$3bHs%x?#f`}+{_k}GL# ztLsU`##D=>%m!AxN%&Fv2dK-z0xq^TV$HE$#Wa*V@r%>JJE2W)SF=&Gk?QL-><$=9 zTGQeg9eQI?-Q@gYkso9{LgD5bbxJyQGEwz2C$#;FzvfjL=r7j)V zXD6n1s-zjOoyM+vOv@Jj6OtCZcQ^Bv$l_M7`8cPsu8!2keDbe@RFoIDgC^U7-6%%d zXjEq!>Z{Gv)X2BA_4QEzi4fqziv$ZjGePq7; ztAWf2bs%zsQ@X@{_A`ymmLsrg$GqL@9HCI^v0JJ@_-&DTtZP*yJ+5J4$dFnp^`hx< zklY{-u$)MStTX7<`Z;Upn55XW7THyniQytj(e)EzvhMl=hP2W=A~$j&Z&;e!qI187 zo(Yyn(QlZK2}@#YcI(QJsbi+jT2*I#lA2vwv@C;HNOsLKZg+s^FcWBpL_DGC`~`bn zTI8MHvbtjkj57YH_BH1@kqzr9vdFD9Tj?T|W~j`2w5z;_He^aV09$Yed&D!P_D8fN z?SP9ViIpsNzpX`vDs!9SwKpfD#t~aeMk^T%Wc-lup_llltT0kWG*G=KNT=+3o73EG zxb~n`gY1UddDck->giNoSqW6yu=p;($RT!Z@Zb~D!dhYC(PE<2@TrK6pv?N## z^3;pLX1i-gu^JDxeuQ?Kuc9*SoHpigkZb4sEIn>cQ)wyXHqFAVqjc(__6}tpGFybt z`p!o~uSwBb5}AD(Qr;~%MIRb5nO-#V@^gWFNM#bcqD8rplAuKN5ogNNDznGV?{)MW ztB=Uw*PN?K+qiB0n(6{$U8r-j8<8z6Bi&P4np$q+B1vhrTp?5am%qsLzcB*CmFr`( z{J$zVa66GxiDXT5taA;Lx768aGh3;t7S(hsO zNb9tE$)mR!?Titf6mW4@stlu#gZJ~)F!GbsFC|bios7>xw3wLPe1T0BQnqGo& z3y$_O>NaAN6wA_az38TZFl=9JsUJtw5kN6Nej|e#b!1A%cIs~_%inNhs#8!#+K0I% zdf895Yi*fp(<+4i7A-2#ftKhPxr_+3u~D_UBT3QbmB~mhZrt=Tn{_0LAC_7hzcG@a z>$^9mTQ%#DSUqjR_Q)RH;q{Z~*h*s=hdK4nVZhNx2;-KusqR%9Fn-6{l*V#eyoGl= zg5A+3TjOD^NMA5pnvcO~gE2fVbEia=#xW9RMG3;5qbp%ol*U^Xw>0PG7xu{I#31(? zQ@y4rz79k4oXD>ppwYV-YR|s(1q};J&Fx5UkVq5JmoRUIj$3p9Nn6mOR4u;^HEneZ zYV)@I5z4LN%)TnLcIV8rIbmRiV^fh&lpEcP81*OG6cq%~7HGq1 zmx5a7lC^m%T33zQ2o?qy`@Q?2GVSSUuDFrVD@Lx2#3Zc~5^S_Rtz*OPh^@9+-F(Ny zc6>b?)N5&MPa35tN|==)P7tYIQHxH5(##VET)VQ@xYrQtLW{~c%~FTOB)F-z5S#=Jx97=J8JU@7-Ev24 zBQxz0E6g^R)4DBd)={{>EMj#y4L9dGgYp2DNOurUE60Q6+(%9cPpVlvi!y>AU{%)I zEEB7Fw@l~KZa+*~wC-pncbf%vUFJ?K<=3vPHajAJWblq!(q>0J?FjX%4O>G~spiAU zhCAsbmpN=VVrn0-9)w3n>00adTMb;#lnUUnQEiaHBJSO4-YF)2S3qfeIUQVmO+zPTx?DLxiQf2m&Y2jRB!Flv(nN ziH@+%H_USaq?WmQasWoArMjOKvtfW97FPdF^{uOcFP!T@nN~WXZJegxIWqQBi#U&X z-!B&h<8*$Q0UiVagWSm3YY{R4f(oW66uf^d+$l9pL?pEe zs^q0w83nKP3ap4rhs;&>v2eg{Cr0gS^$~qHykl3o{u z_!}L3H}978(3o=%Wt=oHPKx@Xi#eL}m^FrEtz?cd%>#$Cr<)HqYqpM~t+lASSJ2%q z)q2{kTLom8%EJ`$?D3nHov7FM(PMWOqq*NQpCGxv?>-=MuYpJokd&lXaoj~C&6i+E zwm88@sd|NC{jzHh^tsxE9e!+UT1kHYXdGsKYT^JFnl{$QSDG`s@gGsyo6NYxSzz*30W=w58s* z_eFapZFh6dVz(|cI4*9WgNV)yBm-9@DY^OV_>;qzq&wx6!Ab1j$!czl#6cvhO)x4A zS9?_d^^Lk|sQ&Iwgs4bGXcTANlI!lk5dmq{dYornd=(P)S#t{!Vo7wRlWE}%o0dl* zR$U+LuAJ5zF1q+p0>}YG5s4P2y`FA5rJO5=?Ahj#NRZUh)hx0LHW9_OZ{(2LqJ9Z} z4Uh;mVhN`D`(q8*zOsQx#%+{`8&Oi>jr7Jti&_nxNm4UOG%Gn-l&ldI50g(?r=)VN zz)s6>lDa_qxbZlguwG}^gT;KMX%mPU6!uqj%qrMz@bKTwzlV{tp^wdo7vD~ zDN$QpGG;nCR>wDF7jtI6;|!y_Y1(Z;$k?azf(-0d$CtGZyBo;V_r}>}l4n`lbl0|w zw6hQs(qp@h-RvWFfV-p5x+gbu?{PkMzTJ8~#SB6lORDwzS8K5H@J83JG$qYG8A#m= zlE;Cn9v4|w%+b4=dMS}jqNUTW?!vE`DuJ>7I>Z9E2dFn?_TP4gI_oaB7#)|_0VS_m zlUSl^9O^aI8?XC2WzljcXm+pkicn;xxRP;;n4~~CC0I3zz#89!Z=9KRR^?Uy-Higl zX>6iU$D1U>OTW}4l+S7LN^8{l-0Op~q0}{22fCZQ;`#0+$GXJiRsZdc0y@H*3|b<= z`eE7|3h@4`6Sx#Ty_Z|xuW$?ZItO@%uT@JVuB=n;nytGxC-yK%8m0)@>(ugrYqhR4 z@maSFOYqpkzevKFLWEbR=a}jj-pSzA+4RyXal7>}njG$B*7{^>NCWOGfWbBKYpQ z(s<|Iy>;fhXrYjZyUw+g?^k>zt~45#eqOENfs(r#Wrk=On}wdl(cEPrGTA!u8Ag3z zJ*+q9bIX`p&crj_dqN7=+oIoX>W_p+cg3fcy~x;9H(KV!gVGo6W;YIs^UKSxs<5y z`)Nt-&R<2PvUhRWtDhY)u ztGDD96v=rQF88c$t1{5U9656RwCCvG-Du!U8dous92EuC z*}L0_kOfV%TAL$Mm9&C6wW=T* zm|`}qJ7f7Nnx^^M_MqilvxuF0Y0nwwO{a_%viWJonzjdc>S`I2+)s{4&NuAk8J+bo z?S~0Hj-JCD;B@RMo{kGiACehcRAt)4`DLDPrK9&kbsfA@A0&cFEHk{ZtP;BUV~w$* z^DyaqUHbTfBpVl4}7_L|EK%C zU61_7|NB3T|L;F>?4d0K7eDK73VLJdpn4&(DH!z9Nx4DwmDWwcjJMIm^PZQEwWeG0 zCf%~bq!am=m&>;1TfD5FP3058X`aEET!MVT>6X^aQoPd`Q;dE?qVZQFuKb;gD}Mow z8qUR9J7cY>me%fcyfvuS;;otLb8?4fpR6Y17GZsr_7rL%s*$c-B>mcmJO z;&i4uOe}LQwJB5mtVcegl^bum!^Cl;+7#94D{m*YTaO=kQg|rYnK_rF1>1PuOJ~ke z18!JDYo4-MztzOL)9IEr6W1fwl~$2lQ2m^5T4H*}1Yb^0+Be|&>7aT((b|nCY53(0 zp7GZ1%o6SSnI%v_ue_Y~fdP<9Ql@Hflv`#BJ-+NX78^wgNou3}sO33aW2r3aNY?e=$?= zJL_J*?rp1kQ+029-J5P-t)V+n_h-(v*;Z7upO5*r4Wa}RQTSYxfRir?8Sx+?Cd}aj zN*mKfm{es-cjbM$nC{XircXz{)kgSTKI5H_b*d!Kc=!|^6mAWl$?&P#6yFv;Q{l5+ zPb#%xzdPYK1X_IcBy%pzYEi0L0hEUC27%(og6bvvy{w+pIzV!^Eg$zYH9wmcuB@-S zrMrdE^0PQu(i5qyZH!>2;!<+bOm&eFkC>P3PH6gPJFRP30kcjqDYC*4@CM7-OaZh( zA9%r0M?UWSJ^^J;3r8X&LLSpsZg9xDW7d7xy2q^hXwnf(m+uBkxQOTIJ>$pBAyyUn zG~E(xgV@q|V!<}Q3mRoix7kXz#ad%fJ5%?frejb$pXCY3ozF6xz~T99j0o$2$NBuH z_>V1D^`d?sR<7uU{Q~}CLujNaO}U0_iF*F#@`Kbihz)JPZV~o|H8s{B#YN9Smcu^U zEVAHLC_992m<4QrP%oC5AyRuu(+P@6(#xc48*-TVVcU-O;Z$yf&oFtEHc07la`q87 zVBLz%+e>Szr=N6fZBE)U+T|@R%-(#8a#k$&(t#;v1PSHM- z;YGiV6-CeBLkZ26b5S^Rj%i|3wCtw46H!8ULPa$LTYMVyY0zitv<6whc_G%CWd%!U z>Asi-z935^OvLgLCjBUj{mwYjf{A-_VsaFY@0P>A7jMNSTOsZ%s!L8@PF0SfSlm!7 zuH11$p12`T9BBw=w;VE(=E;f4u~~ijy5!{L?3PoNV_2WbBZt+GJn^b+!?YNDR8aNs z-S#MX{M{C^fjB5Mah6vTPs(YNlakXeCoN}#oQ#}6&PF*m$=M|5W;vU2z}%?T-Y*Je ze<&OdL}OhmDtJ#Ttdn)#vb7=$m;yvIEM8F5NEd=)BF|D#gl}t+Adsnki2%d&B~TX} zwaEo}N9EjM>%yhbfFeF(y|hG?wR;rvh|Tf{tT@<}seU6ZiM4--2CS$v1!z`294Ai({I_1+`zBQ}>U5>&qn z@ArbELG}4e^^YZPr0E_|j%Yzaxca(n_qzfaB!CbnsC?5k_)WoI{dTa0AS>jz70W|y zRljSS`KHkRtOno(Ip2})0b)RGsNg{#hpoAD@+un^Z5}eKjyAg%sKjZH= z8@IBreKT9v+B*pa#!GU(D(5Tl??G4bvWVnX9M5>(t=GPW;$6*+OQDPQzPB|eNfW;E z-A(oRW%|6&($zje@hWk(@4_|2Z*sol9+FFgvK@mmzG>^5#&^>CPU1UdeWz68>ki|u z6MKmNG5#Os{}}&|D*X+Y&I9El&DcTejyH`4yAy_CdI}0>%$|xP6KC7SQMBR*i%3x| zF+?)75XwM@#(_z+pUy1B5QCs)37fV)wQwk+8M)uszk1~^{gOQo5D@R%vI(KV~fELpIfw;iy%sQ7PUX*3_@B|;^D`&G0e zFJ_VHrzH+nFR}pmG=-1p0}eDx+_TXr2EV82s4kUaH8uJ*ycSL~4eL<+n|EgyA0l53Y4S63$GOURy1WKto zINgy?S_LzkB2u874s}hk3y{-Uh20c98&1Kqw!CEsPax}RR#u;=$5o@aYCY~VQQT*U z>&zoSqqdBuk+ox)d@49y50cJ6#DdeB6W@^Yt#m%=33PD8Fn){feA0(c5%^>(BNd6E zVa`Z9u!x6e=R~kMMTzd8N@+cZ8iVTRGiGf8Exi(1wL0@qAqa$7@cEcs8{WeEMd94H zmHkA-a?ldXLA(;L!Sr(?Egm-TqzgQ017C50@L@@9$(CLMt1+gO(u3+xG>8Xrs8B=q zoOPeH?pLh)l5#8wBhSP;#H;XqEuNKci=21KxkXM+PPd%fTxwU z)v8~&_0|%YK&m!t=&2<{nMD|rU3H5g+w-lWeqKHMve@BGR^cfs1hr2Qq7SI;01}fT zoIsOIr2LdrID#!v5G9VDAXU+Prq-skPWfR6@^`rSPWjQn>6M%mTrFWmsG@Hv3L6bz zf5CGhw4qnJjAxBGt0}CD%+;8d%AA_?yP;lI*^E#!$`UQ6Rz1(xP5bj`Rmz)=?+6`0 z5kAE^$oUFi;8a^eNo|v-1hBg$Q|s0u454m?I;Cl)Emd5MS2V^y!=WHKw~6AvFMMs4 zbEljUFk0KLgr~_QuIS|2Y*77?VlTC}QCjo|aPonLRO+b-a`r%|@3c^g-LtTQzhGX!jn2r`>GYE3W<55Ta* zVF;s^RFYsemxeovyVdd`*Q({=N-DI?cB!@vy6tK;%CkLgFwAHP@Zsmgq+5-(+=+## z3gq>ex^M?L(o_m(6pJ7nEVGmjQ!-1I$r2%%)5V8bu}9dfK86L^gO*rvRh|w!>;H>hH8Dtlen?wr1)PLUO_*@pA7#Vb85nhfGQ| zZ=nI=(5t1*Mp7Zh7i3`17cv#8CCBT==OFJTEhenTEVhGMubrS|6!IZ+<--MNaEk}( z3y#X75ggU3O2rnV!BIVYJ%o^A>kgGlyNBqe_M(^yQ6NwBM+CJ?d__^Ca+xb6tV04Y zUy(8tp$Q#}ZEM_N?_rz5ovxQTxc<{-A?woUYZ@b&xOt0sfdJ_M2$)^~&k6U%11e5Xk&CdSi!6Ar@s-F~yk( z7qgp8o6GMriy}jn-;VvUdJ$vp&aQ0A#MO>IDZ^}qfAVGhQ#rpYb(3Lwt+uFqhZSX${sC$B*UB!um|sN25~Bsu*@Bys5=baVweO zP+Vn(gP9qmtWHM81}QBW{d zhtFd?g`3QPLj=#1?P+Ep2x%jDRBa*zc0|xKeuCQ$g#e?d>gY}|wt`1pfWWeN_=W?O zjUz&4!2mUNWoplYfoH6cso@f>Wu2TD2H<+m(5RH)G?PU&XPL-6gVW47h3%?*ksMY$ zRL(QGHk(z2uwmOwS`qRgVYpq5tWU}VMUV^w zJ1=r1ctMp6${Ar6;kE7viDVi{_%=!|D|}G>L8o{ei`);SMa4D<^)J=KuGL-cu?MR` z7M6}4;dz~k1Jf?)HE0Qr`I;7VX6`fO?DS$@-1EIIFYoQPnQLFw+KHX}FA~0s_?qR) zwu_nCH!RboLPJd#ZGc`Y@cmZUEOGAfeVg>AOL`MtDut_4`la=>0hjZINfOd*L~1oD z5itWQE8d(J5Sce{8)!mY6`aTw++Hv@2GVbb(9XSiY<% zVFT22Ny(RN@+AxYYYzO^k}P*ZTpR1GpO(*7ddUI!T9=&)!DzNS4N#Z5SkE<~@X~_lj9&B|@vz^G6{+|zDLz*fa;v^}B+t4;X8{HahU{K?N*QRi9V=b1>t ztX*35U3Nayus5~7TJowrt3KAA4VKYS4&z_ZEm3 zXCM0Fr#|pczIDgF|7y>>e)f-k|EK@-)L%~h&L8~7?%(_98~b*2{`il6>xsU}KNya0 z{N#T~FYfuy-+l5=9@w_~PoDlaPyOXc|KFYe`d3Ha=>JA~8jH0Zm_1pU zpIWSxjZ6Hd@5%JdA6ll5v4S-g);`pBGJ?8qjSroVL3SB$*uhM!9jbbl$xJOu%Nj%R21 z6hVK^t`aZ14S0n!wO89{g2HHX5(LkMu_$BsyTec-$s+I^=9#Eva&Jl|*wN3N3;Pp3 z=p&o;48FGRVSAa{>umcIS(6P?)rk!C>`bE8J(ubvg?dCoU+^Skqsd8(2diSa8;vUK zhRSYAIvvkt1T<-U)EU%%*uvZ9#=(k_X#pb+RM5N>bV7)n>_A6~}32L`$NLbS8;D`a`FB!JS9|ED=c7QuRgp0JwfzWQ`Ul>qsV|K6K~W zlW{lv%&k^>O>XFufCkX-OiGLmmOs)a-OAws`YVE?bhy!%5E{gGtr{51ESGYb^vY4CKz_W{z{PtO*jhi7HT)WMw^KTW|*vb_5s&1~}WDgNU$Bpz5lV;Ui_K{fA-y z;PD{;MF*Ahq@Zzp=z7(Qpf+0L)ME{&Bi794s& zprs8w);g#s3l4>2zVOj>j>h9CDi*HI$+iI7$$7rE0`@coa*iU}-^9-V$wzHk4M95! zQ%-g*&2bIYGx)(U9#MX14^2{fWeCQzjzGq)$Vd}(eWxmIS_s-4ClxE9O z?9Tj}Y&-K0Rpu9_=4N;G_7r+XhI$G+^Lx)sFP@pN?3%5dS)4CT@5~=MGd?{v@xjW{ z*xbh}v%AXUBmKkU6Mf}@fyv3- z*sBmkdIxYC}OC74~#RXEGZPjNRnVva1gLL8WeNz!BKb~Mq_By z%f(b}^?Raq9y!3_k5Te6%U@vOvq4i!d#3t(_fJjC&n?VNF7`ZhB*IG1zS3ez2n(^- zbL8}Nh`6!J*~R_ksl~bZo%!{O*6~*ae|&yE`o;_WlY^7PlfAv=!9uCObmqv?!eV8n zXWxA3@u}Gp5e!EUj4hq2L~S?cskhqqPFrP6Jfj^#V@`YK=!vKSVIt}~?L#mjbR^W9 z9k}jhhlfjp6N5v&BmD!FLUF_m1p|bUw*~~&r`E%&8xS`yGxHNSd{kVk4vMc^j$B|823t_% zTUY@?*?f6ZJ4}m>Z1%<33YT)Ceeq!V1*fTehd_=H>kBR$?=kTLNgxCf8*HpiP<$)% z@}nHMHgG={1bsWYyp~%{*R9ayt(=PRf_?CfV4pq;l@%)MqtLWM)A}fMQlXRjD0E7p zQ~D$bRbRJozmA8mjd{byyumiIc9QK{iK#|gNQ11UnPk%T@%eO645qqs084%QIEk5r zJtxI=&v)loak2exBd`@#q=j5%(Ok8!B5x!qR4>RUVW4{9cFB7PX1UcEB6B$fB~(-| zAahZ_Rt&@vjzK(!pu>?`0}fwGYiO3Wxr}W4DqrE2mEr|>B_TXxo_X--LM1;p%l~A4 z@nj{xun7Mz&6o4{R!&UKj?I^57fN<6CBxZ4k3{wunBQ?gAGliMjrcw+y^?I11xAON9v zMoGD}hTn;uKfu0&aKMfW!bh%AFig-l#02ervhrdnP>vX&U4+9h|OzKqe^ z()?T2{R!|%Zf0kn!t&U;k`uh?0L`TXnu%o!TJc!2QLsSUPl@BGuQf7Z=VBl=c__@x zk#?Y(tIum5@<=B!gE7;dm)Zb2(M(pnU^eyn8B#-)<1 zYzmT$gzX7H z=WW(VR;vP7w00d?oM(BDR>x2Hr1Y;byw9W*ITozh}# z2x|ZQDm(mqUoyp!2BM;Z{%WSx7$$FH;jEZ*V-Zd?z%66B_lnA%x}toP+*ApMKz4!x zICxW4vD|M;w|#20A3)~HH-HG=puHS?S~BfZOoDhre!;TAGbxFbZn4JX!hymAhHuEzK|GKXCNGJ{O^W<)e-XjH8DS@G_HU{QJ(Zc-YWQp4qUkGFd{8 z$d66UROZg`PLd)I%~wv9<}3Nb73PB4SLA)Asp0`mna+ci6Qzlz{C#ut zGbIWmy0;y!l*;)BXQz3;a*Jnf8m*iyl`9idGo|VLq0+*_<8$+6m+?^PL?wS@>Jt?! z5!WVMbDPR#<}$Ee}adJVRErR>blEKJPJPfv~4Il(&?vIRdkBzWfL)z%$c zdB=l{!Bp6FZ;3%aLf2ZYTv ze~eT*TbdS8?Vmj}qa%&%lX|8jOvo$6m_;i2SYssz7UrfcIUcM$RzcBhNV_3u&yvz)hu zVOx?^?ddAKuC<;Gh8797?6C{(57Z42R=#W=>q44m` z9OU22>s-}WZcer#(IO$}Y#U>MDBaCR=HXz)8G^Cb;#*C&mgAM9)<&G(l)<-}v4?7>lV3(6|)f4s__~eM5(tnUa=}IOr zvt{T5K1^%A^dR(yBAVT()ho_ZpY)H+N~yNF$E!XOa=;^%i8JgcE%h9#%+F|{o||3h zi6ZN9dlp&P$ImRnCU4++R{fkecJx!f7$o9hHx!73<%(4pDkl@z;HYg6Rw^hBqMO=w zp1i$*>6a%%%t>w3TGWv0Ga&J|uLb(y%H*^&ZvC>+nDNG99rsse#w+uCCMGHi3!W6v zl^ONL>bNU2gi!L>-1rH7ARyhxQh%1ymCl|K`98$1boEC!Lp>QQb1Q`BejDvJ60xzf zWkwx%to<6?q$Kz9?9|g*VV=f-0=>$vYCK+1zk9&1|VVuYgw?m zd@ZcrH#J>3@Zc{Sqt)O2d4zcd92W66lra50)6;5ZK`%XNrRHU?T9;iquvlPrsJ?6i z%Wt{3r*BVk9HXn7ct2Qvi&GvLFS_OPgOxKf+xR~FC_Ko;VI#J_R+eB%sAfD>wUN>3 z>8v)H)EH-B?FrZ@9mR+iG8Tbv!$j=^ z1fc%c&^Ij*%;V=Vyf8homVLrP8^Li*6|;?HuG)I2<+Q}K>V$X0E&YCEYr zht2p@I3rlwPhkO^U6j~8-Q$FQWW&cQ^T=J11Y2L;{~n6Q_1f_7Jye=U$DsLzUr~`G zntAMPxp`7Zu%W$?Z72-F8_l~oHG!3iMVBMGek{sk87!+Z+l|^LWgCn`80?0JT#~n! zEw^k9pNa6944-Y`vt3VkI5LfVo0BQ70f2RmKrSQL>6S7zPA#-qi=1|EAtWEt#^MOs z7In-cD5ko+SZIBh4SiG;&0d=`hNfFFYo@IQJe}4ir`~15c=2VnB6 z>4v4;A2JuUaqVVIXw*xmZ%Vd?CLYxmCT_xV9ISjDamLL&s==np(gBM?+On12l={Hg{$QeTf~Q#twXi+CCAmQx(DL%k)V>;dzNRB- zxhytmdx+3IQnx2L55=m=;Y1hT;JW)OQY@cP+iSLIC{f3GILnKxv(-A~mcSUTqqQ9P z0F^ph5M!Yh?~0auj@gN~LPwV!dxh1*iU99fYl*KtyFtRjsE(8|N-!dsb#(+#ey!Sm zOntJ$={7cMm+XE#uh5HMURHpU>^>TeJ1iM`Qt7aww_ROP@UjcC8!w<-K%4C@;Iqf% zysx+n>t10<`yep6o%irml9qhDMN|OT!SPaGabmnYS(xk}8kwjJ z4)tNQkg=n$&^vf%q5sapK)!e6?!jKZ*!K3i#E|x-^Mo^OJM);i&-*zIo=hlZ%U|7Vf_5t_8O-Tvk=iYSc3~f8s8FKm=RcmF+N9F^9RM z1o?e)Go>lEmO4C>JY1QsV0K|Yc*--ii7QL?9Gsdx-EazFSE0~1P|)8%(LP38s8ARx z^x23oeXwt^f1tO&S2=CGeEJ^*cf~R|D-KT#RC>pU`g+Ud$;rWTabRG$Z+M`$I5Idi zGBP|lFg#cpFZPWL^o>*odV5Qgll_&E{>hQy@!>+bGBi>g9~tf&8YqnP4UU&N57AdF zFe0VC!BTOczi()0WVnC000_eqF=Mcj8BaBmL>*@<#K=j_&}l3+dnY?Y{kCb!HM2tX`p{#1ZRk*Mn)?A6aB@(iHV_N zKO;U_EDlW$P4pJV%Oi!}Ucl}fFAveR;o-qTv7g+f-jR`k-txrA1gJg|8N9nTIyEB+Fmq+_N)<`YU-I!Z-RAnr7^M~h4ryk(2!`X?-DH-d> zuqoCB%*jy&+pbN~I^W8dEY&vt$4zj&`EZi&ac8>{I}w(-MCf${A#et z)76kqKdUk~zi)c_esL;m&8Sp*%G2DU%-_$pQ-{pUzyAA`!~pvv^otjgtIgeWhsg@- z#4Fz@{|`SJH-F|f=WNkGYZ>7AkkRk9>DOTn<8wcKUjOYIWqcw2zy3~#x847vtIzl2 z)1N5VaSt1`&OTg^T6JT-yR5Kc-|W-1bo$$7OO4rU@^tBIhb6~o1U`mLBAE=$&L=Hv$$2|KM$jt5n{NJr>&vh zhiorbf4hzJwU_j$jYDQLW$N!_>g9{+hTdKe3_W1f-tkU-yG@$<4$`)MFKyaFcMANd zcPA|7)MowXYBWL`LtVG2UO#N%c`(ecIMov2N+FH*_2H%wu2J5-@Io3W)4r}&Y#h_; z=_k!{50Y@~Xep{^EvDDQ^F6lQ+Uv8|{_M~CW2AO}{r4-3fkSblt0)S0{|fi<*Im0R G2L2z9KRh1* literal 0 HcmV?d00001 diff --git a/Admin/packages.config b/Admin/packages.config new file mode 100644 index 000000000..f2dfb35b5 --- /dev/null +++ b/Admin/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Admin/version.txt b/Admin/version.txt index a6cd23903..a803ba7b4 100644 --- a/Admin/version.txt +++ b/Admin/version.txt @@ -1,4 +1,21 @@ -VERSION: 0.7 +VERSION: 0.8 CHANGELOG: --rcon tweaks --so much stuff cant remember +-added mask command +-added baninfo command +-added alias command and removed redundant output from `find` +-added rcon command +-added webfront (http://127.0.0.1:1624) +-true skill is officially implemented +-find now shows last connect time +-noise on pm (if gsc_enabled) +-force 8 line chat height (if gsc_enabled) +-tell admins the number of reports on join +-enhanced ban tracking +-ip wait timeout added +-remove report on ban +-can't report yourself +-remove reported players when banned +-fixed rare crash with toadmins backend +-fixed crash when finding player stats that don't exist +-fixed a bug that caused owner command to reactivate only `creator` rank player existed +-fixed a bug that caused certain notifications to be sent to all players \ No newline at end of file diff --git a/Admin/webfront/bans.html b/Admin/webfront/bans.html new file mode 100644 index 000000000..7cbacad98 --- /dev/null +++ b/Admin/webfront/bans.html @@ -0,0 +1,11 @@ + + +
+
BANS
Back
+
+ {{BANS}} +
+ + + + \ No newline at end of file diff --git a/Admin/webfront/header.html b/Admin/webfront/header.html new file mode 100644 index 000000000..cb6e38628 --- /dev/null +++ b/Admin/webfront/header.html @@ -0,0 +1,277 @@ + + + + + + {{TITLE}} + + diff --git a/Admin/webfront/main.html b/Admin/webfront/main.html new file mode 100644 index 000000000..2ceb65d35 --- /dev/null +++ b/Admin/webfront/main.html @@ -0,0 +1,12 @@ + + +
+
IW4M Admin
+ +

Currently Monitoring

+
+ {{SERVERS}} +
+ + + \ No newline at end of file diff --git a/Admin/webfront/stats.html b/Admin/webfront/stats.html new file mode 100644 index 000000000..fff5a9991 --- /dev/null +++ b/Admin/webfront/stats.html @@ -0,0 +1,10 @@ + +
+
STATS
Back
+
+ {{STATS}} +
+ + + + \ No newline at end of file