<commit_before>/*
 * Copyright (c) 2013, SteamDB. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
using System;
using System.Collections.Generic;
using MySql.Data.MySqlClient;
using SteamKit2;
using SteamKit2.GC;
using SteamKit2.GC.CSGO.Internal;
using SteamKit2.GC.Dota.Internal;
using SteamKit2.GC.Internal;
using SteamKit2.Internal;

namespace SteamDatabaseBackend
{
    public class GameCoordinator
    {
        private readonly uint AppID;
        private readonly SteamClient SteamClient;
        private readonly SteamGameCoordinator SteamGameCoordinator;
        private readonly Dictionary<uint, Action<IPacketGCMsg>> GCMessageMap;
        private readonly System.Timers.Timer Timer;
        private readonly string Name;
        private int LastVersion = -1;
        private uint LastSchemaVersion;
        private GCConnectionStatus LastStatus = GCConnectionStatus.GCConnectionStatus_NO_STEAM;

        public GameCoordinator(uint appID, SteamClient steamClient, CallbackManager callbackManager)
        {
            // Map gc messages to our callback functions
            GCMessageMap = new Dictionary<uint, Action<IPacketGCMsg>>
            {
                { (uint)EGCBaseClientMsg.k_EMsgGCClientWelcome, OnClientWelcome },
                { (uint)EGCItemMsg.k_EMsgGCUpdateItemSchema, OnItemSchemaUpdate },
                { (uint)EGCBaseMsg.k_EMsgGCSystemMessage, OnSystemMessage },
                { (uint)EGCBaseClientMsg.k_EMsgGCClientConnectionStatus, OnClientConnectionStatus },
                { (uint)4008 /* TF2's k_EMsgGCClientGoodbye */, OnClientConnectionStatus }
            };

            this.AppID = appID;
            this.SteamClient = steamClient;
            this.SteamGameCoordinator = SteamClient.GetHandler<SteamGameCoordinator>();
            this.Name = string.Format("GC {0}", appID);

            // Make sure Steam knows we're playing the game
            Timer = new System.Timers.Timer();
            Timer.Elapsed += OnTimerPlayGame;
            Timer.Interval = TimeSpan.FromMinutes(5).TotalMilliseconds;
            Timer.Start();

            Timer = new System.Timers.Timer();
            Timer.Elapsed += OnTimer;

            callbackManager.Register(new Callback<SteamGameCoordinator.MessageCallback>(OnGameCoordinatorMessage));
        }

        private void OnTimerPlayGame(object sender, System.Timers.ElapsedEventArgs e)
        {
            PlayGame();
        }

        private void OnTimer(object sender, System.Timers.ElapsedEventArgs e)
        {
            Hello();
        }

        public void PlayGame()
        {
            var clientGamesPlayed = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);

            clientGamesPlayed.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
            {
                game_id = AppID
            });

            SteamClient.Send(clientGamesPlayed);

            if (!Timer.Enabled)
            {
                Timer.Interval = TimeSpan.FromSeconds(60).TotalMilliseconds;
                Timer.Start();
            }
        }

        public void Hello()
        {
            var clientHello = new ClientGCMsgProtobuf<CMsgClientHello>((uint)EGCBaseClientMsg.k_EMsgGCClientHello);

            SteamGameCoordinator.Send(clientHello, AppID);
        }

        private void OnGameCoordinatorMessage(SteamGameCoordinator.MessageCallback callback)
        {
            Action<IPacketGCMsg> callbackFunction;

            if (GCMessageMap.TryGetValue(callback.EMsg, out callbackFunction))
            {
                callbackFunction(callback.Message);
            }
            else
            {
                Log.WriteDebug(Name, "Unhandled GC message - EMsg: {0} ({1})", callback.EMsg, GetEMsgDisplayString((int)callback.EMsg));
            }

            // If we hear from GC, but it's not hello, keep bugging it
            if (!Timer.Enabled && LastStatus == GCConnectionStatus.GCConnectionStatus_NO_SESSION)
            {
                Timer.Interval = TimeSpan.FromSeconds(60).TotalMilliseconds;
                Timer.Start();
            }
            else if (Timer.Enabled && LastStatus == GCConnectionStatus.GCConnectionStatus_HAVE_SESSION)
            {
                Timer.Stop();
            }
        }

        private void OnClientWelcome(IPacketGCMsg packetMsg)
        {
            Timer.Stop();

            var msg = new ClientGCMsgProtobuf<CMsgClientWelcome>(packetMsg).Body;

            Log.WriteInfo(Name, "New GC session ({0} -> {1})", LastVersion, msg.version);

            string message = string.Format("New {0}{1}{2} GC session", Colors.OLIVE, SteamProxy.GetAppName(AppID), Colors.NORMAL);

            if (LastVersion == -1 || LastVersion == msg.version)
            {
                message += string.Format(" {0}(version {1})", Colors.DARK_GRAY, msg.version);
            }<commit_msg>Revert "Keep resending hello message until we hear from GC"<commit_after>/*
 * Copyright (c) 2013, SteamDB. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
using System;
using System.Collections.Generic;
using MySql.Data.MySqlClient;
using SteamKit2;
using SteamKit2.GC;
using SteamKit2.GC.CSGO.Internal;
using SteamKit2.GC.Dota.Internal;
using SteamKit2.GC.Internal;
using SteamKit2.Internal;

namespace SteamDatabaseBackend
{
    public class GameCoordinator
    {
        private readonly uint AppID;
        private readonly SteamClient SteamClient;
        private readonly SteamGameCoordinator SteamGameCoordinator;
        private readonly Dictionary<uint, Action<IPacketGCMsg>> GCMessageMap;
        private readonly System.Timers.Timer Timer;
        private readonly string Name;
        private int LastVersion = -1;
        private uint LastSchemaVersion;
        private GCConnectionStatus LastStatus = GCConnectionStatus.GCConnectionStatus_NO_STEAM;

        public GameCoordinator(uint appID, SteamClient steamClient, CallbackManager callbackManager)
        {
            // Map gc messages to our callback functions
            GCMessageMap = new Dictionary<uint, Action<IPacketGCMsg>>
            {
                { (uint)EGCBaseClientMsg.k_EMsgGCClientWelcome, OnClientWelcome },
                { (uint)EGCItemMsg.k_EMsgGCUpdateItemSchema, OnItemSchemaUpdate },
                { (uint)EGCBaseMsg.k_EMsgGCSystemMessage, OnSystemMessage },
                { (uint)EGCBaseClientMsg.k_EMsgGCClientConnectionStatus, OnClientConnectionStatus },
                { (uint)4008 /* TF2's k_EMsgGCClientGoodbye */, OnClientConnectionStatus }
            };

            this.AppID = appID;
            this.SteamClient = steamClient;
            this.SteamGameCoordinator = SteamClient.GetHandler<SteamGameCoordinator>();
            this.Name = string.Format("GC {0}", appID);

            // Make sure Steam knows we're playing the game
            Timer = new System.Timers.Timer();
            Timer.Elapsed += OnTimerPlayGame;
            Timer.Interval = TimeSpan.FromMinutes(5).TotalMilliseconds;
            Timer.Start();

            Timer = new System.Timers.Timer();
            Timer.Elapsed += OnTimer;

            callbackManager.Register(new Callback<SteamGameCoordinator.MessageCallback>(OnGameCoordinatorMessage));
        }

        private void OnTimerPlayGame(object sender, System.Timers.ElapsedEventArgs e)
        {
            PlayGame();
        }

        private void OnTimer(object sender, System.Timers.ElapsedEventArgs e)
        {
            Hello();
        }

        public void PlayGame()
        {
            var clientGamesPlayed = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);

            clientGamesPlayed.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
            {
                game_id = AppID
            });

            SteamClient.Send(clientGamesPlayed);
        }

        public void Hello()
        {
            var clientHello = new ClientGCMsgProtobuf<CMsgClientHello>((uint)EGCBaseClientMsg.k_EMsgGCClientHello);

            SteamGameCoordinator.Send(clientHello, AppID);
        }

        private void OnGameCoordinatorMessage(SteamGameCoordinator.MessageCallback callback)
        {
            Action<IPacketGCMsg> callbackFunction;

            if (GCMessageMap.TryGetValue(callback.EMsg, out callbackFunction))
            {
                callbackFunction(callback.Message);
            }
            else
            {
                Log.WriteDebug(Name, "Unhandled GC message - EMsg: {0} ({1})", callback.EMsg, GetEMsgDisplayString((int)callback.EMsg));
            }

            // If we hear from GC, but it's not hello, keep bugging it
            if (!Timer.Enabled && LastStatus == GCConnectionStatus.GCConnectionStatus_NO_SESSION)
            {
                Timer.Interval = TimeSpan.FromSeconds(60).TotalMilliseconds;
                Timer.Start();
            }
        }

        private void OnClientWelcome(IPacketGCMsg packetMsg)
        {
            Timer.Stop();

            var msg = new ClientGCMsgProtobuf<CMsgClientWelcome>(packetMsg).Body;

            Log.WriteInfo(Name, "New GC session ({0} -> {1})", LastVersion, msg.version);

            string message = string.Format("New {0}{1}{2} GC session", Colors.OLIVE, SteamProxy.GetAppName(AppID), Colors.NORMAL);

            if (LastVersion == -1 || LastVersion == msg.version)
            {
                message += string.Format(" {0}(version {1})", Colors.DARK_GRAY, msg.version);
            }
{'fraction_non_alphanumeric': 0.08728593668915413, 'fraction_numerical': 0.006434872859366891, 'mean_word_length': 2.2966130687649673, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2462510', 'n_tokens_mistral': 2629, 'n_tokens_neox': 2527, 'n_words': 542}