From 455b94dfada30708eb03b9fcaf207c9b34a0b724 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sun, 4 Dec 2016 02:08:45 +0100 Subject: [PATCH] Apply optimization --- ArchiSteamFarm/Bot.cs | 18 ++++++------- ArchiSteamFarm/Statistics.cs | 50 +++++++++++++++++++++-------------- resources/Statistics.mwb | Bin 6793 -> 7011 bytes resources/Statistics.mwb.bak | Bin 0 -> 7010 bytes 4 files changed, 38 insertions(+), 30 deletions(-) create mode 100644 resources/Statistics.mwb.bak diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 0bcadbfeb..6f94d06fb 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -76,6 +76,7 @@ namespace ArchiSteamFarm { private readonly ConcurrentHashSet OwnedPackageIDs = new ConcurrentHashSet(); private readonly string SentryFile; + private readonly Statistics Statistics; private readonly SteamApps SteamApps; private readonly SteamClient SteamClient; private readonly ConcurrentHashSet SteamFamilySharingIDs = new ConcurrentHashSet(); @@ -203,6 +204,10 @@ namespace ArchiSteamFarm { Trading = new Trading(this); + if (Program.GlobalConfig.Statistics) { + Statistics = new Statistics(this); + } + HeartBeatTimer = new Timer(async e => await HeartBeat().ConfigureAwait(false), null, TimeSpan.FromMinutes(1) + TimeSpan.FromMinutes(0.2 * Bots.Count), // Delay TimeSpan.FromMinutes(1) // Period ); @@ -665,9 +670,7 @@ namespace ArchiSteamFarm { try { await SteamApps.PICSGetProductInfo(0, null); - if (Program.GlobalConfig.Statistics) { - Statistics.OnHeartBeat(this).Forget(); - } + Statistics?.OnHeartBeat().Forget(); } catch { if (!IsConnectedAndLoggedOn || (HeartBeatFailures == byte.MaxValue)) { return; @@ -1212,10 +1215,7 @@ namespace ArchiSteamFarm { }).Forget(); } - if (Program.GlobalConfig.Statistics) { - Statistics.OnLoggedOn(this).Forget(); - } - + Statistics?.OnLoggedOn().Forget(); Trading.CheckTrades().Forget(); break; case EResult.InvalidPassword: @@ -1324,9 +1324,7 @@ namespace ArchiSteamFarm { if (callback.FriendID == SteamClient.SteamID) { Events.OnPersonaState(this, callback); - if (Program.GlobalConfig.Statistics) { - Statistics.OnPersonaState(this, callback).Forget(); - } + Statistics?.OnPersonaState(callback).Forget(); } else if ((callback.FriendID == LibraryLockedBySteamID) && (callback.GameID == 0)) { LibraryLockedBySteamID = 0; CheckOccupationStatus(); diff --git a/ArchiSteamFarm/Statistics.cs b/ArchiSteamFarm/Statistics.cs index 1ac98c435..981e23f84 100644 --- a/ArchiSteamFarm/Statistics.cs +++ b/ArchiSteamFarm/Statistics.cs @@ -28,45 +28,55 @@ using System.Threading.Tasks; using SteamKit2; namespace ArchiSteamFarm { - internal static class Statistics { - internal static async Task OnHeartBeat(Bot bot) { + internal sealed class Statistics { + private const byte MinHeartBeatTTL = 5; // Minimum amount of minutes we must wait before sending next HeartBeat + + private readonly Bot Bot; + + private DateTime LastHeartBeat = DateTime.MinValue; + + internal Statistics(Bot bot) { if (bot == null) { - ASF.ArchiLogger.LogNullError(nameof(bot)); + throw new ArgumentNullException(nameof(bot)); + } + + Bot = bot; + } + + internal async Task OnHeartBeat() { + if (DateTime.Now < LastHeartBeat.AddMinutes(MinHeartBeatTTL)) { return; } const string request = SharedInfo.StatisticsServer + "/api/HeartBeat"; Dictionary data = new Dictionary(1) { - { "SteamID", bot.SteamID.ToString() } + { "SteamID", Bot.SteamID.ToString() } }; // We don't need retry logic here - await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + if (await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false)) { + LastHeartBeat = DateTime.Now; + } } - internal static async Task OnLoggedOn(Bot bot) { - if (bot == null) { - ASF.ArchiLogger.LogNullError(nameof(bot)); - return; - } - - await bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false); + internal async Task OnLoggedOn() { + await Bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false); const string request = SharedInfo.StatisticsServer + "/api/LoggedOn"; Dictionary data = new Dictionary(4) { - { "SteamID", bot.SteamID.ToString() }, - { "HasMobileAuthenticator", bot.HasMobileAuthenticator ? "1" : "0" }, - { "SteamTradeMatcher", bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) ? "1" : "0" }, - { "MatchEverything", bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything) ? "1" : "0" } + { "SteamID", Bot.SteamID.ToString() }, + { "HasMobileAuthenticator", Bot.HasMobileAuthenticator ? "1" : "0" }, + { "SteamTradeMatcher", Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) ? "1" : "0" }, + { "MatchEverything", Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything) ? "1" : "0" } }; // We don't need retry logic here await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); } - internal static async Task OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { - if ((bot == null) || (callback == null)) { - ASF.ArchiLogger.LogNullError(nameof(bot) + " || " + nameof(callback)); + internal async Task OnPersonaState(SteamFriends.PersonaStateCallback callback) { + if (callback == null) { + ASF.ArchiLogger.LogNullError(nameof(callback)); return; } @@ -74,7 +84,7 @@ namespace ArchiSteamFarm { const string request = SharedInfo.StatisticsServer + "/api/PersonaState"; Dictionary data = new Dictionary(2) { - { "SteamID", bot.SteamID.ToString() }, + { "SteamID", Bot.SteamID.ToString() }, { "AvatarHash", avatarHash } }; diff --git a/resources/Statistics.mwb b/resources/Statistics.mwb index 22149cc3d26bac0155d3c18cf91027fb79ae7411..1f96f222d1406abe83a7222fb1912b5c78226b36 100644 GIT binary patch delta 6248 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 S90J)FlPek>0%;nPN*X^GfFHyF delta 6106 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 IA2siP0ZN>x?*IS* diff --git a/resources/Statistics.mwb.bak b/resources/Statistics.mwb.bak new file mode 100644 index 0000000000000000000000000000000000000000..da2cd2e7cf9e8c3b3e2c61648116f08b31bf3221 GIT binary patch literal 7010 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