2019-12-02 16:52:36 -05:00
|
|
|
|
using IW4MAdmin.Plugins.Stats;
|
|
|
|
|
using IW4MAdmin.Plugins.Stats.Helpers;
|
2019-02-26 22:25:27 -05:00
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
2018-06-05 17:31:36 -04:00
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2018-05-28 21:30:31 -04:00
|
|
|
|
using SharedLibraryCore;
|
2019-02-25 20:36:10 -05:00
|
|
|
|
using SharedLibraryCore.Dtos;
|
2020-08-20 11:38:11 -04:00
|
|
|
|
using SharedLibraryCore.Dtos.Meta.Responses;
|
2019-12-02 16:52:36 -05:00
|
|
|
|
using SharedLibraryCore.Interfaces;
|
2020-08-20 11:38:11 -04:00
|
|
|
|
using Stats.Dtos;
|
2020-05-22 21:29:41 -04:00
|
|
|
|
using StatsWeb.Extensions;
|
2018-05-28 21:30:31 -04:00
|
|
|
|
using System;
|
2018-06-05 17:31:36 -04:00
|
|
|
|
using System.Linq;
|
2018-05-28 21:30:31 -04:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2019-12-02 16:52:36 -05:00
|
|
|
|
namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers
|
2018-05-28 21:30:31 -04:00
|
|
|
|
{
|
|
|
|
|
public class StatsController : BaseController
|
|
|
|
|
{
|
2020-05-22 21:29:41 -04:00
|
|
|
|
private readonly ILogger _logger;
|
2019-12-02 16:52:36 -05:00
|
|
|
|
private readonly IManager _manager;
|
2020-08-20 11:38:11 -04:00
|
|
|
|
private readonly IResourceQueryHelper<ChatSearchQuery, MessageResponse> _chatResourceQueryHelper;
|
2020-05-22 21:29:41 -04:00
|
|
|
|
private readonly ITranslationLookup _translationLookup;
|
2019-12-02 16:52:36 -05:00
|
|
|
|
|
2020-08-20 11:38:11 -04:00
|
|
|
|
public StatsController(ILogger logger, IManager manager, IResourceQueryHelper<ChatSearchQuery, MessageResponse> resourceQueryHelper,
|
2020-05-22 21:29:41 -04:00
|
|
|
|
ITranslationLookup translationLookup) : base(manager)
|
2019-12-02 16:52:36 -05:00
|
|
|
|
{
|
2020-05-22 21:29:41 -04:00
|
|
|
|
_logger = logger;
|
2019-12-02 16:52:36 -05:00
|
|
|
|
_manager = manager;
|
2020-05-22 21:29:41 -04:00
|
|
|
|
_chatResourceQueryHelper = resourceQueryHelper;
|
|
|
|
|
_translationLookup = translationLookup;
|
2019-12-02 16:52:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-28 21:30:31 -04:00
|
|
|
|
[HttpGet]
|
2019-02-26 22:25:27 -05:00
|
|
|
|
public IActionResult TopPlayersAsync()
|
2018-05-28 21:30:31 -04:00
|
|
|
|
{
|
2019-03-24 22:34:20 -04:00
|
|
|
|
ViewBag.Title = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_TITLE"];
|
|
|
|
|
ViewBag.Description = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_DESC"];
|
2019-12-02 16:52:36 -05:00
|
|
|
|
ViewBag.Servers = _manager.GetServers().Select(_server => new ServerInfo() { Name = _server.Hostname, ID = _server.EndPoint });
|
2020-08-17 22:21:11 -04:00
|
|
|
|
ViewBag.Localization = _translationLookup;
|
2018-05-28 21:30:31 -04:00
|
|
|
|
|
2019-02-26 22:25:27 -05:00
|
|
|
|
return View("Index");
|
2018-05-28 21:30:31 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpGet]
|
2019-02-26 22:25:27 -05:00
|
|
|
|
public async Task<IActionResult> GetTopPlayersAsync(int count, int offset, long? serverId = null)
|
2018-05-28 21:30:31 -04:00
|
|
|
|
{
|
2019-02-26 22:25:27 -05:00
|
|
|
|
// this prevents empty results when we really want aggregate
|
|
|
|
|
if (serverId == 0)
|
|
|
|
|
{
|
|
|
|
|
serverId = null;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-02 16:52:36 -05:00
|
|
|
|
var server = _manager.GetServers().FirstOrDefault(_server => _server.EndPoint == serverId);
|
2019-02-26 22:25:27 -05:00
|
|
|
|
|
|
|
|
|
if (server != null)
|
|
|
|
|
{
|
2019-08-23 19:34:31 -04:00
|
|
|
|
serverId = StatManager.GetIdForServer(server);
|
2019-02-26 22:25:27 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var results = await Plugin.Manager.GetTopStats(offset, count, serverId);
|
|
|
|
|
|
|
|
|
|
// this returns an empty result so we know to stale the loader
|
|
|
|
|
if (results.Count == 0 && offset > 0)
|
|
|
|
|
{
|
|
|
|
|
return Ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return View("Components/TopPlayers/_List", results);
|
|
|
|
|
}
|
2018-05-28 21:30:31 -04:00
|
|
|
|
}
|
2018-06-05 17:31:36 -04:00
|
|
|
|
|
|
|
|
|
[HttpGet]
|
2020-08-20 11:38:11 -04:00
|
|
|
|
public async Task<IActionResult> GetMessageAsync(string serverId, long when)
|
2018-06-05 17:31:36 -04:00
|
|
|
|
{
|
2019-04-08 21:31:32 -04:00
|
|
|
|
var whenTime = DateTime.FromFileTimeUtc(when);
|
|
|
|
|
var whenUpper = whenTime.AddMinutes(5);
|
|
|
|
|
var whenLower = whenTime.AddMinutes(-5);
|
2018-06-05 17:31:36 -04:00
|
|
|
|
|
2020-08-20 11:38:11 -04:00
|
|
|
|
var messages = await _chatResourceQueryHelper.QueryResource(new ChatSearchQuery()
|
2018-06-05 17:31:36 -04:00
|
|
|
|
{
|
2020-08-20 11:38:11 -04:00
|
|
|
|
ServerId = serverId,
|
|
|
|
|
SentBefore = whenUpper,
|
|
|
|
|
SentAfter = whenLower
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return View("_MessageContext", messages.Results);
|
2018-06-05 17:31:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 21:29:41 -04:00
|
|
|
|
[HttpGet("Message/Find")]
|
2020-08-20 11:38:11 -04:00
|
|
|
|
public async Task<IActionResult> FindMessage([FromQuery] string query)
|
2020-05-22 21:29:41 -04:00
|
|
|
|
{
|
|
|
|
|
ViewBag.Localization = _translationLookup;
|
|
|
|
|
ViewBag.EnableColorCodes = _manager.GetApplicationSettings().Configuration().EnableColorCodes;
|
|
|
|
|
ViewBag.Query = query;
|
|
|
|
|
ViewBag.QueryLimit = 100;
|
|
|
|
|
ViewBag.Title = _translationLookup["WEBFRONT_STATS_MESSAGES_TITLE"];
|
|
|
|
|
ViewBag.Error = null;
|
|
|
|
|
ViewBag.IsFluid = true;
|
|
|
|
|
ChatSearchQuery searchRequest = null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
searchRequest = query.ParseSearchInfo(int.MaxValue, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (ArgumentException e)
|
|
|
|
|
{
|
|
|
|
|
_logger.WriteWarning($"Could not parse chat message search query - {query}");
|
|
|
|
|
_logger.WriteDebug(e.GetExceptionInfo());
|
|
|
|
|
ViewBag.Error = e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (FormatException e)
|
|
|
|
|
{
|
|
|
|
|
_logger.WriteWarning($"Could not parse chat message search query filter format - {query}");
|
|
|
|
|
_logger.WriteDebug(e.GetExceptionInfo());
|
|
|
|
|
ViewBag.Error = e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var result = searchRequest != null ? await _chatResourceQueryHelper.QueryResource(searchRequest) : null;
|
|
|
|
|
return View("Message/Find", result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpGet("Message/FindNext")]
|
2020-08-20 11:38:11 -04:00
|
|
|
|
public async Task<IActionResult> FindNextMessages([FromQuery] string query, [FromQuery] int count, [FromQuery] int offset)
|
2020-05-22 21:29:41 -04:00
|
|
|
|
{
|
|
|
|
|
ChatSearchQuery searchRequest;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
searchRequest = query.ParseSearchInfo(count, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (ArgumentException e)
|
|
|
|
|
{
|
|
|
|
|
_logger.WriteWarning($"Could not parse chat message search query - {query}");
|
|
|
|
|
_logger.WriteDebug(e.GetExceptionInfo());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (FormatException e)
|
|
|
|
|
{
|
|
|
|
|
_logger.WriteWarning($"Could not parse chat message search query filter format - {query}");
|
|
|
|
|
_logger.WriteDebug(e.GetExceptionInfo());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var result = await _chatResourceQueryHelper.QueryResource(searchRequest);
|
|
|
|
|
return PartialView("Message/_Item", result.Results);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-05 17:31:36 -04:00
|
|
|
|
[HttpGet]
|
2018-09-04 22:07:34 -04:00
|
|
|
|
[Authorize]
|
2019-08-06 14:36:37 -04:00
|
|
|
|
public async Task<IActionResult> GetAutomatedPenaltyInfoAsync(int penaltyId)
|
2018-06-05 17:31:36 -04:00
|
|
|
|
{
|
2018-09-04 22:07:34 -04:00
|
|
|
|
using (var ctx = new SharedLibraryCore.Database.DatabaseContext(true))
|
2018-06-05 17:31:36 -04:00
|
|
|
|
{
|
2019-08-06 14:36:37 -04:00
|
|
|
|
var penalty = await ctx.Penalties
|
|
|
|
|
.Select(_penalty => new { _penalty.OffenderId, _penalty.PenaltyId, _penalty.When, _penalty.AutomatedOffense })
|
|
|
|
|
.FirstOrDefaultAsync(_penalty => _penalty.PenaltyId == penaltyId);
|
2019-03-31 20:56:31 -04:00
|
|
|
|
|
2019-12-25 22:05:57 -05:00
|
|
|
|
if (penalty == null)
|
|
|
|
|
{
|
|
|
|
|
return NotFound();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-25 13:05:12 -05:00
|
|
|
|
// todo: this can be optimized
|
2019-12-03 17:27:26 -05:00
|
|
|
|
var iqSnapshotInfo = ctx.Set<Stats.Models.EFACSnapshot>()
|
2019-08-06 14:36:37 -04:00
|
|
|
|
.Where(s => s.ClientId == penalty.OffenderId)
|
2018-06-05 17:31:36 -04:00
|
|
|
|
.Include(s => s.LastStrainAngle)
|
|
|
|
|
.Include(s => s.HitOrigin)
|
|
|
|
|
.Include(s => s.HitDestination)
|
|
|
|
|
.Include(s => s.CurrentViewAngle)
|
|
|
|
|
.Include(s => s.PredictedViewAngles)
|
2019-09-09 18:40:04 -04:00
|
|
|
|
.ThenInclude(_angles => _angles.Vector)
|
2018-09-04 22:07:34 -04:00
|
|
|
|
.OrderBy(s => s.When)
|
2019-03-31 20:56:31 -04:00
|
|
|
|
.ThenBy(s => s.Hits);
|
|
|
|
|
|
2019-08-06 14:36:37 -04:00
|
|
|
|
var penaltyInfo = await iqSnapshotInfo.ToListAsync();
|
2019-03-31 20:56:31 -04:00
|
|
|
|
|
2019-08-06 14:36:37 -04:00
|
|
|
|
if (penaltyInfo.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
return View("_PenaltyInfo", penaltyInfo);
|
|
|
|
|
}
|
2018-06-05 17:31:36 -04:00
|
|
|
|
|
2019-08-06 14:36:37 -04:00
|
|
|
|
// we want to show anything related to the automated offense
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return View("_MessageContext", new[]
|
|
|
|
|
{
|
|
|
|
|
new ChatInfo()
|
|
|
|
|
{
|
|
|
|
|
ClientId = penalty.OffenderId,
|
|
|
|
|
Message = penalty.AutomatedOffense,
|
|
|
|
|
Time = penalty.When
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-06-05 17:31:36 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-28 21:30:31 -04:00
|
|
|
|
}
|
|
|
|
|
}
|