public MoniverseResponse Insert(MoniverseRequest request)
        {
            MoniverseResponse response = new MoniverseResponse()
            {
                TaskName = request.TaskName,
                TimeStamp = request.TimeStamp,
                Status = "Fail"
            };
            try
            {
                Logger.Instance.Info(String.Format("Insert Recieved - {0} - {1}", request.TaskName, request.TimeStamp));
                try
                {
                    DBManager.Instance.Insert(Datastore.Monitoring, request.Task);
                    Logger.Instance.Info(request.TaskName + " Success");
                }
                catch (Exception ex)
                {
                    _workStack.Execute(() => {
                        DBManager.Instance.Insert(Datastore.Monitoring, request.Task);
                        Logger.Instance.Info(request.TaskName + " Success");
                    });
                    Logger.Instance.Exception("Message: " + ex.Message + request.TaskName + " Error", ex.StackTrace);
                }
            }
            catch (Exception ex)
            {
                OperationContext.Current.Channel.Close();
                Logger.Instance.Exception(ex.Message, ex.StackTrace);
            }

            response.Status = "Success";
            Logger.Instance.Info(response.ToString());
            return response;
        }
        protected void Save()
        {
            StringBuilder query = new StringBuilder();
            query.AppendFormat("INSERT INTO {0}", RETENTION_RETURNER_VIEW_TABLE);
            query.AppendFormat(@"(Date, NewUsers, Logins, WAU, NUR, CUR, RUR, NewUserCohort, ContinuingUsersCohort, ReactivatedUsersCohort, NURR, CURR, RURR, "
                + GeneralRetention.GenerateDayString() +
                ") VALUES ('{0}','{1}', '{2}','{3}','{4}', '{5}', '{6}', '{7}', '{8}','{9}', '{10}', '{11}', '{12}'",
                Date.ToString("yyyy-MM-dd 00:00:00"),
                Installs,
                Logins,
                WAU,
                CohortRetention.NURR.RelevantMetricProcessedCount,
                CohortRetention.CURR.RelevantMetricProcessedCount,
                CohortRetention.RURR.RelevantMetricProcessedCount,
                newUsers,
                continues,
                reacts,
                CohortRetention.NURR.Percentage,
                CohortRetention.CURR.Percentage,
                CohortRetention.RURR.Percentage
                );

            for (int i = 1; i < GeneralRetention.days.Length; i++)
            {
                query.AppendFormat(",'{0}'", GeneralRetention.days[i]);
            }
            query.Append(") ON DUPLICATE KEY UPDATE ");
            for (int idx = 1; idx < GeneralRetention.days.Length - 1; idx++)
            {
                GeneralRetention.canHavePercent(idx);
                {
                    query.AppendFormat("Day{0} = {1},", idx, GeneralRetention.days[idx]);
                }
            }
            query.Length--;

            try
            {
                string q = query.ToString();
                MoniverseResponse response = new MoniverseResponse()
                {
                    Status = "unsent",
                    TimeStamp = DateTime.UtcNow
                };

                lock (MoniverseBase.ConsoleWriterLock)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("Beginning Insert of Retention Row Batch");
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("");
                }
                //Retention.Service(Service => Service.Insert(new MoniverseRequest()
                //{
                //    TaskName = "Insert Retention Row Batch",
                //    Task = q,
                //    TimeStamp = DateTime.UtcNow
                //}));
                int result = DBManager.Instance.Insert(Datastore.Monitoring, query.ToString());

                lock (MoniverseBase.ConsoleWriterLock)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("Insert Retention Row Batch success");
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("");
                    Logger.Instance.Info("Done inserting Retention Row Data.");
                    Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                    Logger.Instance.Info("");
                    Console.ResetColor();
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.Info(ex.Message);
                //Logger.Instance.Error(ex.Message);
            }
        }
        public void UpdateRetentionRow(RetentionRow thatDay)
        {
            StringBuilder query = new StringBuilder();
            query.Append("UPDATE Retention SET ");
            for (int i = thatDay.days.Length - 1; i > 0; i--)
            {
                query.AppendFormat("Day{0} = '{1}'", i, thatDay.days[i]);
                if (i != 1)
                {
                    query.Append(",");
                }
                else
                {
                    query.AppendFormat(" WHERE DATE(Date) = DATE('{0}');", thatDay.date.ToString("yyyy/MM/dd 00:00:00"));
                }
            }
            try
            {
                MoniverseResponse response = new MoniverseResponse()
                {
                    Status = "unsent",
                    TimeStamp = DateTime.UtcNow
                };

                lock (MoniverseBase.ConsoleWriterLock)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("Beginning Update of Retention Row Batch");
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("");
                }
                Retention.Service(Service =>
                    response = Service.Insert(new MoniverseRequest()
                    {
                        TaskName = "UpdateRetentionRow Row Batch",
                        Task = query.ToString(),
                        TimeStamp = DateTime.UtcNow
                    }));
                if (response.Status != "404" || response.Status != "500" || response.Status != "fail")
                {
                    Retention.Instance.InsertRetentionRow(thatDay);
                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Retention Row Update Success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Logger.Instance.Info(String.Format("--== Updated Retention Row: {0} ==--", thatDay.date.ToString()));
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Error(ex.Message);
                Logger.Instance.Info(ex.Message);
            }
        }
        public void RecordLatestLogins()
        {
            DateTime LatestRecord = UserSessions.Instance.GetLastLoginRecordTimestamp();
            if (LatestRecord == DateTime.MinValue)
            {
                LatestRecord = DateTime.UtcNow.AddDays(-1).Date;
            }
            HashSet<Login> logins = UserSessions.Instance.ExtractLatestLogins(LatestRecord);

            if (logins.Count > 0)
            {
                List<string> queries = new List<string>();
                List<string> processedUsers = new List<string>();

                foreach (List<Login> userBatch in logins.Batch<Login>(500))
                {
                    string q = String.Format(@"INSERT INTO {1}
                            (`UserId`,
                            `GameId`,
                            `UserSessionId`,
                            `Platform`,
                            `LoginTimestamp`,
                            `LogoffTimestamp`,
                            `SessionLength`,
                            `InstallDateRecord`,
                            `RetentionCohortType`,
                            `RecordDate`)
                        VALUES {0};", DatabaseUtilities.instance.GenerateInsertValues<Login>(userBatch), USER_SESSION_META_TABLE);
                    try
                    {
                        int result = -1;
                        MoniverseResponse response = new MoniverseResponse()
                        {
                            Status = "unsent",
                            TimeStamp = DateTime.UtcNow
                        };

                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info(@"   Beginning Insert of Login Batch   ");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                        }
                        Retention.Service(Service =>
                        {
                            response = Service.Insert(new MoniverseRequest()
                            {
                                TaskName = "Insert of Login Batch ",
                                Task = q,
                                TimeStamp = DateTime.UtcNow
                            });
                        });
                        //esult = DBManager.Instance.Insert(Datastore.Monitoring, q);
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Green;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info(@"       Login Batch success");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                            Logger.Instance.Info("Done inserting Retention Row Data.");
                            Logger.Instance.Info(String.Format("success!! {0}", result));
                            Logger.Instance.Info("");
                            Console.ResetColor();
                        }
                        if (result > 0)
                        {
                            foreach (Login user in userBatch)
                                processedUsers.Add(user.UserId);
                        }
                        else
                        {
                            Logger.Instance.Info(String.Format("There was a problem with adding {0} users for {1} - {0}", userBatch.Count, LatestRecord.ToString(), DateTime.UtcNow.ToString()));
                        }

                    }
                    catch (Exception e)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Logger.Instance.Info(e.Message);
                        Console.ResetColor();
                    }

                }

                Logger.Instance.Info(String.Format("{0} Added to UserSessionMeta since {1}", logins.Count(), LatestRecord.ToString()));
            }
            else
            {
                Logger.Instance.Info("No Logins retrieved from Keen");
            }
        }
        public void CheckComputeHostingInstances(GameMonitoringConfig game)
        {
            DataTable Result = new DataTable();
            string query = String.Format(@"SELECT 0 as 'ID'
                ,'{0}'  AS RecordTimestamp
                ,HI.Id AS 'HostingInstance_Id'
                ,HI.MachineId AS 'HostingInstance_MachineId'
                ,HI.IP AS 'HostingInstance_IP'
                ,HI.CreationTime AS 'HostingInstance_CreationTime'
                ,HI.StartTime AS 'HostingInstance_StartTime'
                ,HI.LastUpdateTime AS 'HostingInstance_LastUpdateTime'
                ,HI.GameId AS 'HostingInstance_GameId'
                ,RHC.Id AS 'RegionHostingConfiguration_Id'
                ,RHC.MinimumNumInstances AS 'RegionHostingConfiguration_MinimumNumInstances'
                ,RHC.MaximumFreeInstances AS 'RegionHostingConfiguration_MaximumFreeInstances'
                ,HC.Name AS 'HostingConfiguration_Name'
                ,HR.Name AS 'HostingRegion_Name'
                ,HI.GameVersionId 'GameVersion_Id'
                ,GV.Major AS 'GameVersion_Major'
                ,GV.Minor AS 'GameVersion_Minor'
                ,GV.Status AS 'GameVersion_Status'
                ,GV.Label 'GameVersion_Label'
                ,HI.Status AS 'HostingInstance_Status'
                ,HI.Health AS 'HostingInstance_Health'
                ,HI.MaximumComputeUnits AS 'HostingInstance_MaximumComputeUnits'
                ,HI.TotalComputeUnits AS 'HostingInstance_TotalComputeUnits'
                ,IFNULL(CALC.TotalComputeUnits, 0) AS 'HostingInstance_CalcTotalComputeUnits'
                ,HI.ServersCount AS 'HostingInstance_ServersCount'
                ,IFNULL(CALC.ServersCount, 0) AS 'HostingInstance_CalcServersCount'
                ,IFNULL(ROUND(CALC.TotalComputeUnits/CALC.ServersCount, 2), 0) AS 'HostingInstance_AvgComputeUnitsAcrossServers'
                ,IFNULL(CALC.MaxUserCount, 0) AS 'HostingInstance_MaxUserCount'
                ,IFNULL(CALC.UserCount, 0) AS 'HostingInstance_UserCount'
                FROM HostingInstance HI
                INNER JOIN RegionHostingConfiguration RHC
                    ON HI.RegionConfigurationId = RHC.Id
                INNER JOIN HostingConfiguration  HC
                    ON RHC.HostingConfigurationId = HC.Id
                INNER JOIN HostingRegion HR
                    ON RHC.RegionId = HR.Id
                LEFT JOIN GameVersion GV
                    ON HI.GameVersionId = GV.Id
                LEFT JOIN (
                    SELECT GSr.InstanceId, SUM(GSr.ComputeUnits) AS 'TotalComputeUnits', COUNT(*) AS 'ServersCount', SUM(GS.MaxNumPlayers) AS 'MaxUserCount', SUM(GS.UserCount) AS 'UserCount'
                    FROM GameServer GSr
                    INNER JOIN
                    (
                        SELECT GSn.Id, COUNT(*) AS 'UserCount', GST.MaxNumPlayers
                        FROM GameSession GSn
                        INNER JOIN GameSessionType GST
                            ON GSn.SessionTypeId = GST.Id
                        LEFT JOIN GameSessionUser GSU
                            ON GSn.Id = GSU.GameSessionId
                        WHERE GSU.Status = 2
                        GROUP BY GSn.Id
                    ) GS
                    ON GSr.GameSessionId = GS.Id
                    GROUP BY GSr.InstanceId
                ) CALC
                    ON HI.Id = CALC.InstanceId
                WHERE HI.IsLocallyEmulated = 0
                AND HI.IsPhysicallyHosted = 0
                AND HI.GameID = '{1}'
                ORDER BY HI.GameId, HR.Name, HI.Status, HI.Id;",
                DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"), game.Id);

            try
            {

                Logger.Instance.Info("--------------------------------------");
                Logger.Instance.Info("Beginning Hosting Instance Query");
                Logger.Instance.Info("--------------------------------------");
                Logger.Instance.Info("");
                Result = DBManager.Instance.Query(Datastore.General, query);
                Logger.Instance.Info(String.Format("Succesfully retrieved Hosting Instances  : {0}", Result.Rows.Count));
                if (Result.Rows.Count > 0)
                {
                    List<string> InsertStatements = new List<string>();
                    foreach (DataRow row in Result.Rows)
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append(@"INSERT INTO `HostingInstance_ComputeRaw`
                    (`ID`,
                    `RecordTimestamp`,
                    `HostingInstance_Id`,
                    `HostingInstance_MachineId`,
                    `HostingInstance_IP`,
                    `HostingInstance_CreationTime`,
                    `HostingInstance_StartTime`,
                    `HostingInstance_LastUpdateTime`,
                    `HostingInstance_GameId`,
                    `RegionHostingConfiguration_Id`,
                    `RegionHostingConfiguration_MinimumNumInstances`,
                    `RegionHostingConfiguration_MaximumFreeInstances`,
                    `HostingConfiguration_Name`,
                    `HostingRegion_Name`,
                    `GameVersion_Id`,
                    `GameVersion_Major`,
                    `GameVersion_Minor`,
                    `GameVersion_Status`,
                    `GameVersion_Label`,
                    `HostingInstance_Status`,
                    `HostingInstance_Health`,
                    `HostingInstance_MaximumComputeUnits`,
                    `HostingInstance_TotalComputeUnits`,
                    `HostingInstance_CalcTotalComputeUnits`,
                    `HostingInstance_ServersCount`,
                    `HostingInstance_CalcServersCount`,
                    `HostingInstance_AvgComputeUnitsAcrossServers`,
                    `HostingInstance_MaxUserCount`,
                    `HostingInstance_UserCount`) VALUES (");
                        foreach (var item in row.ItemArray)
                        {
                            if (item is DateTime)
                            {
                                DateTime itm = (DateTime)item;
                                sb.Append("'" + itm.ToString("yyyy-MM-dd HH:mm:ss") + "'");
                                sb.Append(",");
                            }
                            else
                            {
                                sb.Append("'" + item.ToString() + "'");
                                sb.Append(",");
                            }

                        }
                        sb.Length--;
                        sb.Append(");");
                        string Insert = sb.ToString();
                        InsertStatements.Add(Insert);

                    }
                    try
                    {
                        MoniverseResponse response = new MoniverseResponse()
                        {
                            Status = "unsent",
                            TimeStamp = DateTime.UtcNow
                        };

                        string shittyWay = string.Join("", InsertStatements);
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("Beginning Insert of Retention Row Batch");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                        }
                        HostingInstances.Service(Service => {
                            Service.Insert(new MoniverseRequest()
                            {
                                TaskName = "Insert",
                                Task = shittyWay,
                                TimeStamp = DateTime.UtcNow
                            });
                        });
                        //int result = DBManager.Instance.Insert(Datastore.Monitoring, shittyWay);
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Green;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("Beginning Insert of Retention Row Batch");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                            Logger.Instance.Info(String.Format("success!! {0} inserted", InsertStatements.Count));
                            Console.ResetColor();
                        }

                    }
                    catch (Exception e)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Logger.Instance.Info(e.Message);
                        Console.ResetColor();
                    }
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(ex.Message, ex.StackTrace);
            }
        }
        public void RecordGameSessionUserStats(GameMonitoringConfig game)
        {
            try
            {
                if (game == null)
                {
                    throw new Exception("GameInfo cannot be null or empty");
                }

                foreach (PrivacyCompareSessionTypes privacyCompare in game.PrivacyCompareSessionTypes)
                {
                    DataTable result = DBManager.Instance.Query(Datastore.General, GetGameSessionUserStatsQueryStr(game.Id, privacyCompare.PublicTypes, privacyCompare.PrivateTypes));

                    if (result.HasRows())
                    {
                        string query = String.Format(
                            @"INSERT INTO GameSessionUserStats
                            (GameId, SessionType, MaxNumPlayers, AvgPlayers, Sessions, PrivateAvgPlayers
                            ,PrivateSessions, TotalAvgPlayers, TotalSessions, RecordTimestamp)
                            VALUES ('{0}', '{1}', {2}, {3}, {4}, {5}, {6}, {7}, {8}, '{9}');",
                            result.Rows[0].Field<string>("GameId"),
                            result.Rows[0].Field<string>("SessionType"),
                            result.Rows[0].Field<int>("MaxNumPlayers"),
                            result.Rows[0].Field<decimal>("AvgPlayers"),
                            result.Rows[0].Field<long>("Sessions"),
                            result.Rows[0].Field<decimal>("PrivateAvgPlayers"),
                            result.Rows[0].Field<long>("PrivateSessions"),
                            result.Rows[0].Field<decimal>("TotalAvgPlayers"),
                            result.Rows[0].Field<long>("TotalSessions"),
                            DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                        try
                        {
                            MoniverseResponse response = new MoniverseResponse()
                            {
                                Status = "unsent",
                                TimeStamp = DateTime.UtcNow
                            };

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Beginning Insert of Game Session User Stats");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                            }
                            Users.Service(Service =>
                            {
                                response = Service.Insert(new MoniverseRequest()
                                {
                                    TaskName = "Insert",
                                    Task = query,
                                    TimeStamp = DateTime.UtcNow
                                });
                            });
                            //int res = DBManager.Instance.Insert(Datastore.Monitoring, query);

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Game Session User Stats success");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                                Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                                Console.ResetColor();
                            }

                        }
                        catch (Exception e)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Logger.Instance.Info(e.Message);
                            Console.ResetColor();
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(String.Format("Game: {0} - {1} | Message: {2}", game.Id, game.Title, ex.Message), ex.StackTrace);
            }
        }
        public void RecordDailyActiveUsers()
        {
            try
            {
                if (dau_nextRecordTime <= DateTime.UtcNow)
                {
                    // Check if global DAU record exists for yesterday
                    string query = CheckStatsRecordExistsQueryStr(Games.EMPTYGAMEID, TYPE_DAU, dau_nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                    int count = DBManager.Instance.QueryForCount(Datastore.Monitoring, query);

                    if (count == 0)
                    {
                        // Get count of global DAU from RecentPlayers
                        query = GetRecentPlayerCountQueryStr(null, dau_nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"), dau_nextRecordTime.AddMinutes(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                        count = DBManager.Instance.QueryForCount(Datastore.General, query);

                        // Insert global DAU record into Monitoring datastore
                        query = InsertStatsRecordQueryStr(Games.EMPTYGAMEID, TYPE_DAU, count, dau_nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                        try
                        {
                            MoniverseResponse response = new MoniverseResponse()
                            {
                                Status = "unsent",
                                TimeStamp = DateTime.UtcNow
                            };

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Beginning DAU INsert Batch");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                            }
                            Users.Service(Service =>
                            {
                                response = Service.Insert(new MoniverseRequest()
                                {
                                    TaskName = "Insert RecordDailyActiveUsers",
                                    Task = query,
                                    TimeStamp = DateTime.UtcNow
                                });
                            });

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("DAU Batch Success");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                                Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                                Logger.Instance.Info("");
                                Console.ResetColor();
                            }

                        }
                        catch (Exception e)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Logger.Instance.Info(e.Message);
                            Console.ResetColor();
                        }
                    }

                    // Increment by a day so the record is only collected once a day after midnight
                    dau_nextRecordTime = dau_nextRecordTime.AddDays(1);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(ex.Message, ex.StackTrace);
            }
        }
        public void RecordActiveUsers(GameMonitoringConfig game)
        {
            try
            {
                if (game == null)
                {
                    throw new Exception("GameInfo cannot be null or empty");
                }

                // Init the session type specific collections
                string[] sessionTypes = game.ActiveUserSessionTypes.ToArray();
                string[] sessionTypeNames = new string[8];
                for (int i = 0; i < 8; i++)
                {
                    if (i < sessionTypes.Count())
                    {
                        sessionTypeNames[i] = sessionTypes[i];
                    }
                    else
                    {
                        sessionTypeNames[i] = String.Empty;
                    }
                }

                // Grab regional counts
                DataTable queryResults = DBManager.Instance.Query(Datastore.General, GetSessionTypeUserCountByRegionQueryStr(game.Id, sessionTypes.ToList()));
                if (queryResults.HasRows())
                {
                    List<RegionSessionTypeCounts> gameSessionUserResults = new List<RegionSessionTypeCounts>();
                    foreach (DataRow row in queryResults.Rows)
                    {
                        gameSessionUserResults.Add(new RegionSessionTypeCounts()
                        {
                            RegionName = row.Field<string>("RegionName"),
                            SessionType = row.Field<string>("SessionType"),
                            Count = (int)row.Field<long>("Count")
                        });
                    }

                    // Grab global playverse game counts
                    int eventListeners = DBManager.Instance.QueryForCount(Datastore.General, GetEventListenersCountQueryStr(game.Id));
                    int titleScreenUsers = eventListeners - gameSessionUserResults.Sum(x => x.Count);
                    int otherSessionTypeUsers = 0;
                    DateTime timestamp = DateTime.UtcNow;

                    // Grab the region counts and insert the region specific metric
                    foreach (IGrouping<string, RegionSessionTypeCounts> region in gameSessionUserResults.GroupBy(x => x.RegionName))
                    {
                        int gameSessionUsers = region.Sum(x => x.Count);
                        int[] sessionTypeUserCounts = new int[8];
                        for (int i = 0; i < 8; i++)
                        {
                            if (sessionTypeNames[i] != String.Empty)
                            {
                                RegionSessionTypeCounts regionSessionType = region.Where(x => x.SessionType == sessionTypeNames[i]).FirstOrDefault();
                                if (regionSessionType != null)
                                {
                                    sessionTypeUserCounts[i] = regionSessionType.Count;
                                }
                            }
                        }

                        // Grab the other session type region count
                        RegionSessionTypeCounts otherRegionSessionType = region.Where(x => x.SessionType == "Other").FirstOrDefault();
                        if (otherRegionSessionType != null)
                        {
                            otherSessionTypeUsers = otherRegionSessionType.Count;
                        }

                        // Store new game user activity record
                        string insertQuery = String.Format(
                            @"INSERT INTO GameUserActivity
                            (GameId, RegionName, RecordTimestamp, GameSessionUsers, EventListeners, TitleScreenUsers, SessionTypeName_0, SessionTypeUsers_0,
                            SessionTypeName_1, SessionTypeUsers_1, SessionTypeName_2, SessionTypeUsers_2, SessionTypeName_3, SessionTypeUsers_3,
                            SessionTypeName_4, SessionTypeUsers_4, SessionTypeName_5, SessionTypeUsers_5, SessionTypeName_6, SessionTypeUsers_6,
                            SessionTypeName_7, SessionTypeUsers_7, SessionTypeUsers_Other)
                            VALUES('{0}','{1}','{2}',{3},{4},{5},'{6}',{7},'{8}',{9},'{10}',{11},'{12}',{13},'{14}',{15},'{16}',{17},'{18}',{19},'{20}',{21}, {22})",
                                    game.Id,
                                    region.Key,
                            //truncated seconds
                                    timestamp.ToString("yyyy-MM-dd HH:mm"),
                                    gameSessionUsers,
                                    eventListeners,
                                    titleScreenUsers,
                                    sessionTypeNames[0],
                                    sessionTypeUserCounts[0],
                                    sessionTypeNames[1],
                                    sessionTypeUserCounts[1],
                                    sessionTypeNames[2],
                                    sessionTypeUserCounts[2],
                                    sessionTypeNames[3],
                                    sessionTypeUserCounts[3],
                                    sessionTypeNames[4],
                                    sessionTypeUserCounts[4],
                                    sessionTypeNames[5],
                                    sessionTypeUserCounts[5],
                                    sessionTypeNames[6],
                                    sessionTypeUserCounts[6],
                                    sessionTypeNames[7],
                                    sessionTypeUserCounts[7],
                                    otherSessionTypeUsers);
                        try
                        {
                            MoniverseResponse response = new MoniverseResponse()
                            {
                                Status = "unsent",
                                TimeStamp = DateTime.UtcNow
                            };

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Beginning Insert of Active Users");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                            }
                            Users.Service(Service =>
                            {
                                response = Service.Insert(new MoniverseRequest()
                                {
                                    TaskName = "Insert RecordActiveUsers",
                                    Task = insertQuery,
                                    TimeStamp = DateTime.UtcNow
                                });
                            });
                            //int result = DBManager.Instance.Insert(Datastore.Monitoring, insertQuery);

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Active User Success");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                                Logger.Instance.Info("Done inserting Retention Row Data.");
                                Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                                Logger.Instance.Info("");
                                Console.ResetColor();
                            }

                        }
                        catch (Exception e)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Logger.Instance.Info(e.Message);
                            Console.ResetColor();
                        }

                    }
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(String.Format("Game: {0} - {1} | Message: {2}", game.Id, game.Title, ex.Message), ex.StackTrace);
            }
        }
        private void RecordLatestTransactions(List<PlayversePurchaseAggregation> aggregations)
        {
            if (aggregations.Count == 0)
            {
                return;
            }
            foreach (List<PlayversePurchaseAggregation> aggregationBatch in aggregations.Batch<PlayversePurchaseAggregation>(1000))
            {
                int listLength = aggregations.Count - 1;
                string InsertStatement = String.Format(
                    @"INSERT INTO {1} (`ID`,`RecordTimestamp`, `GameId`,`Type` , `UserData`, `Category`, `Cost`, `TotalBought`, `TotalCredits`) VALUES {0}",
                    DatabaseUtilities.instance.GenerateInsertValues<PlayversePurchaseAggregation>(aggregationBatch), ECONOMY_TABLE);
                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning RecordPurchaseTransactionAggregation Batch");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }

                    Transactions.Service(service =>
                    {
                        response = service.Insert(new MoniverseRequest()
                        {
                            TaskName = "RecordPurchaseTransactionAggregation Insert",
                            Task = InsertStatement,
                            TimeStamp = DateTime.UtcNow
                        });
                    });
                    //int result = DBManager.Instance.Insert(Datastore.Monitoring, InsertStatement);
                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("RecordPurchaseTransactionAggregation Batch success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }

            }
        }
        private void RecordGameCreditTransactions(List<PlayverseGameCreditTransaction> gameCreditTransactions)
        {
            foreach (List<PlayverseGameCreditTransaction> aggregationBatch in gameCreditTransactions.Batch<PlayverseGameCreditTransaction>(1000))
            {
                string InsertStatement = String.Format(

                  @"INSERT INTO {1} (`RecordTimestamp`,`TransactionId`,`UserId`, `GameId`,`ExternalOnlineService` , `ThirdPartyOrderId`, `Credits`, `PaymentProvider`, `PaymentTransactionId`, `TransactionType`, `CreditPackId`,
                    `UserData`, `Description`, `CostAmount`, `Status`, `CreatedOn`, `UpdatedOn`, `Category`, `ClientKey`) VALUES {0}",
                DatabaseUtilities.instance.GenerateInsertValues<PlayverseGameCreditTransaction>(aggregationBatch), ECONOMY_GAMECREDITTRANSACTIONS_TABLE);

                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning PlayverseGameCreditTransactionAggregation Batch");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }

                    Transactions.Service(service =>
                    {
                        response = service.Insert(new MoniverseRequest()
                        {
                            TaskName = "PlayverseGameCreditTransactionAggregation Insert",
                            Task = InsertStatement,
                            TimeStamp = DateTime.UtcNow
                        });
                    });

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("PlayverseGameCreditTransactionAggregation Batch success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }
            }
        }
        public void UpdateExistingOpenSessionsWithLogoutInfo(HashSet<Logoff> logoffs)
        {
            Logger.Instance.Info("Trying to update existing 'orphaned' user sessionsleft 'open'");
            int updateCount = 0;

            string query = String.Format(@"select * from {0} as GSM WHERE GSM.LogoffTimestamp = '0001-01-01 00:00:00'", USER_SESSION_META_TABLE);
            DataTable NullLogoffTimestampsSinceBOT = new DataTable();
            try
            {
                Logger.Instance.Info("UpdateExistingOpenSessionsWithLogoutInfo");
                NullLogoffTimestampsSinceBOT = DBManager.Instance.Query(Datastore.Monitoring, query);
            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(ex.Message, ex.StackTrace);
                //throw;
            }

            Logger.Instance.Info(String.Format("{0} lonely orphans without logouts", NullLogoffTimestampsSinceBOT.Rows.Count));
            if (NullLogoffTimestampsSinceBOT.Rows.Count > 0)
            {
                List<string> updates = new List<string>();
                foreach (DataRow row in NullLogoffTimestampsSinceBOT.Rows)
                {

                    if (logoffs.Any(x =>
                    {
                        string thisSessionId = row["UserSessionId"].ToString();
                        //Logger.Instance.Info("Comparing {0} => {1}", x.UserSessionId, thisSessionId);
                        return x.UserSessionId == thisSessionId;
                    }))
                    {
                        Logoff match = logoffs.FirstOrDefault(x => x.UserSessionId == row["UserSessionId"].ToString());
                        string UserSessionId = row["UserSessionId"].ToString();
                        string validatedLogoffTimestamp = match.LoginTimestamp.ToString("yyyy-MM-dd HH:mm:ss");

                        long SessionLength = (match.LoginTimestamp - DateTime.Parse(row["LoginTimestamp"].ToString())).Ticks / TimeSpan.TicksPerMillisecond;

                        string updateQuery = String.Format(@"UPDATE {0} WHERE UserSessionId = '{1}' SET LogoffTimestamp = '{2}', SessionLength = {3};",
                            USER_SESSION_META_TABLE, UserSessionId, validatedLogoffTimestamp, SessionLength);
                        updates.Add(updateQuery);
                        updateCount++;
                    }
                }
                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning UpdateExistingOpenSessionsWithLogoutInfo");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }
                    UserSessions.Service(Service =>
                    {
                        response = Service.Update(new UpdateRequest()
                        {
                            TaskName = "UpdateExistingOpenSessionsWithLogoutInfo",
                            Task = updates,
                            TimeStamp = DateTime.UtcNow
                        });
                    });
                    //int result = DBManager.Instance.Update(Datastore.Monitoring, updates);

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("UpdateExistingOpenSessionsWithLogoutInfo success ");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Logger.Instance.Info(String.Format("Updated {0} orphaned Sessions with LogoutTimestamp and Session Length", updateCount));
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }

            }
        }
        public void processLogoffs()
        {
            DateTime lastProcessRecord = GetLastLoginRecordTimestamp();
            HashSet<Logoff> logoffs = ExtractLatestLogoffs(lastProcessRecord);
            Logger.Instance.Info(String.Format("{0} Logoffs Retrieved Successfully {1} - {2}", logoffs.Count, lastProcessRecord.ToString(), DateTime.UtcNow.ToString()));
            if (logoffs.Count > 0)
            {
                List<string> SessionIds = new List<string>();
                StringBuilder sb = new StringBuilder();
                sb.Append("SELECT * from UserSessionMeta where UserSessionId IN (");
                foreach (Logoff logoff in logoffs)
                {
                    sb.AppendFormat("'{0}'", logoff.UserSessionId);
                    sb.Append(",");
                }
                sb.Length--;
                sb.Append(");");
                string query = sb.ToString();
                DataTable LogoffResult = DBManager.Instance.Query(Datastore.Monitoring, query);
                List<string> UpdateStatements = new List<string>();
                if (LogoffResult.HasRows())
                {
                    foreach (DataRow row in LogoffResult.Rows)
                    {
                        long validatedSessionLength = -1;
                        Logoff logofftoUpdate = logoffs.Where(x => x.UserSessionId == row["UserSessionId"].ToString()).FirstOrDefault();
                        DateTime RowLoginTime = DateTime.Parse(row["LoginTimestamp"].ToString());
                        if (logofftoUpdate != null)
                        {
                            long sessionLength = (logofftoUpdate.LogoffTimestamp - RowLoginTime).Ticks / TimeSpan.TicksPerMillisecond;
                            validatedSessionLength = (sessionLength > 0) ? sessionLength : -1;
                        }

                        UpdateStatements.Add(string.Format("UPDATE {0} SET LogoffTimestamp = '{1}', SessionLength = {2} WHERE UserSessionId = '{3}';", USER_SESSION_META_TABLE, logofftoUpdate.LogoffTimestamp.ToString("yyyy/MM/dd HH:mm:ss"), validatedSessionLength, logofftoUpdate.UserSessionId));
                    }
                    MoniverseResponse response = new MoniverseResponse();
                    UserSessions.Service(Service =>

                        response = Service.Update(new UpdateRequest()
                        {
                            Task = UpdateStatements,
                            TaskName = "Update Logoff Batch",
                            TimeStamp = DateTime.UtcNow
                        }));
                }

            }
            else
            {
                Logger.Instance.Info("No Logoffs retrieved");
                return;
            }
        }
        public int InsertLoginSessionMeta(List<UserSessionMeta> sessions)
        {
            UserSessionMeta FirstLoginInBatch = sessions.FirstOrDefault();
            UserSessionMeta LastLoginINBatch = sessions.LastOrDefault();

            if (true)
            {
                foreach (List<UserSessionMeta> UserSessionBatch in sessions.Batch<UserSessionMeta>(500))
                {
                    string InsertStatement = string.Format("INSERT IGNORE INTO {1} (`UserId`, `GameId`,`UserSessionId` , `Platform`, `LoginTimestamp`, `LogoffTimestamp`, `City`, `Country`, `Region`,`Longitude`,`Latitude`, `LocationId`, `SessionLength`, `InstallDateRecord`, `RetentionCohortType`, `RecordDate`) VALUES {0};", DatabaseUtilities.instance.GenerateInsertValues<UserSessionMeta>(UserSessionBatch), USER_SESSION_META_TABLE);
                    int listLength = sessions.Count - 1;

                    try
                    {
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("Beginning Insert of Login Session Meta Batch");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                        }

                        // int result = DBManager.Instance.Insert(Datastore.Monitoring, InsertStatement);
                        MoniverseResponse response = new MoniverseResponse()
                        {
                            Status = "unsent",
                            TimeStamp = DateTime.UtcNow
                        };
                        UserSessions.Service(Service =>
                        {
                            response = Service.Insert(new MoniverseRequest()
                            {
                                TaskName = "InsertLoginSessionMeta",
                                Task = InsertStatement,
                                TimeStamp = DateTime.UtcNow
                            });
                        });
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Green;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("Login Session Meta Batch Success");
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                            Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                            Console.ResetColor();
                        }

                    }
                    catch (Exception e)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Logger.Instance.Info(e.Message);
                        Console.ResetColor();
                    }
                }
            }
            else
            {
                Console.WriteLine(String.Format("Already processed {0} - {1}",
                    FirstLoginInBatch.LoginTimestamp.ToString("yyyy/MM/dd HH:mm:ss"),
                    LastLoginINBatch.LoginTimestamp.ToString("yyyy/MM/dd HH:mm:ss")));
            }

            return 0;
        }
 public MoniverseResponse QueueSize(MoniverseRequest request)
 {
     //_workStack.Execute(() =>
     //{
     //    Logger.Instance.Info(String.Format("Queue Size Request Recieved - {0} - {1}", request.TaskName, request.TimeStamp));
     //});
     MoniverseResponse response = new MoniverseResponse()
     {
         TaskName = "QUEUE SIZE",
         TimeStamp = request.TimeStamp,
         Status = "Success"
     };
     Logger.Instance.Info(response.ToString());
     return response;
 }
        public void UpdateGameSessionMeta(List<GameSessionMeta> CurrentGameSessions, DateTime ProcessDate)
        {
            List<GameMonitoringConfig> games = Games.Instance.GetMonitoredGames();

                //Logger.Instance.Info(String.Format("Beginning {0}", game.Title));
                int RunningGameCounter = 0;
                //List<GameSessionUpdateInfo> CurrentRecords = QueryGameSessionMeta(ProcessDate);
                string query = String.Format("SELECT * FROM {0} WHERE DATE(recordCreated) = '{1}' AND Status <> 2;", GAME_SESSION_META_TABLE, ProcessDate.ToString("yyyy-MM-dd"));
                Logger.Instance.Info(query);
            //#if DEBUG
            //                Debugger.Launch();
            //#endif
                List<GameSessionMeta> GameSessionList = new List<GameSessionMeta>();

                DataTable GameSessionMetaTable = DBManager.Instance.Query(Datastore.Monitoring, query);

                if (GameSessionMetaTable.Rows.Count > 0)
                {
                    List<string> statements = new List<string>();
                    foreach (DataRow row in GameSessionMetaTable.Rows)
                    {
                        GameSessionMeta GameSessionMetaRow = new GameSessionMeta()
                        {
                            RecordCreated = DateTime.Parse(row["RecordCreated"].ToString()),
                            RecordLastUpdateTime = DateTime.Parse(row["RecordLastUpdateTime"].ToString()),
                            GameSessionId = row["GameSessionId"].ToString(),
                            IP = row["IP"].ToString(),
                            Port = Convert.ToInt32(row["Port"]),
                            CreationTime = DateTime.Parse(row["CreationTime"].ToString()),
                            SessionStarted = Convert.ToBoolean(row["SessionStarted"]),
                            GameId = row["GameId"].ToString(),
                            IsLocallyEmulated = Convert.ToBoolean(row["IsLocallyEmulated"]),
                            LastUpdateTime = DateTime.Parse(row["LastUpdateTime"].ToString()),
                            Major = Convert.ToInt32(row["Major"]),
                            Minor = Convert.ToInt32(row["Minor"]),
                            UsersCount = Convert.ToInt32(row["UsersCount"]),
                            SessionTypeId = row["SessionTypeId"].ToString(),
                            SessionTypeFriendly = row["SessionTypeFriendly"].ToString(),
                            Status = Convert.ToInt32(row["Status"]),
                            CurrentRanking = Convert.ToInt32(row["CurrentRanking"]),
                            IsPartySession = Convert.ToBoolean(row["IsPartySession"]),
                            InitiatorUserId = row["InitiatorUserId"].ToString(),
                            IsHosted = Convert.ToBoolean(row["IsHosted"]),
                            SessionMetadata = row["SessionMetadata"].ToString()
                        };

                        string UpdateStatement = String.Format("UPDATE {0} SET RecordLastUpdateTime = '{1}', Status = {2}, IP = '{4}', Port = {5}, LastUpdateTime = '{6}', SessionStarted = {7} WHERE GameSessionId = '{3}'; ",
                            GAME_SESSION_META_TABLE,
                            DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
                            GameSessionMetaRow.Status,
                            GameSessionMetaRow.GameSessionId,
                            GameSessionMetaRow.IP,
                            GameSessionMetaRow.Port,
                            GameSessionMetaRow.LastUpdateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                            (GameSessionMetaRow.SessionStarted == true) ? 1 : 0,
                            GameSessionMetaRow.GameId);
                        //Logger.Instance.Info(UpdateStatement);

                        statements.Add(UpdateStatement);

                        CurrentGameSessions.Remove(GameSessionMetaRow);
                        RunningGameCounter++;
                    }
                    try
                    {
                        Logger.Instance.Info(String.Format("updating {0} statements in {1} batches", statements.Count, statements.Count / 100));
                        foreach (List<string> updateBatch in statements.Batch<string>(1000)) {
                            MoniverseResponse response = new MoniverseResponse()
                            {
                                Status = "unsent",
                                TimeStamp = DateTime.UtcNow
                            };

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Logger.Instance.Info("-----------------------------------------------");
                                Logger.Instance.Info("Beginning Update of Active Sessions (All Games)");
                                Logger.Instance.Info("-----------------------------------------------");
                                Logger.Instance.Info("");
                            }

                            GameSessions.Service(Service =>
                            {
                                Service.Update(new UpdateRequest()
                                {
                                    TaskName = "UpdateGameSessionMeta Update",
                                    Task = updateBatch,
                                    TimeStamp = DateTime.UtcNow
                                });
                            });

                            //int result = DBManager.Instance.Update(Datastore.Monitoring, statements);
                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Active Game Session Update Batch Success");
                                Logger.Instance.Info("--------------------------------------");
                                Console.ResetColor();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Logger.Instance.Info(e.Message);
                        Console.ResetColor();
                    }
                }
        }
        private void RecordPurchaseTransactionAggregation(List<PlayversePurchaseAggregation> aggregations)
        {
            if (aggregations.Count == 0) {
                return;
            }
            foreach (List<PlayversePurchaseAggregation> aggregationBatch in aggregations.Batch<PlayversePurchaseAggregation>(100)) {
                int listLength = aggregations.Count - 1;
                int RowIndex = 0;
                string InsertStatement = "INSERT INTO Economy_PurchaseBreakdownRaw (`ID`,`RecordTimestamp`, `GameId`,`Type` , `UserData`, `Cost`, `TotalBought`, `TotalCredits`) VALUES ";
                foreach (PlayversePurchaseAggregation RowEntry in aggregationBatch)
                {
                    string entry = "(";
                    int propertyCount = RowEntry.GetType().GetProperties().Length - 1;
                    var propertyIndex = 0;
                    foreach (PropertyInfo propertyInfo in RowEntry.GetType().GetProperties())
                    {
                        if (propertyInfo.CanRead)
                        {
                            object property = propertyInfo.GetValue(RowEntry);
                            if (property is DateTime)
                            {
                                entry += "'" + DateTime.Parse(propertyInfo.GetValue(RowEntry).ToString()).ToString("yyyy-MM-dd HH:mm:ss") + "'";
                            }
                            else if (property is string)
                            {
                                entry += "'" + propertyInfo.GetValue(RowEntry).ToString().Replace("'", @"\'") + "'";
                            }
                            else
                            {
                                entry += "'" + propertyInfo.GetValue(RowEntry).ToString() + "'";
                            }

                            if (propertyIndex < propertyCount)
                            {
                                entry += ",";
                            }
                        }
                        propertyIndex++;
                    }
                    entry += ")";
                    InsertStatement += entry;

                    if (RowIndex < listLength)
                    {
                        InsertStatement += ",";
                    }
                    RowIndex++;
                }
                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning RecordPurchaseTransactionAggregation Batch");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }

                    Transactions.Service(service => {
                        response = service.Insert(new MoniverseRequest()
                        {
                        TaskName = "RecordPurchaseTransactionAggregation Insert",
                        Task = InsertStatement,
                        TimeStamp = DateTime.UtcNow
                        });
                    });
                    //int result = DBManager.Instance.Insert(Datastore.Monitoring, InsertStatement);
                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("RecordPurchaseTransactionAggregation Batch success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }

            }
        }
        public void InsertGameSessionMeta(List<GameSessionMeta> CurrentGameSessions)
        {
            List<string> InsertStatements = new List<string>();
            foreach (List<GameSessionMeta> Batch in CurrentGameSessions.Batch<GameSessionMeta>(500))
            {
                MoniverseResponse response = new MoniverseResponse() {
                    Status = "unsent",
                    TimeStamp = DateTime.UtcNow
                };

                string InsertStatement = String.Format(@"INSERT INTO {0}
                                                                (`RecordCreated`,
                                                                `RecordLastUpdateTime`,
                                                                `GameSessionId`,
                                                                `IP`,
                                                                `Port`,
                                                                `CreationTime`,
                                                                `SessionStarted`,
                                                                `GameId`,
                                                                `IsLocallyEmulated`,
                                                                `LastUpdateTime`,
                                                                `Major`,
                                                                `Minor`,
                                                                `UsersCount`,
                                                                `SessionTypeId`,
                                                                `SessionTypeFriendly`,
                                                                `Status`,
                                                                `CurrentRanking`,
                                                                `IsPartySession`,
                                                                `GameSessionRankRangeMin`,
                                                                `GameSessionRankRangeMax`,
                                                                `StartLaunchCountDownTime`,
                                                                `IsPrivateSession`,
                                                                `InitiatorUserId`,
                                                                `IsHosted`,
                                                                `SessionMetadata`) VALUES {1} ON DUPLICATE KEY UPDATE RecordLastUpdateTime = '{2}'", GAME_SESSION_META_TABLE, DatabaseUtilities.instance.GenerateInsertValues<GameSessionMeta>(Batch), DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                try
                {
                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning Insert of Game Sessions Batch");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }
                    GameSessions.Service(Service => {
                        response = Service.Insert(new MoniverseRequest()
                        {
                            TaskName = "Game Sessions Batch Insert",
                            Task = InsertStatement,
                            TimeStamp = DateTime.UtcNow
                        });
                    });
                    //int result = DBManager.Instance.Insert(Datastore.Monitoring, InsertStatement);

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Game Sessions Batch Success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Logger.Instance.Info(String.Format("success!! {0} inserted", Batch.Count()));
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }
            }
        }
        protected void GameSessionUserStats720Migrate()
        {
            string statement = @"-- GameSessionUserStats - 12 hour INTERVAL
            truncate GameSessionUserStats_12hour;
            INSERT INTO GameSessionUserStats_12hour
            SELECT 0,
              GameId,
              SessionType,
              ROUND(AVG(MaxNumPlayers)),
            AVG(AvgPlayers),
            ROUND(AVG(Sessions)),

            AVG(PrivateAvgPlayers),

            ROUND(AVG(PrivateSessions)),

            AVG(TotalAvgPlayers),

            ROUND(AVG(TotalSessions)),
             DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(720 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 720) * 60) + SECOND(RecordTimestamp) SECOND) AS RecordTimestamp
            FROM GameSessionUserStats
            -- WHERE '2015-3-19 00:00:00' > DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(720 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 720) * 60) + SECOND(RecordTimestamp) SECOND)
            GROUP BY GameId,
               SessionType,
            DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(720 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 720) * 60) + SECOND(RecordTimestamp) SECOND)
            ORDER BY DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(720 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 720) * 60) + SECOND(RecordTimestamp) SECOND),
               GameId,
               SessionType;";
            MoniverseResponse response = new MoniverseResponse()
            {
                TaskName = "12 hour GameSessionUserStats Migration",
                Status = "Fail",
                TimeStamp = DateTime.UtcNow
            };
            try
            {
                DataBuilder.Service(Service => {
                    response = Service.Insert(new MoniverseRequest()
                    {
                        TaskName = "12 hour GameSessionUserStats Migration",
                        Task = statement,
                        TimeStamp = DateTime.UtcNow

                    });
                });
            }
            catch (Exception ex)
            {

                Logger.Instance.Info(ex.Message);
            }

            Logger.Instance.Info(response.Status);
        }
        public void RecordActiveUsersInterval(object modVal)
        {
            //#if DEBUG
            //            Debugger.Launch();
            //#endif
            try
            {
                string IntervalTable = "";
                // TODO: insert into correct table based on time interval
                //TODO: based on the modval create an interval range
                // select

                DateTime endDate = DateTime.UtcNow;
                DateTime startDate = endDate.AddMinutes(-(int)modVal);

                switch ((int)modVal)
                {
                    case 5:
                        IntervalTable = "GameUserActivity_5min";
                        break;
                    case 15:
                        IntervalTable = "GameUserActivity_15min";
                        break;
                    case 30:
                        IntervalTable = "GameUserActivity_30min";
                        break;
                    case 60:
                        IntervalTable = "GameUserActivity_hour";
                        break;
                    case 360:
                        IntervalTable = "GameUserActivity_6hour";
                        break;
                    case 720:
                        IntervalTable = "GameUserActivity_12hour";
                        break;
                    case 1440:
                        IntervalTable = "GameUserActivity_24hour";
                        break;
                    default:
                        startDate = endDate;
                        IntervalTable = "GameUserActivity";
                        break;
                }

                string insertQuery = String.Format(
                    @"INSERT INTO {0}
                            (GameId, RegionName, RecordTimestamp, GameSessionUsers, EventListeners, TitleScreenUsers, SessionTypeName_0, SessionTypeUsers_0,
                            SessionTypeName_1, SessionTypeUsers_1, SessionTypeName_2, SessionTypeUsers_2, SessionTypeName_3, SessionTypeUsers_3,
                            SessionTypeName_4, SessionTypeUsers_4, SessionTypeName_5, SessionTypeUsers_5, SessionTypeName_6, SessionTypeUsers_6,
                            SessionTypeName_7, SessionTypeUsers_7, SessionTypeUsers_Other)
                              SELECT GameId,
                              RegionName,
                              '{2}',
                                    ROUND(AVG(GameSessionUsers)),
                                    ROUND(AVG(EventListeners)),
                                    ROUND(AVG(TitleScreenUsers)),
                                    SessionTypeName_0,
                                    ROUND(AVG(SessionTypeUsers_0)),
                                    SessionTypeName_1,
                                    ROUND(AVG(SessionTypeUsers_1)),
                                    SessionTypeName_2,
                                    ROUND(AVG(SessionTypeUsers_2)),
                                    SessionTypeName_3,
                                    ROUND(AVG(SessionTypeUsers_3)),
                                    SessionTypeName_4,
                                    ROUND(AVG(SessionTypeUsers_4)),
                                    SessionTypeName_5,
                                    ROUND(AVG(SessionTypeUsers_5)),
                                    SessionTypeName_6,
                                    ROUND(AVG(SessionTypeUsers_6)),
                              SessionTypeName_7,
                              ROUND(AVG(SessionTypeUsers_7)),
                              ROUND(AVG(SessionTypeUsers_Other))
                            FROM GameUserActivity
                            WHERE RecordTimestamp BETWEEN '{1}' AND '{2}'
                            GROUP BY GameId,
                                     RegionName,
                                    SessionTypeName_0,
                                    SessionTypeName_1,
                                    SessionTypeName_2,
                                    SessionTypeName_3,
                                    SessionTypeName_4,
                                    SessionTypeName_5,
                                    SessionTypeName_6,
                                    SessionTypeName_7;",
                            IntervalTable,
                            startDate.ToString("yyyy-MM-dd HH:mm"),
                            endDate.ToString("yyyy-MM-dd HH:mm"));
            #if DEBUG
                //Debugger.Launch();
            #endif
                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info(String.Format("Beginning insert Game User Activity {0} minute", modVal));
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }
                    Users.Service(Service =>
                    {
                        response = Service.Insert(new MoniverseRequest()
                        {
                            TaskName = "Insert RecordActiveUsersInterval",
                            Task = insertQuery,
                            TimeStamp = DateTime.UtcNow
                        });
                    });
                    //int result = DBManager.Instance.Insert(Datastore.Monitoring, insertQuery);

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info(String.Format("Game User Activity {0} minute success", modVal));
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                        Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Logger.Instance.Info(e.Message);
                    Console.ResetColor();
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(String.Format("Message: {0}", ex.Message), ex.StackTrace);
            }
        }
        protected void GameUserActivity5MinuteMigrate()
        {
            string statement = @"SET SQL_SAFE_UPDATES = 0;
            -- GameSessionUserStats - 5 MIN INTERVAL

            truncate GameUserActivity_5min;
            INSERT INTO GameUserActivity_5min
            SELECT 0,
              GameId,
              RegionName,
              DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(5 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 5) * 60) + SECOND(RecordTimestamp) SECOND) AS RecordTimestamp,
              ROUND(AVG(GameSessionUsers)) as GameSessionUsers,
            ROUND(AVG(EventListeners)) as EventListeners,
            ROUND(AVG(TitleScreenUsers)) as TitleScreenUsers,
            SessionTypeName_0,
            ROUND(AVG(SessionTypeUsers_0)) as SessionTypeUsers_0,
            SessionTypeName_1,
            ROUND(AVG(SessionTypeUsers_1)) as SessionTypeUsers_1,
            SessionTypeName_2,
            ROUND(AVG(SessionTypeUsers_2)) as SessionTypeUsers_2,
            SessionTypeName_3,
            ROUND(AVG(SessionTypeUsers_3)) as SessionTypeUsers_3,
            SessionTypeName_4,
            ROUND(AVG(SessionTypeUsers_4)) as SessionTypeUsers_4,
            SessionTypeName_5,
            ROUND(AVG(SessionTypeUsers_5)) as SessionTypeUsers_5,
            SessionTypeName_6,
            ROUND(AVG(SessionTypeUsers_6)) as SessionTypeUsers_6,
            SessionTypeName_7,
            ROUND(AVG(SessionTypeUsers_7)) SessionTypeUsers_7,
            ROUND(AVG(SessionTypeUsers_Other)) as SessionTypeUsers_Other
            FROM GameUserActivity
            WHERE RecordTimestamp < NOW()
            GROUP BY GameId,
             RegionName,
             DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(5 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 5) * 60) + SECOND(RecordTimestamp) SECOND),
            SessionTypeName_0,
            SessionTypeName_1,
            SessionTypeName_2,
            SessionTypeName_3,
            SessionTypeName_4,
            SessionTypeName_5,
            SessionTypeName_6,
            SessionTypeName_7
            ORDER BY DATE_SUB(RecordTimestamp, INTERVAL (IFNULL(HOUR(RecordTimestamp) % FLOOR(5 / 60), 0) * 60 * 60) + ((MINUTE(RecordTimestamp) % 5) * 60) + SECOND(RecordTimestamp) SECOND) desc,
               GameId;";
            MoniverseResponse response = new MoniverseResponse(){
                TaskName = "5 Minute GameUserActivity Migration",
                Status = "Fail",
                TimeStamp = DateTime.UtcNow
            };
            try
            {
                DataBuilder.Service(Service => {
                    response = Service.Insert(new MoniverseRequest()
                    {
                        TaskName = "5 Minute GameUserActivity Migration",
                        Task = statement,
                        TimeStamp = DateTime.UtcNow

                    });
                });
            }
            catch (Exception ex)
            {

                Logger.Instance.Info(ex.Message);
            }

            Logger.Instance.Info(response.Status);
        }
        public void RecordDailyActiveUsersByGame(GameMonitoringConfig game)
        {
            try
            {
                if (game == null)
                {
                    throw new Exception("GameInfo cannot be null or empty");
                }

                if (!dau_nextGameRecordTime.ContainsKey(game.Id))
                {
                    dau_nextGameRecordTime.TryAdd(game.Id, DateTime.UtcNow.Date);
                }

                DateTime nextRecordTime = dau_nextGameRecordTime[game.Id];

                if (nextRecordTime <= DateTime.UtcNow)
                {
                    // Check if game DAU record exists for yesterday
                    string query = CheckStatsRecordExistsQueryStr(game.Id, TYPE_DAU, nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                    int count = DBManager.Instance.QueryForCount(Datastore.Monitoring, query);

                    if (count == 0)
                    {
                        // Get count of game DAU from RecentPlayers
                        query = GetRecentPlayerCountQueryStr(game.Id, nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"), nextRecordTime.AddMinutes(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                        count = DBManager.Instance.QueryForCount(Datastore.General, query);

                        // Insert game DAU record into Monitoring datastore
                        query = InsertStatsRecordQueryStr(game.Id, TYPE_DAU, count, nextRecordTime.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"));
                        try
                        {
                            MoniverseResponse response = new MoniverseResponse()
                            {
                                Status = "unsent",
                                TimeStamp = DateTime.UtcNow
                            };

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("Beginning Insert of DAU By Game");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                            }
                            Users.Service(Service =>
                            {
                                response = Service.Insert(new MoniverseRequest()
                                {
                                    TaskName = game.ShortTitle + "DAU Insert",
                                    Task = query,
                                    TimeStamp = DateTime.UtcNow
                                });
                            });
                            //int result = DBManager.Instance.Insert(Datastore.Monitoring, query);

                            lock (MoniverseBase.ConsoleWriterLock)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("DAU By Game Success");
                                Logger.Instance.Info("--------------------------------------");
                                Logger.Instance.Info("");
                                Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                                Console.ResetColor();
                            }
                        }
                        catch (Exception e)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Logger.Instance.Info(e.Message);
                            Console.ResetColor();
                        }
                    }

                    // Increment by a day so the record is only collected once a day after midnight
                    dau_nextGameRecordTime[game.Id] = nextRecordTime.AddDays(1);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(String.Format("Game: {0} - {1} | Message: {2}", game.Id, game.Title, ex.Message), ex.StackTrace);
            }
        }
        public void InsertRetentionRow(RetentionRow newday)
        {
            StringBuilder query = new StringBuilder();
            query.Append("INSERT INTO Retention");
            query.AppendFormat("(Date, NewUsers, Logins, " + GenerateDayString(newday) + ") VALUES ('{0}','{1}', '{2}'", newday.date.ToString("yyyy/MM/dd 00:00:00"), newday.installsOnThisDay, newday.loginsOnThisDay);

            for (int i = 1; i <= newday.days.Length - 1; i++)
            {
                query.AppendFormat(",'{0}'", newday.days[i]);
            }
            query.Append(");");
            try
            {

                MoniverseResponse response = new MoniverseResponse()
                {
                    Status = "unsent",
                    TimeStamp = DateTime.UtcNow
                };

                lock (MoniverseBase.ConsoleWriterLock)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("Beginning Insert of Retention Row Batch");
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("");
                }
                Retention.Service(Service => Service.Insert(new MoniverseRequest()
                {
                    TaskName = "Insert Retention Row Batch",
                    Task = query.ToString(),
                    TimeStamp = DateTime.UtcNow
                }));
                //int result = DBManager.Instance.Insert(Datastore.Monitoring, query.ToString());

                lock (MoniverseBase.ConsoleWriterLock)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("Insert Retention Row Batch success");
                    Logger.Instance.Info("--------------------------------------");
                    Logger.Instance.Info("");
                    Logger.Instance.Info("Done inserting Retention Row Data.");
                    Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                    Logger.Instance.Info("");
                    Console.ResetColor();
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.Info(ex.Message);
                //Logger.Instance.Error(ex.Message);
            }
        }
        public void RecordGameSessionUserStatsInterval(object modVal)
        {
            //#if DEBUG
            //            Debugger.Launch();
            //#endif
            List<GameMonitoringConfig> games = Games.Instance.GetMonitoredGames();
            try
            {
                string IntervalTable = "";
                DateTime endDate = DateTime.UtcNow;
                DateTime startDate = endDate.AddMinutes(-(int)modVal);
                switch ((int)modVal)
                {
                    case 5:
                        {
                            endDate = endDate.AddSeconds(-endDate.Second);
                            startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_5min";
                        }
                        break;
                    case 15:
                        {
                            endDate = endDate.AddSeconds(-endDate.Second);
                            startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_15min";
                        }
                        break;
                    case 30:
                        {
                            endDate = endDate.AddSeconds(-endDate.Second);
                            startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_30min";
                        }
                        break;
                    case 60:
                        {
                            //endDate = endDate.AddMinutes(-endDate.Minute);
                            //startDate = startDate.AddMinutes(-startDate.Minute);
                            endDate = endDate.AddSeconds(-endDate.Second);
                            startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_hour";
                        }
                        break;
                    case 360:
                        {
                            //endDate = endDate.AddMinutes(-endDate.Minute);
                            //startDate = startDate.AddMinutes(-startDate.Minute);
                            //endDate = endDate.AddSeconds(-endDate.Second);
                            //startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_6hour";
                        }
                        break;
                    case 720:
                        {
                            //endDate = endDate.AddMinutes(-endDate.Minute);
                            //startDate = startDate.AddMinutes(-startDate.Minute);
                            //endDate = endDate.AddSeconds(-endDate.Second);
                            //startDate = startDate.AddSeconds(-startDate.Second);
                            IntervalTable = "GameSessionUserStats_12hour";
                        }
                        break;
                    case 1440:
                        {
                            endDate = endDate.Subtract(endDate.TimeOfDay);
                            startDate = startDate.Subtract(startDate.TimeOfDay);
                            IntervalTable = "GameSessionUserStats_24hour";
                        }
                        break;
                    default:
                        IntervalTable = "GameSessionUserStats";
                        startDate = endDate;
                        break;
                }

                List<string> queries = new List<string>();

                foreach (GameMonitoringConfig game in games)
                {
                    string query = String.Format(
                     @"INSERT INTO {0}
                            (GameId, SessionType, MaxNumPlayers, AvgPlayers, Sessions, PrivateAvgPlayers
                            ,PrivateSessions, TotalAvgPlayers, TotalSessions, RecordTimestamp)
                            SELECT
                            GameId, SessionType, ROUND(AVG(MaxNumPlayers)), ROUND(AVG(AvgPlayers),2), ROUND(AVG(Sessions)), ROUND(AVG(PrivateAvgPlayers),2)
                            ,ROUND(AVG(PrivateSessions)), ROUND(AVG(TotalAvgPlayers),2), ROUND(AVG(TotalSessions)), '{2}'
                            FROM GameSessionUserStats
                            WHERE RecordTimestamp BETWEEN '{1}' AND '{2}'
                            AND GameId = '{3}'
                            GROUP BY GameId,
                                     SessionType;",
                     IntervalTable,
                     startDate.ToString("yyyy-MM-dd HH:mm"),
                     endDate.ToString("yyyy-MM-dd HH:mm"),
                     game.Id);

                    queries.Add(query);
                    //Logger.Instance.Info(String.Format("query for {0}: \n {1}", game.Id, query));
                }

            #if DEBUG
                //Debugger.Launch();
            #endif
                //Logger.Instance.Info(query);
                try
                {
                    try
                    {
                        MoniverseResponse response = new MoniverseResponse()
                        {
                            Status = "unsent",
                            TimeStamp = DateTime.UtcNow
                        };

                        string shitty = string.Join("", queries);
                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info(String.Format("Beginning Insert of {0}", IntervalTable));
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                        }
                        Users.Service(Service =>
                        {
                            response = Service.Insert(new MoniverseRequest()
                            {
                                TaskName = "Insert RecordGameSessionUserStatsInterval",
                                Task = shitty,
                                TimeStamp = DateTime.UtcNow
                            });
                        });
                        //int result = DBManager.Instance.Insert(Datastore.Monitoring, shitty);

                        lock (MoniverseBase.ConsoleWriterLock)
                        {
                            Console.ForegroundColor = ConsoleColor.Green;
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info(String.Format("{0} success", IntervalTable));
                            Logger.Instance.Info("--------------------------------------");
                            Logger.Instance.Info("");
                            Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                            Console.ResetColor();
                        }

                    }
                    catch (Exception e)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Logger.Instance.Info(e.Message);
                        Console.ResetColor();
                    }

                }
                catch (Exception e)
                {
                    //Moniverse.hasError = true;
                    Logger.Instance.Exception(e.Message, e.StackTrace);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Exception(String.Format("Message: {0}", ex.Message), ex.StackTrace);
            }
        }
        //public void UpdateHostingInstanceMeta(List<HostingInstanceMeta> CurrentHostingInstances, DateTime ProcessDate)
        //{
        //    List<GameMonitoringConfig> games = Games.Instance.GetMonitoredGames();
        //    Logger.Instance.Info("--------------------------------------");
        //    Logger.Instance.Info("Beginning Update of Active Sessions (All Games)");
        //    Logger.Instance.Info("--------------------------------------");
        //    Logger.Instance.Info("");
        //    //Logger.Instance.Info(String.Format("Beginning {0}", game.Title));
        //    int RunningGameCounter = 0;
        //    //List<GameSessionUpdateInfo> CurrentRecords = QueryGameSessionMeta(game.Id, ProcessDate);
        //    string query = String.Format("SELECT * FROM {0} WHERE DATE(recordCreated) = '{1}'", GAME_SESSION_META_TABLE, ProcessDate.ToString("yyyy-MM-dd"));
        //    List<GameSessionUpdateInfo> GameSessionList = new List<GameSessionUpdateInfo>();
        //    DataTable GameSessionMetaTable = DBManager.Instance.Query(Datastore.Monitoring, query);
        //    if (GameSessionMetaTable.Rows.Count > 0)
        //    {
        //        List<string> statements = new List<string>();
        //        foreach (DataRow row in GameSessionMetaTable.Rows)
        //        {
        //            GameSessionUpdateInfo GameSessionMetaRow = new GameSessionUpdateInfo()
        //            {
        //                RecordCreated = DateTime.Parse(row["RecordCreated"].ToString()),
        //                RecordLastUpdateTime = DateTime.Parse(row["RecordLastUpdateTime"].ToString()),
        //                GameSessionId = row["Id"].ToString(),
        //                IP = row["IP"].ToString(),
        //                Port = Convert.ToInt32(row["Port"]),
        //                CreationTime = DateTime.Parse(row["CreationTime"].ToString()),
        //                SessionStarted = Convert.ToBoolean(row["SessionStarted"]),
        //                GameId = row["GameId"].ToString(),
        //                IsLocallyEmulated = Convert.ToBoolean(row["IsLocallyEmulated"]),
        //                LastUpdateTime = DateTime.Parse(row["LastUpdateTime"].ToString()),
        //                Major = Convert.ToInt32(row["Major"]),
        //                Minor = Convert.ToInt32(row["Minor"]),
        //                UsersCount = Convert.ToInt32(row["UsersCount"]),
        //                SessionTypeId = row["SessionTypeId"].ToString(),
        //                SessionTypeFriendly = row["SessionTypeFriendly"].ToString(),
        //                Status = Convert.ToInt32(row["Status"]),
        //                CurrentRanking = Convert.ToInt32(row["CurrentRanking"]),
        //                IsPartySession = Convert.ToBoolean(row["IsPartySession"]),
        //                InitiatorUserId = row["InitiatorUserId"].ToString(),
        //                IsHosted = Convert.ToBoolean(row["IsHosted"]),
        //                SessionMetadata = row["SessionMetadata"].ToString()
        //            };
        //            string UpdateStatement = String.Format("UPDATE {0} SET RecordLastUpdateTime = '{1}', Status = {2}, IP = '{4}', Port = {5}, LastUpdateTime = '{6}', SessionStarted = {7} WHERE GameSessionId = '{3}' and GameId = '{7}'; ",
        //                HOSTING_INSTANCE_META_TABLE, DateTime.UtcNow, GameSessionMetaRow.Status, GameSessionMetaRow.GameSessionId, GameSessionMetaRow.IP, GameSessionMetaRow.Port, GameSessionMetaRow.LastUpdateTime, GameSessionMetaRow.SessionStarted, GameSessionMetaRow.GameId);
        //            statements.Add(UpdateStatement);
        //            CurrentGameSessions.Remove(GameSessionMetaRow);
        //            RunningGameCounter++;
        //        }
        //        try
        //        {
        //            Logger.Instance.Info(String.Format("updating {0} statements", statements.Count));
        //            DBManager.Instance.Update(Datastore.Monitoring, statements);
        //        }
        //        catch (Exception ex)
        //        {
        //            Logger.Instance.Exception(ex.Message, ex.StackTrace);
        //            Retry.Do(() =>
        //            {
        //                Logger.Instance.Info(String.Format("retry {0} statements", statements.Count));
        //                DBManager.Instance.Update(Datastore.Monitoring, statements);
        //            }, TimeSpan.FromSeconds(10), 5);
        //        }
        //    }
        //    Logger.Instance.Info(String.Format("Updated {1} running sessions", RunningGameCounter));
        //}
        public void InsertHostingInstanceMeta(List<HostingInstanceMeta> CurrentHostingInstances, DateTime ProcessDate)
        {
            //there aren't currently going to be this many instances running, but this at least forces an upper limit to a batch size by convention
            // only 500 will ever be processed at once, so that's a thing -- PJ
            foreach (List<HostingInstanceMeta> Batch in CurrentHostingInstances.Batch<HostingInstanceMeta>(500))
            {
                string InsertStatement = String.Format(@"INSERT INTO {0}
                                                                (`RecordTimestamp`,
                                                                `HostingInstance_Id`,
                                                                `HostingInstance_MachineId`,
                                                                `HostingInstance_IP`,
                                                                `HostingInstance_CreationTime`,
                                                                `HostingInstance_StartTime`,
                                                                `HostingInstance_LastUpdateTime`,
                                                                `HostingInstance_GameId`,
                                                                `RegionHostingConfiguration_Id`,
                                                                `RegionHostingConfiguration_MinimumNumInstances`,
                                                                `RegionHostingConfiguration_MaximumFreeInstances`,
                                                                `HostingConfiguration_Name`,
                                                                `HostingRegion_Name`,
                                                                `GameVersion_Id`,
                                                                `GameVersion_Major`,
                                                                `GameVersion_Minor`,
                                                                `GameVersion_Status`,
                                                                `GameVersion_Label`,
                                                                `HostingInstance_Status`,
                                                                `HostingInstance_Health`,
                                                                `HostingInstance_MaximumComputeUnits`,
                                                                `HostingInstance_TotalComputeUnits`,
                                                                `HostingInstance_CalcTotalComputeUnits`,
                                                                `HostingInstance_ServersCount`,
                                                                `HostingInstance_CalcServersCount`,
                                                                `HostingInstance_AvgComputeUnitsAcrossServers`,
                                                                `HostingInstance_MaxUserCount`,
                                                                `HostingInstance_UserCount`) VALUES {1}", HOSTING_INSTANCE_META_TABLE, DatabaseUtilities.instance.GenerateInsertValues<HostingInstanceMeta>(Batch));
                try
                {
                    MoniverseResponse response = new MoniverseResponse()
                    {
                        Status = "unsent",
                        TimeStamp = DateTime.UtcNow
                    };

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Beginning Insert of Hosting Instances Batch");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("");
                    }

                    HostingInstances.Service(Service => Service.Insert(new MoniverseRequest()
                    {
                        TaskName = "Hosting Instance Insert",
                        Task = InsertStatement,
                        TimeStamp = DateTime.UtcNow

                    }));

                    lock (MoniverseBase.ConsoleWriterLock)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info("Hosting Instance Batch Success");
                        Logger.Instance.Info("--------------------------------------");
                        Logger.Instance.Info(String.Format("Inserted {0} Hosting Instances", Batch.Count));
                        Logger.Instance.Info(String.Format("success!! {0}", response.Status));
                        Logger.Instance.Info("");
                        Console.ResetColor();
                    }

                }
                catch (Exception ex)
                {
                    Logger.Instance.Exception(ex.Message, ex.StackTrace);
                }
            }
        }