Merge 2.3 into 2.4-pr
This commit is contained in:
commit
2b8d8fc4b7
@ -6,7 +6,7 @@ namespace IW4MAdmin.Application.API.GameLogServer
|
|||||||
[Header("User-Agent", "IW4MAdmin-RestEase")]
|
[Header("User-Agent", "IW4MAdmin-RestEase")]
|
||||||
public interface IGameLogServer
|
public interface IGameLogServer
|
||||||
{
|
{
|
||||||
[Get("log/{path}")]
|
[Get("log/{path}/{key}")]
|
||||||
Task<LogInfo> Log([Path] string path);
|
Task<LogInfo> Log([Path] string path, [Path] string key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,7 @@ namespace IW4MAdmin.Application.API.GameLogServer
|
|||||||
public int Length { get; set; }
|
public int Length { get; set; }
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public string Data { get; set; }
|
public string Data { get; set; }
|
||||||
|
[JsonProperty("next_key")]
|
||||||
|
public string NextKey { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||||
|
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||||
<TieredCompilation>true</TieredCompilation>
|
<TieredCompilation>true</TieredCompilation>
|
||||||
<AssemblyVersion>2.2.8.1</AssemblyVersion>
|
<AssemblyVersion>2.2.8.1</AssemblyVersion>
|
||||||
<FileVersion>2.2.8.1</FileVersion>
|
<FileVersion>2.2.8.1</FileVersion>
|
||||||
|
@ -42,8 +42,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_server.Logger.WriteWarning($"Failed to update log event for {_server.EndPoint}");
|
_server.Logger.WriteWarning($"Failed to update log event for {_server.EndPoint}");
|
||||||
_server.Logger.WriteDebug($"Exception: {e.Message}");
|
_server.Logger.WriteDebug(e.GetExceptionInfo());
|
||||||
_server.Logger.WriteDebug($"StackTrace: {e.StackTrace}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
readonly IGameLogServer Api;
|
readonly IGameLogServer Api;
|
||||||
readonly string logPath;
|
readonly string logPath;
|
||||||
private bool? ignoreBots;
|
private bool? ignoreBots;
|
||||||
|
private string lastKey = "next";
|
||||||
|
|
||||||
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
|
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
|
||||||
{
|
{
|
||||||
@ -30,12 +31,12 @@ namespace IW4MAdmin.Application.IO
|
|||||||
|
|
||||||
public long Length => -1;
|
public long Length => -1;
|
||||||
|
|
||||||
public int UpdateInterval => 550;
|
public int UpdateInterval => 250;
|
||||||
|
|
||||||
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||||
{
|
{
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
server.Logger.WriteDebug($"Begin reading from http log");
|
server.Logger.WriteDebug($"Begin reading from http log at {DateTime.Now.Millisecond}");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!ignoreBots.HasValue)
|
if (!ignoreBots.HasValue)
|
||||||
@ -45,72 +46,79 @@ namespace IW4MAdmin.Application.IO
|
|||||||
|
|
||||||
var events = new List<GameEvent>();
|
var events = new List<GameEvent>();
|
||||||
string b64Path = logPath;
|
string b64Path = logPath;
|
||||||
var response = await Api.Log(b64Path);
|
var response = await Api.Log(b64Path, lastKey);
|
||||||
|
lastKey = response.NextKey;
|
||||||
|
|
||||||
if (!response.Success)
|
if (!response.Success && string.IsNullOrEmpty(lastKey))
|
||||||
{
|
{
|
||||||
server.Logger.WriteError($"Could not get log server info of {logPath}/{b64Path} ({server.LogPath})");
|
server.Logger.WriteError($"Could not get log server info of {logPath}/{b64Path} ({server.LogPath})");
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse each line
|
else if (response.Data != null)
|
||||||
foreach (string eventLine in response.Data.Split(Environment.NewLine))
|
|
||||||
{
|
{
|
||||||
if (eventLine.Length > 0)
|
// parse each line
|
||||||
|
foreach (string eventLine in response.Data.Split(Environment.NewLine))
|
||||||
{
|
{
|
||||||
try
|
if (eventLine.Length > 0)
|
||||||
{
|
{
|
||||||
var gameEvent = Parser.GenerateGameEvent(eventLine);
|
try
|
||||||
// we don't want to add the event if ignoreBots is on and the event comes from a bot
|
|
||||||
if (!ignoreBots.Value || (ignoreBots.Value && !((gameEvent.Origin?.IsBot ?? false) || (gameEvent.Target?.IsBot ?? false))))
|
|
||||||
{
|
{
|
||||||
gameEvent.Owner = server;
|
var gameEvent = Parser.GenerateGameEvent(eventLine);
|
||||||
|
// we don't want to add the event if ignoreBots is on and the event comes from a bot
|
||||||
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Origin) == GameEvent.EventRequiredEntity.Origin && gameEvent.Origin.NetworkId != 1)
|
if (!ignoreBots.Value || (ignoreBots.Value && !((gameEvent.Origin?.IsBot ?? false) || (gameEvent.Target?.IsBot ?? false))))
|
||||||
{
|
{
|
||||||
gameEvent.Origin = server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin?.NetworkId);
|
gameEvent.Owner = server;
|
||||||
}
|
|
||||||
|
|
||||||
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Target) == GameEvent.EventRequiredEntity.Target)
|
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Origin) == GameEvent.EventRequiredEntity.Origin && gameEvent.Origin.NetworkId != 1)
|
||||||
{
|
{
|
||||||
gameEvent.Target = server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target?.NetworkId);
|
gameEvent.Origin = server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin?.NetworkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameEvent.Origin != null)
|
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Target) == GameEvent.EventRequiredEntity.Target)
|
||||||
{
|
{
|
||||||
gameEvent.Origin.CurrentServer = server;
|
gameEvent.Target = server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target?.NetworkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameEvent.Target != null)
|
if (gameEvent.Origin != null)
|
||||||
{
|
{
|
||||||
gameEvent.Target.CurrentServer = server;
|
gameEvent.Origin.CurrentServer = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
events.Add(gameEvent);
|
if (gameEvent.Target != null)
|
||||||
}
|
{
|
||||||
|
gameEvent.Target.CurrentServer = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.Add(gameEvent);
|
||||||
|
}
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
server.Logger.WriteDebug($"Parsed event with id {gameEvent.Id} from http");
|
server.Logger.WriteDebug($"Parsed event with id {gameEvent.Id} from http");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
|
||||||
if (!ignoreBots.Value)
|
|
||||||
{
|
{
|
||||||
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
|
if (!ignoreBots.Value)
|
||||||
|
{
|
||||||
|
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
|
||||||
|
server.Logger.WriteDebug(eventLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
server.Logger.WriteWarning("Could not properly parse remote event line");
|
||||||
|
server.Logger.WriteDebug(e.Message);
|
||||||
server.Logger.WriteDebug(eventLine);
|
server.Logger.WriteDebug(eventLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
server.Logger.WriteWarning("Could not properly parse remote event line");
|
|
||||||
server.Logger.WriteDebug(e.Message);
|
|
||||||
server.Logger.WriteDebug(eventLine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG == true
|
||||||
|
server.Logger.WriteDebug($"End reading from http log at {DateTime.Now.Millisecond}");
|
||||||
|
#endif
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application
|
namespace IW4MAdmin.Application
|
||||||
{
|
{
|
||||||
@ -54,9 +55,9 @@ namespace IW4MAdmin.Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(string msg, LogType type)
|
async Task Write(string msg, LogType type)
|
||||||
{
|
{
|
||||||
OnLogWriting.Wait();
|
await OnLogWriting.WaitAsync();
|
||||||
|
|
||||||
string stringType = type.ToString();
|
string stringType = type.ToString();
|
||||||
|
|
||||||
@ -73,14 +74,14 @@ namespace IW4MAdmin.Application
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
|
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
|
||||||
Console.WriteLine(LogLine);
|
Console.WriteLine(LogLine);
|
||||||
File.AppendAllText(FileName, LogLine + Environment.NewLine);
|
await File.AppendAllTextAsync(FileName, $"{LogLine}{Environment.NewLine}");
|
||||||
Debug.WriteLine(msg);
|
//Debug.WriteLine(msg);
|
||||||
#else
|
#else
|
||||||
if (type == LogType.Error || type == LogType.Verbose)
|
if (type == LogType.Error || type == LogType.Verbose)
|
||||||
{
|
{
|
||||||
Console.WriteLine(LogLine);
|
Console.WriteLine(LogLine);
|
||||||
}
|
}
|
||||||
File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}");
|
await File.AppendAllTextAsync(FileName, $"{LogLine}{Environment.NewLine}");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
class LogReader(object):
|
class LogReader(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -8,7 +10,7 @@ class LogReader(object):
|
|||||||
# (if the time between checks is greater, ignore ) - in seconds
|
# (if the time between checks is greater, ignore ) - in seconds
|
||||||
self.max_file_time_change = 60
|
self.max_file_time_change = 60
|
||||||
|
|
||||||
def read_file(self, path):
|
def read_file(self, path, retrieval_key):
|
||||||
# this removes old entries that are no longer valid
|
# this removes old entries that are no longer valid
|
||||||
try:
|
try:
|
||||||
self._clear_old_logs()
|
self._clear_old_logs()
|
||||||
@ -22,57 +24,95 @@ class LogReader(object):
|
|||||||
|
|
||||||
# prevent traversing directories
|
# prevent traversing directories
|
||||||
if re.search('r^.+\.\.\\.+$', path):
|
if re.search('r^.+\.\.\\.+$', path):
|
||||||
return False
|
return self._generate_bad_response()
|
||||||
|
|
||||||
# must be a valid log path and log file
|
# must be a valid log path and log file
|
||||||
if not re.search(r'^.+[\\|\/](.+)[\\|\/].+.log$', path):
|
if not re.search(r'^.+[\\|\/](.+)[\\|\/].+.log$', path):
|
||||||
return False
|
return self._generate_bad_response()
|
||||||
|
|
||||||
# get the new file size
|
# get the new file size
|
||||||
new_file_size = self.file_length(path)
|
new_file_size = self.file_length(path)
|
||||||
|
|
||||||
# the log size was unable to be read (probably the wrong path)
|
# the log size was unable to be read (probably the wrong path)
|
||||||
if new_file_size < 0:
|
if new_file_size < 0:
|
||||||
return False
|
return self._generate_bad_response()
|
||||||
|
|
||||||
# this is the first time the log has been requested
|
next_retrieval_key = self._generate_key()
|
||||||
if path not in self.log_file_sizes:
|
|
||||||
self.log_file_sizes[path] = {
|
#print('next key is %s' % next_retrieval_key)
|
||||||
'length' : new_file_size,
|
|
||||||
'read': time.time()
|
# this is the first time the key has been requested, so we need to the next one
|
||||||
|
if retrieval_key not in self.log_file_sizes:
|
||||||
|
print ('requested key %s does not exist' % retrieval_key)
|
||||||
|
self.log_file_sizes[next_retrieval_key] = {
|
||||||
|
'size': new_file_size,
|
||||||
|
'length': 0,
|
||||||
|
'read': time.time(),
|
||||||
|
'next_key': next_retrieval_key, # the key that IW4MAdmin should request next
|
||||||
|
'previous_key': retrieval_key # the old key that can be deleted next
|
||||||
}
|
}
|
||||||
return ''
|
return {
|
||||||
|
'content': None,
|
||||||
|
'next_key': next_retrieval_key
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
current_log_info = self.log_file_sizes[retrieval_key]
|
||||||
|
|
||||||
# grab the previous values
|
# grab the previous values
|
||||||
last_length = self.log_file_sizes[path]['length']
|
last_length = current_log_info['length']
|
||||||
file_size_difference = new_file_size - last_length
|
last_size = current_log_info['size']
|
||||||
|
file_size_difference = new_file_size - last_size
|
||||||
|
|
||||||
|
#print('generating info for next key %s' % next_retrieval_key)
|
||||||
|
|
||||||
# update the new size and actually read the data
|
# update the new size and actually read the data
|
||||||
self.log_file_sizes[path] = {
|
self.log_file_sizes[next_retrieval_key] = {
|
||||||
'length': new_file_size,
|
'size' : new_file_size,
|
||||||
'read': time.time()
|
'length': last_length,
|
||||||
|
'read': time.time(),
|
||||||
|
'next_key': next_retrieval_key,
|
||||||
|
'previous_key': retrieval_key
|
||||||
}
|
}
|
||||||
|
|
||||||
new_log_info = self.get_file_lines(path, file_size_difference)
|
if current_log_info['previous_key'] in self.log_file_sizes.keys():
|
||||||
return new_log_info
|
#print('deleting old key %s' % current_log_info['previous_key'])
|
||||||
|
del self.log_file_sizes[current_log_info['previous_key']]
|
||||||
|
|
||||||
def get_file_lines(self, path, length):
|
#print('reading %i bytes starting at %i' % (file_size_difference, last_size))
|
||||||
|
|
||||||
|
new_log_info = self.get_file_lines(path, last_size, file_size_difference)
|
||||||
|
return {
|
||||||
|
'content': new_log_info,
|
||||||
|
'next_key': next_retrieval_key
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_file_lines(self, path, start_position, length_to_read):
|
||||||
try:
|
try:
|
||||||
file_handle = open(path, 'rb')
|
file_handle = open(path, 'rb')
|
||||||
file_handle.seek(-length, 2)
|
file_handle.seek(start_position)
|
||||||
file_data = file_handle.read(length)
|
file_data = file_handle.read(length_to_read)
|
||||||
file_handle.close()
|
file_handle.close()
|
||||||
# using ignore errors omits the pesky 0xb2 bytes we're reading in for some reason
|
# using ignore errors omits the pesky 0xb2 bytes we're reading in for some reason
|
||||||
return file_data.decode('utf-8', errors='ignore')
|
return file_data.decode('utf-8', errors='ignore')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('could not read the log file at {0}, wanted to read {1} bytes'.format(path, length))
|
print('could not read the log file at {0}, wanted to read {1} bytes'.format(path, length_to_read))
|
||||||
print(e)
|
print(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _clear_old_logs(self):
|
def _clear_old_logs(self):
|
||||||
expired_logs = [path for path in self.log_file_sizes if int(time.time() - self.log_file_sizes[path]['read']) > self.max_file_time_change]
|
expired_logs = [path for path in self.log_file_sizes if int(time.time() - self.log_file_sizes[path]['read']) > self.max_file_time_change]
|
||||||
for log in expired_logs:
|
for key in expired_logs:
|
||||||
print('removing expired log {0}'.format(log))
|
print('removing expired log with key {0}'.format(key))
|
||||||
del self.log_file_sizes[log]
|
del self.log_file_sizes[key]
|
||||||
|
|
||||||
|
def _generate_bad_response(self):
|
||||||
|
return {
|
||||||
|
'content': None,
|
||||||
|
'next_key': None
|
||||||
|
}
|
||||||
|
|
||||||
|
def _generate_key(self):
|
||||||
|
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
|
||||||
|
|
||||||
def file_length(self, path):
|
def file_length(self, path):
|
||||||
try:
|
try:
|
||||||
|
@ -3,12 +3,14 @@ from GameLogServer.log_reader import reader
|
|||||||
from base64 import urlsafe_b64decode
|
from base64 import urlsafe_b64decode
|
||||||
|
|
||||||
class LogResource(Resource):
|
class LogResource(Resource):
|
||||||
def get(self, path):
|
def get(self, path, retrieval_key):
|
||||||
path = urlsafe_b64decode(path).decode('utf-8')
|
path = urlsafe_b64decode(path).decode('utf-8')
|
||||||
log_info = reader.read_file(path)
|
log_info = reader.read_file(path, retrieval_key)
|
||||||
|
content = log_info['content']
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'success' : log_info is not False,
|
'success' : content is not None,
|
||||||
'length': 0 if log_info is False else len(log_info),
|
'length': 0 if content is None else len(content),
|
||||||
'data': log_info
|
'data': content,
|
||||||
|
'next_key': log_info['next_key']
|
||||||
}
|
}
|
||||||
|
@ -10,5 +10,5 @@ def init():
|
|||||||
log = logging.getLogger('werkzeug')
|
log = logging.getLogger('werkzeug')
|
||||||
log.setLevel(logging.ERROR)
|
log.setLevel(logging.ERROR)
|
||||||
api = Api(app)
|
api = Api(app)
|
||||||
api.add_resource(LogResource, '/log/<string:path>')
|
api.add_resource(LogResource, '/log/<string:path>/<string:retrieval_key>')
|
||||||
#api.add_resource(RestartResource, '/restart')
|
#api.add_resource(RestartResource, '/restart')
|
||||||
|
@ -858,7 +858,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
#region INDIVIDUAL_SERVER_PERFORMANCE
|
#region INDIVIDUAL_SERVER_PERFORMANCE
|
||||||
// get the client ranking for the current server
|
// get the client ranking for the current server
|
||||||
int individualClientRanking = await ctx.Set<EFRating>()
|
int individualClientRanking = await ctx.Set<EFRating>()
|
||||||
.Where(GetRankingFunc(clientStats.ServerId))
|
.Where(GetRankingFunc(clientStats.ServerId))
|
||||||
// ignore themselves in the query
|
// ignore themselves in the query
|
||||||
.Where(c => c.RatingHistory.ClientId != client.ClientId)
|
.Where(c => c.RatingHistory.ClientId != client.ClientId)
|
||||||
|
@ -21,13 +21,7 @@ namespace Stats.Models
|
|||||||
.HasColumnName("EFClientStatistics_ServerId");
|
.HasColumnName("EFClientStatistics_ServerId");
|
||||||
|
|
||||||
builder.Entity<EFRating>()
|
builder.Entity<EFRating>()
|
||||||
.HasIndex(p => p.Performance);
|
.HasIndex(p => new { p.Performance, p.Ranking, p.When });
|
||||||
|
|
||||||
builder.Entity<EFRating>()
|
|
||||||
.HasIndex(p => p.Ranking);
|
|
||||||
|
|
||||||
builder.Entity<EFRating>()
|
|
||||||
.HasIndex(p => p.When);
|
|
||||||
|
|
||||||
builder.Entity<EFClientMessage>()
|
builder.Entity<EFClientMessage>()
|
||||||
.HasIndex(p => p.TimeSent);
|
.HasIndex(p => p.TimeSent);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Console;
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
@ -20,6 +22,11 @@ namespace SharedLibraryCore.Database
|
|||||||
public DbSet<EFMeta> EFMeta { get; set; }
|
public DbSet<EFMeta> EFMeta { get; set; }
|
||||||
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
|
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
private static readonly ILoggerFactory _loggerFactory = new LoggerFactory(new[] {
|
||||||
|
new ConsoleLoggerProvider((category, level) => level == LogLevel.Information, true)
|
||||||
|
});
|
||||||
|
|
||||||
static string _ConnectionString;
|
static string _ConnectionString;
|
||||||
static string _provider;
|
static string _provider;
|
||||||
private static readonly string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins";
|
private static readonly string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins";
|
||||||
@ -103,6 +110,13 @@ namespace SharedLibraryCore.Database
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
optionsBuilder.UseLoggerFactory(_loggerFactory)
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
|
.EnableSensitiveDataLogging();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
699
SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.Designer.cs
generated
Normal file
699
SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.Designer.cs
generated
Normal file
@ -0,0 +1,699 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using SharedLibraryCore.Database;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20190725000309_AlterEFRatingIndex")]
|
||||||
|
partial class AlterEFRatingIndex
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SnapshotId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentSessionLength");
|
||||||
|
|
||||||
|
b.Property<double>("CurrentStrain");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentViewAngleId");
|
||||||
|
|
||||||
|
b.Property<int>("Deaths");
|
||||||
|
|
||||||
|
b.Property<double>("Distance");
|
||||||
|
|
||||||
|
b.Property<double>("EloRating");
|
||||||
|
|
||||||
|
b.Property<int>("HitDestinationId");
|
||||||
|
|
||||||
|
b.Property<int>("HitLocation");
|
||||||
|
|
||||||
|
b.Property<int>("HitOriginId");
|
||||||
|
|
||||||
|
b.Property<int>("HitType");
|
||||||
|
|
||||||
|
b.Property<int>("Hits");
|
||||||
|
|
||||||
|
b.Property<int>("Kills");
|
||||||
|
|
||||||
|
b.Property<int>("LastStrainAngleId");
|
||||||
|
|
||||||
|
b.Property<double>("RecoilOffset");
|
||||||
|
|
||||||
|
b.Property<double>("SessionAngleOffset");
|
||||||
|
|
||||||
|
b.Property<double>("SessionSPM");
|
||||||
|
|
||||||
|
b.Property<int>("SessionScore");
|
||||||
|
|
||||||
|
b.Property<double>("StrainAngleBetween");
|
||||||
|
|
||||||
|
b.Property<int>("TimeSinceLastEvent");
|
||||||
|
|
||||||
|
b.Property<int>("WeaponId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("SnapshotId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentViewAngleId");
|
||||||
|
|
||||||
|
b.HasIndex("HitDestinationId");
|
||||||
|
|
||||||
|
b.HasIndex("HitOriginId");
|
||||||
|
|
||||||
|
b.HasIndex("LastStrainAngleId");
|
||||||
|
|
||||||
|
b.ToTable("EFACSnapshot");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("KillId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("AttackerId");
|
||||||
|
|
||||||
|
b.Property<int>("Damage");
|
||||||
|
|
||||||
|
b.Property<int?>("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.Property<int>("DeathType");
|
||||||
|
|
||||||
|
b.Property<double>("Fraction");
|
||||||
|
|
||||||
|
b.Property<int>("HitLoc");
|
||||||
|
|
||||||
|
b.Property<bool>("IsKill");
|
||||||
|
|
||||||
|
b.Property<int?>("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.Property<int>("Map");
|
||||||
|
|
||||||
|
b.Property<long>("ServerId");
|
||||||
|
|
||||||
|
b.Property<int>("VictimId");
|
||||||
|
|
||||||
|
b.Property<int?>("ViewAnglesVector3Id");
|
||||||
|
|
||||||
|
b.Property<double>("VisibilityPercentage");
|
||||||
|
|
||||||
|
b.Property<int>("Weapon");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("KillId");
|
||||||
|
|
||||||
|
b.HasIndex("AttackerId");
|
||||||
|
|
||||||
|
b.HasIndex("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("VictimId");
|
||||||
|
|
||||||
|
b.HasIndex("ViewAnglesVector3Id");
|
||||||
|
|
||||||
|
b.ToTable("EFClientKills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("MessageId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<long>("ServerId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeSent");
|
||||||
|
|
||||||
|
b.HasKey("MessageId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("TimeSent");
|
||||||
|
|
||||||
|
b.ToTable("EFClientMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("RatingHistoryId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.HasKey("RatingHistoryId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("EFClientRatingHistory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<long>("ServerId");
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<double>("AverageRecoilOffset");
|
||||||
|
|
||||||
|
b.Property<int>("Deaths");
|
||||||
|
|
||||||
|
b.Property<double>("EloRating");
|
||||||
|
|
||||||
|
b.Property<int>("Kills");
|
||||||
|
|
||||||
|
b.Property<double>("MaxStrain");
|
||||||
|
|
||||||
|
b.Property<double>("RollingWeightedKDR");
|
||||||
|
|
||||||
|
b.Property<double>("SPM");
|
||||||
|
|
||||||
|
b.Property<double>("Skill");
|
||||||
|
|
||||||
|
b.Property<int>("TimePlayed");
|
||||||
|
|
||||||
|
b.Property<double>("VisionAverage");
|
||||||
|
|
||||||
|
b.HasKey("ClientId", "ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFClientStatistics");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HitLocationCountId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId")
|
||||||
|
.HasColumnName("EFClientStatistics_ClientId");
|
||||||
|
|
||||||
|
b.Property<int>("HitCount");
|
||||||
|
|
||||||
|
b.Property<float>("HitOffsetAverage");
|
||||||
|
|
||||||
|
b.Property<int>("Location");
|
||||||
|
|
||||||
|
b.Property<float>("MaxAngleDistance");
|
||||||
|
|
||||||
|
b.Property<long>("ServerId")
|
||||||
|
.HasColumnName("EFClientStatistics_ServerId");
|
||||||
|
|
||||||
|
b.HasKey("HitLocationCountId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId", "ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFHitLocationCounts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("RatingId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ActivityAmount");
|
||||||
|
|
||||||
|
b.Property<bool>("Newest");
|
||||||
|
|
||||||
|
b.Property<double>("Performance");
|
||||||
|
|
||||||
|
b.Property<int>("Ranking");
|
||||||
|
|
||||||
|
b.Property<int>("RatingHistoryId");
|
||||||
|
|
||||||
|
b.Property<long?>("ServerId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("RatingId");
|
||||||
|
|
||||||
|
b.HasIndex("RatingHistoryId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("Performance", "Ranking", "When");
|
||||||
|
|
||||||
|
b.ToTable("EFRating");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("ServerId");
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<string>("EndPoint");
|
||||||
|
|
||||||
|
b.Property<int?>("GameName");
|
||||||
|
|
||||||
|
b.Property<int>("Port");
|
||||||
|
|
||||||
|
b.HasKey("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFServers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("StatisticId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<long>("ServerId");
|
||||||
|
|
||||||
|
b.Property<long>("TotalKills");
|
||||||
|
|
||||||
|
b.Property<long>("TotalPlayTime");
|
||||||
|
|
||||||
|
b.HasKey("StatisticId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFServerStatistics");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AliasId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<int?>("IPAddress");
|
||||||
|
|
||||||
|
b.Property<int>("LinkId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(24);
|
||||||
|
|
||||||
|
b.HasKey("AliasId");
|
||||||
|
|
||||||
|
b.HasIndex("IPAddress");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.HasIndex("Name");
|
||||||
|
|
||||||
|
b.ToTable("EFAlias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AliasLinkId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.HasKey("AliasLinkId");
|
||||||
|
|
||||||
|
b.ToTable("EFAliasLinks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ChangeHistoryId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<string>("Comment")
|
||||||
|
.HasMaxLength(128);
|
||||||
|
|
||||||
|
b.Property<string>("CurrentValue");
|
||||||
|
|
||||||
|
b.Property<int>("OriginEntityId");
|
||||||
|
|
||||||
|
b.Property<string>("PreviousValue");
|
||||||
|
|
||||||
|
b.Property<int>("TargetEntityId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeChanged");
|
||||||
|
|
||||||
|
b.Property<int>("TypeOfChange");
|
||||||
|
|
||||||
|
b.HasKey("ChangeHistoryId");
|
||||||
|
|
||||||
|
b.ToTable("EFChangeHistory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ClientId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("AliasLinkId");
|
||||||
|
|
||||||
|
b.Property<int>("Connections");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentAliasId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FirstConnection");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastConnection");
|
||||||
|
|
||||||
|
b.Property<int>("Level");
|
||||||
|
|
||||||
|
b.Property<bool>("Masked");
|
||||||
|
|
||||||
|
b.Property<long>("NetworkId");
|
||||||
|
|
||||||
|
b.Property<string>("Password");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt");
|
||||||
|
|
||||||
|
b.Property<int>("TotalConnectionTime");
|
||||||
|
|
||||||
|
b.HasKey("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("AliasLinkId");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentAliasId");
|
||||||
|
|
||||||
|
b.HasIndex("NetworkId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("EFClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("MetaId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Created");
|
||||||
|
|
||||||
|
b.Property<string>("Extra");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(32);
|
||||||
|
|
||||||
|
b.Property<DateTime>("Updated");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("MetaId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("Key");
|
||||||
|
|
||||||
|
b.ToTable("EFMeta");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("PenaltyId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<string>("AutomatedOffense");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expires");
|
||||||
|
|
||||||
|
b.Property<bool>("IsEvadedOffense");
|
||||||
|
|
||||||
|
b.Property<int>("LinkId");
|
||||||
|
|
||||||
|
b.Property<int>("OffenderId");
|
||||||
|
|
||||||
|
b.Property<string>("Offense")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("PunisherId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("PenaltyId");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.HasIndex("OffenderId");
|
||||||
|
|
||||||
|
b.HasIndex("PunisherId");
|
||||||
|
|
||||||
|
b.ToTable("EFPenalties");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Vector3Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("EFACSnapshotSnapshotId");
|
||||||
|
|
||||||
|
b.Property<float>("X");
|
||||||
|
|
||||||
|
b.Property<float>("Y");
|
||||||
|
|
||||||
|
b.Property<float>("Z");
|
||||||
|
|
||||||
|
b.HasKey("Vector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("EFACSnapshotSnapshotId");
|
||||||
|
|
||||||
|
b.ToTable("Vector3");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentViewAngleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HitDestinationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HitOriginId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LastStrainAngleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AttackerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("VictimId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ViewAnglesVector3Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
|
||||||
|
.WithMany("HitLocations")
|
||||||
|
.HasForeignKey("ClientId", "ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
|
||||||
|
.WithMany("Ratings")
|
||||||
|
.HasForeignKey("RatingHistoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||||
|
.WithMany("Children")
|
||||||
|
.HasForeignKey("LinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AliasLinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentAliasId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany("Meta")
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||||
|
.WithMany("ReceivedPenalties")
|
||||||
|
.HasForeignKey("LinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
|
||||||
|
.WithMany("ReceivedPenalties")
|
||||||
|
.HasForeignKey("OffenderId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
|
||||||
|
.WithMany("AdministeredPenalties")
|
||||||
|
.HasForeignKey("PunisherId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
|
||||||
|
.WithMany("PredictedViewAngles")
|
||||||
|
.HasForeignKey("EFACSnapshotSnapshotId");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Migrations
|
||||||
|
{
|
||||||
|
public partial class AlterEFRatingIndex : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_EFRating_Performance",
|
||||||
|
table: "EFRating");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_EFRating_Ranking",
|
||||||
|
table: "EFRating");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_EFRating_When",
|
||||||
|
table: "EFRating");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EFRating_Performance_Ranking_When",
|
||||||
|
table: "EFRating",
|
||||||
|
columns: new[] { "Performance", "Ranking", "When" });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_EFRating_Performance_Ranking_When",
|
||||||
|
table: "EFRating");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EFRating_Performance",
|
||||||
|
table: "EFRating",
|
||||||
|
column: "Performance");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EFRating_Ranking",
|
||||||
|
table: "EFRating",
|
||||||
|
column: "Ranking");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EFRating_When",
|
||||||
|
table: "EFRating",
|
||||||
|
column: "When");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -266,15 +266,11 @@ namespace SharedLibraryCore.Migrations
|
|||||||
|
|
||||||
b.HasKey("RatingId");
|
b.HasKey("RatingId");
|
||||||
|
|
||||||
b.HasIndex("Performance");
|
|
||||||
|
|
||||||
b.HasIndex("Ranking");
|
|
||||||
|
|
||||||
b.HasIndex("RatingHistoryId");
|
b.HasIndex("RatingHistoryId");
|
||||||
|
|
||||||
b.HasIndex("ServerId");
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
b.HasIndex("When");
|
b.HasIndex("Performance", "Ranking", "When");
|
||||||
|
|
||||||
b.ToTable("EFRating");
|
b.ToTable("EFRating");
|
||||||
});
|
});
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||||
|
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||||
<TieredCompilation>true</TieredCompilation>
|
<TieredCompilation>true</TieredCompilation>
|
||||||
<LangVersion>7.1</LangVersion>
|
<LangVersion>7.1</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user