public override bool Equals(object obj)
            {
                if (obj == null)
                {
                    return(false);
                }
                ServerStatsJson objAsServerStatsJson = obj as ServerStatsJson;

                if (objAsServerStatsJson == null)
                {
                    return(false);
                }
                return(this.AverageMatchesPerDay == objAsServerStatsJson.AverageMatchesPerDay &&
                       this.AveragePopulation == objAsServerStatsJson.AveragePopulation &&
                       this.MaximumMatchesPerDay == objAsServerStatsJson.MaximumMatchesPerDay &&
                       this.MaximumPopulation == objAsServerStatsJson.MaximumPopulation &&
                       this.TotalMatchesPlayed == objAsServerStatsJson.TotalMatchesPlayed &&
                       this.Top5GameModes.SequenceEqual(objAsServerStatsJson.Top5GameModes) &&
                       this.Top5Maps.SequenceEqual(objAsServerStatsJson.Top5Maps));
            }
        /// <summary>
        /// Returns <see cref="ApiResponse"/> with string representation of <see cref="ServerStatsJson"/> in body.
        /// </summary>
        /// <param name="endpoint"></param>
        /// <returns></returns>
        public ApiResponse GetStats(string endpoint)
        {
            using (var context = new GameStatsDbDataContext())
            {
                int server_id = (from server in context.Servers
                                 where server.endpoint == endpoint
                                 select server.id).FirstOrDefault();
                // server_id is identity (1,1), so if server_id is 0 <=> there is no server with such endpoint
                if (server_id == 0)
                {
                    return(new ApiResponse(System.Net.HttpStatusCode.NotFound));
                }

                var matchesOnCurrentServer =
                    context.Matches
                    .Where(match => match.server_id == server_id);

                ServerStatsJson result = new ServerStatsJson();
                result.TotalMatchesPlayed =
                    matchesOnCurrentServer.Count();
                if (result.TotalMatchesPlayed == 0)
                {
                    // trivial stats
                    return(new ApiResponse(
                               body: JsonConvert.SerializeObject(ServerStatsJson.Trivial())));
                }

                var matchesPerDay =
                    (from match in matchesOnCurrentServer
                     group match by match.timestamp_day into matchGroup
                     //group by constant to use 2 aggregates
                     group matchGroup by 1 into matchGroup
                     select new
                {
                    maximum = matchGroup.Max
                                  (m => m.Count()),
                    average = matchGroup.Average
                                  (m => m.Count())
                })
                    .First();
                result.MaximumMatchesPerDay =
                    matchesPerDay.maximum;
                result.AverageMatchesPerDay =
                    matchesPerDay.average;

                result.MaximumPopulation =
                    matchesOnCurrentServer
                    .Select(match => match.players_count)
                    .Max();
                result.AveragePopulation =
                    matchesOnCurrentServer
                    .Select(match => match.players_count)
                    .Average();

                result.Top5GameModes =
                    (from match in matchesOnCurrentServer
                     group match by match.gm_id into matchGroup
                     orderby matchGroup.Count() descending
                     join gm in context.GameModes
                     on matchGroup.Key equals gm.id
                     select gm.name)
                    .Take(5).ToList();
                result.Top5Maps =
                    (from match in matchesOnCurrentServer
                     group match by match.map_id into matchGroup
                     orderby matchGroup.Count() descending
                     join map in context.Maps
                     on matchGroup.Key equals map.id
                     select map.name)
                    .Take(5).ToList();
                return(new ApiResponse(
                           body: JsonConvert.SerializeObject(result)));
            }
        }